roms писал(а):
то же опасался )
тем не менее тормозов практически нет, видимо планировщик оставляет какой то резерв для других задач
Относительно параллельности и загрузки процессоров (ядер) я вам такую вот интересную штуку нарисую:
Код: Выделить всё
#include <sys/time.h>
#include <unistd.h>
#include <iostream>
using namespace std;
void delay( ulong msec ) { // пассивная задержка в миллисекундах
struct timespec pause = { 0, 0 };
pause.tv_sec = msec / 1000;
pause.tv_nsec = ( msec % 1000 ) * 1000000L;
nanosleep( &pause, NULL );
}
static pthread_spinlock_t loc;
int rept = 10, msec = 100;
bool bspin = true;
static void* block_func( void* par ) { // функция потока
for( int i = 0; i < rept; i++ ) {
if( bspin ) pthread_spin_lock ( &loc );
delay( msec );
if( bspin ) pthread_spin_unlock ( &loc );
}
return NULL;
}
int main( int argc, char *argv[] ) {
int nthr = 5;
if( argc > 1 && atoi( argv[ 1 ] ) != 0 ) nthr = atoi( argv[ 1 ] );
bspin = nthr > 0;
nthr = abs( nthr );
cout << getpid() << ": число потоков = " << nthr << endl;
pthread_spin_init( &loc, 1 );
pthread_t *h = new pthread_t[ nthr ];
struct timeval tb, tf;
gettimeofday( &tb, NULL );
cout << "wait...";
for( int i = 0; i < nthr; i++ ) // параллельные потоки
if( pthread_create( h + i, NULL, &block_func, NULL ) != 0 ) {
cout << "ошибка создания потока " << i << endl;
return EXIT_FAILURE;
}
for( int i = 0; i < nthr; i++ )
pthread_join( h[ i ], NULL );
gettimeofday( &tf, NULL );
cout << "\r";
delete [] h;
timersub( &tf, &tb, &tf );
long interv = tf.tv_sec * 1000L + tf.tv_usec / 1000L +
( tf.tv_usec % 1000 > 500 ? 1 : 0 );
cout << "интервал выполнения: " << nthr << " x " << rept << " x "
<< msec << " = " << interv << " миллисекунд" << endl;
pthread_spin_destroy( &loc );
}
Очень интересно:
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/SMP_block$ ./block 30
8623: число потоков = 30
интервал выполнения: 30 x 10 x 100 = 30020 миллисекунд
И если одновременно посмотрим:
Код: Выделить всё
olej@ACER:~$ top -p 8623
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99,2 us, 0,8 sy, 0,0 ni, 0,0 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st
MiB Mem : 11888,2 total, 1465,5 free, 6084,4 used, 4338,4 buff/cache
MiB Swap: 12165,0 total, 12162,2 free, 2,8 used. 4372,9 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8623 olej 20 0 210532 3588 3184 S 190,7 0,0 0:54.81 block
В системе (в моём тесте) 2 процессора, и они загружены на 200%, т.е.
полностью. Если в вашей системе будет 16 процессоров, то задача эта создаст загрузку 1600% !
Что здесь происходит? Когда 1 поток, захватив спин-блокировку выполняет пассивное ожидание nanosleep(), все остальные N-1 потоков тупо крутятся активно на спин-блокировке, ожидая её освобождения.
А если вот так:
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/SMP_block$ ./block -30
8659: число потоков = 30
интервал выполнения: 30 x 10 x 100 = 1003 миллисекунд
Здесь (- значение параметра) захват спин-блокировки не происходит, и задача завершается ровно в N (по числу потоков) раз быстрее - все потоки выполняются
параллельно.