@ -0,0 +1,272 @@
// 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 ;
}