// CPUSpeed v1.20 // 17/11/2021 // https://t.me/ssleg © 2020 – 2021 #include #include #include #include #include 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; }