commit 4f74c84a3d2aa6ac9bb9167636138a973943ef6a Author: anton Date: Tue Jun 27 11:05:00 2023 +0300 main Initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d216954 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) +project(CPUSpeed) + +set(CMAKE_CXX_STANDARD 14) +SET(CMAKE_CXX_FLAGS -pthread) + +add_executable(CPUSpeed main.cpp) \ No newline at end of file diff --git a/CPUSpeed b/CPUSpeed new file mode 100644 index 0000000..2d7b619 Binary files /dev/null and b/CPUSpeed differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..48c5b06 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright © 2020-2021 https://t.me/ssleg + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..edb2d34 --- /dev/null +++ b/README.MD @@ -0,0 +1,21 @@ +### Тест скорости процессора и памяти на linux-vps. + +Занимается бессмысленным перемножением массивов случайных чисел, для определения скорости процессора и памяти. +Поддерживает любое количество потоков, но не больше чем есть у процессора. +Автоматически определяет свободную память системы. + +Для запуска положите в директорию home, дайте права на исполнение и выполните в консоли +`cd /home` +`./CPUSpeed` + +Пара референсных значений: + +Intel Core i7-4771 (2 ядра, размер массива 100) - 10 440 MFlops +Intel Xeon Gold 6240 (2 ядра, размер массива 100) - 12 120 MFlops + +Благодарности, вопросы и реквесты фич складывать здесь или в комментариях к [этому посту]. + +Лицензия на код и документацию MIT. Вы можете свободно использовать, изменять и продавать код при условии сохранения +информации об авторских правах. + +[этому посту]:https://t.me/ssleg/463 \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..137c9e8 --- /dev/null +++ b/main.cpp @@ -0,0 +1,272 @@ +// 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; +} \ No newline at end of file