CPUSpeed/main.cpp

272 lines
8.4 KiB
C++
Raw Normal View History

2023-06-27 11:05:00 +03:00
// CPUSpeed v1.20
// 17/11/2021
// https://t.me/ssleg © 2020 2021
#include <iostream>
#include <random>
#include <thread>
#include <sys/sysinfo.h>
#include <mutex>
using namespace std;
const int max_gen_value = 2147483647;
const int MB = 1048576;
mutex print_lock;
double cpu_time() {
clockid_t id = CLOCK_THREAD_CPUTIME_ID;
struct timespec ts{};
clock_gettime(id, &ts);
return (double) ts.tv_sec + (double) ts.tv_nsec / 1000000000.0;
}
void rnd_generator(int th_num, int start, int end, float *array, double *times) {
print_lock.lock();
cout << "поток #" << th_num << " " << start << " " << end << endl;
print_lock.unlock();
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dist(0, max_gen_value);
double start_time = cpu_time();
int interval = (end - start) / 5;
double cycle_time;
double old_cycle_time = start_time;
int i;
for (i = start; i < end; i++) {
array[i] = dist(gen);
if (i % interval == 0 and i > 0) {
cycle_time = cpu_time();
print_lock.lock();
printf("поток #%u, %uМб. время %3.5f сек.\n", th_num, i / MB * 16, cycle_time - old_cycle_time);
print_lock.unlock();
old_cycle_time = cycle_time;
}
}
double end_time = cpu_time();
double th_time = end_time - start_time;
print_lock.lock();
printf("поток #%u, всего времени генератора %3.5f сек.\n", th_num, th_time);
print_lock.unlock();
times[th_num] = th_time;
}
void zero_fill(int th_num, int arr_size, double *array, double *times) {
print_lock.lock();
cout << "поток #" << th_num << ", zero_fill." << endl;
print_lock.unlock();
double start_time = cpu_time();
int interval = arr_size / 5;
double cycle_time;
double old_cycle_time = start_time;
int i;
for (i = 0; i < arr_size; i++) {
array[i] = 0;
if (i % interval == 0 and i > 0) {
cycle_time = cpu_time();
print_lock.lock();
printf("поток #%u, %uМб. время %3.5f сек.\n", th_num, i / MB * 16, cycle_time - old_cycle_time);
print_lock.unlock();
old_cycle_time = cycle_time;
}
}
double end_time = cpu_time();
double th_time = end_time - start_time;
print_lock.lock();
printf("поток #%u, всего времени стирания %3.5f сек.\n", th_num, th_time);
print_lock.unlock();
times[th_num] = th_time;
}
void compute(int th_num, int start, int end, const float *a, const float *b, double *rez, double *times) {
int i;
double r1, r2, r3, r4, r5, r6, r7, r8;
double start_time = cpu_time();
double end_time;
for (i = start; i < end - 7; i++) {
r1 = a[i] * b[i];
r2 = a[i] * b[i + 1];
r3 = a[i] * b[i + 2];
r4 = a[i] * b[i + 3];
r5 = a[i] * b[i + 4];
r6 = a[i] * b[i + 5];
r7 = a[i] * b[i + 6];
r8 = a[i] * b[i + 7];
rez[i] = (r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8) / 8;
}
end_time = cpu_time();
times[th_num] = end_time - start_time;
}
void thread_starter(int start_num, int th_number, int arr_size, float *array, thread *threads, double *times) {
int i;
int start, end, block;
block = arr_size / th_number;
for (i = 0; i < th_number; i++) {
start = i * block;
if (i + 1 != th_number) {
end = (i + 1) * block;
} else {
end = arr_size;
}
threads[start_num + i] = thread(rnd_generator, start_num + i, start, end, array, times);
}
}
int input_integer(int low, int high) {
bool flag = false;
int input;
do {
cin >> input;
if (input > low and input <= high) {
flag = true;
} else {
cin.clear();
cin.ignore(32767, '\n');
cout << "неверный ввод, попробуйте снова:";
}
} while (!flag);
cin.ignore(32767, '\n');
return input;
}
int main() {
struct sysinfo info{};
sysinfo(&info);
long total_ram = info.totalram;
long free_ram = info.freeram;
int max_array_size = int(double(free_ram) / 16 / MB);
cout << "-----------------------------------------------" << endl;
cout << "CPUSpeed v1.20" << endl;
cout << "-----------------------------------------------" << endl;
printf("оперативной памяти всего - %3.1f Gb\n", float(total_ram) / 1024 / MB);
printf("свободно - %3.2f Gb\n", float(free_ram) / 1024 / MB);
int cores_count = int(thread::hardware_concurrency());
printf("введите количество потоков [1-%u]:", cores_count);
int threads = input_integer(0, cores_count);
printf("введите размер массива данных [8-%u]:", max_array_size);
int arr = input_integer(7, max_array_size);
cout << "введите количество тестов [1-1000]:";
int test_count = input_integer(0, 1000);
const int arr_size = arr * MB;
const float real_mem_size = float(arr_size) * 16 / 1024 / MB;
auto *a = new float[arr_size];
auto *b = new float[arr_size];
auto *rez = new double[arr_size];
printf("запуск бенчмарка. реальный необходимый обьем RAM - %3.1f Gb\n", real_mem_size);
int i;
auto *thr = new thread[threads];
auto *times = new double[threads];
auto *sum_times = new double[threads];
auto *sum_flops = new double[threads];
if (threads == 1) {
thread_starter(0, threads, arr_size, a, thr, times);
thr[0].join();
thread_starter(0, threads, arr_size, b, thr, times);
thr[0].join();
thr[0] = thread(zero_fill, 0, arr_size, rez, times);
thr[0].join();
}
if (threads == 2) {
thread_starter(0, 1, arr_size, a, thr, times);
thread_starter(1, 1, arr_size, b, thr, times);
thr[0].join();
thr[1].join();
thr[0] = thread(zero_fill, 0, arr_size, rez, times);
thr[0].join();
}
if (threads > 2) {
int a_threads = (threads - 1) / 2;
int b_threads = threads - 1 - a_threads;
thread_starter(0, a_threads, arr_size, a, thr, times);
thread_starter(a_threads, b_threads, arr_size, b, thr, times);
thr[threads - 1] = thread(zero_fill, threads - 1, arr_size, rez, times);
for (i = 0; i < threads; i++) {
thr[i].join();
}
}
for (i = 0; i < threads; i++) {
printf("поток %u, время - %3.5f сек.\n", i, times[i]);
}
int k, start, end, block;
int64_t operations;
double flops;
block = arr_size / threads;
for (k = 0; k < test_count; k++) {
cout << "запуск теста #" << k + 1 << endl;
for (i = 0; i < threads; i++) {
start = i * block;
if (i + 1 != threads) {
end = (i + 1) * block;
} else {
end = arr_size;
}
thr[i] = thread(compute, i, start, end, a, b, rez, times);
}
for (i = 0; i < threads; i++) {
thr[i].join();
}
for (i = 0; i < threads; i++) {
sum_times[i] += times[i];
operations = (int64_t(end) - int64_t(start) - 7) * 16;
flops = (operations / times[i]) / 1000000;
sum_flops[i] += flops;
printf("поток %u, время - %3.5f сек. (%3.2f MFlops)\n", i, times[i], flops);
}
}
cout << "-----------------------------------------------" << endl;
cout << "Итоговая производительность." << endl;
cout << "потоков - " << threads << ", размер массива - " << arr << ", тестов - " << test_count << endl;
cout << "-----------------------------------------------" << endl;
double medium_speed, medium_flops, sys_flops;
sys_flops = 0;
for (i = 0; i < threads; i++) {
medium_speed = sum_times[i] / test_count;
medium_flops = sum_flops[i] / test_count;
sys_flops += medium_flops;
printf("поток %u, время - %3.5f сек. (%3.2f MFlops)\n", i, medium_speed, medium_flops);
}
cout << "-----------------------------------------------" << endl;
printf("Система всего - %3.2f MFlops\n", sys_flops);
cout << "-----------------------------------------------" << endl;
free(a);
free(b);
free(rez);
return 0;
}