CPUSpeed/main.cpp

272 lines
8.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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;
}