При распараллеливании вычислительного объема между потоками эквивалентный код ( файл p4-2.cc ) будет иметь вид (используется та же функция workproc()
), которую мы повторно не показываем):
void* threadfunc(void* data) {
workproc(100);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
int numpar = 1;
if (argc > 1 && atoi(argv[1]) > 0)
numpar = atoi(argv[1]);
pthread_t *tids = new pthread_t [numpar];
_clockperiod clcold;
ClockPeriod(CLOCK_REALTIME, NULL, &clcold, 0);
if (argc > 2 && atoi(argv[2]) > 0) {
_clockperiod clcnew = { atoi(argv[2]) * 1000, 0 };
ClockPeriod(CLOCK_REALTIME, &clcnew, &clcold, 0);
}
timespec interval;
sched_rr_get_interval(0, &interval);
cout << "Rescheduling interval = "
<< (double)interval.tv_nsec / 1000000 << " msec. " << endl;
uint64_t t = ClockCycles();
for (int i = 0; i < numpar; i++)
pthread_create(&tids[i], NULL, threadfunc, NULL);
for (int i = 0; i < numpar; i++)
pthread_join(tids[i], NULL);
t = ClockCycles() - t;
cout << "Threads scheduling time " << cycle2milisec(t)
<< " msec. [" << t << " cycles]" << endl;
ClockPeriod(CLOCK_REALTIME, &clcold, NULL, 0);
exit(EXIT_SUCCESS);
}
Наконец, для сравнительного анализа выполним тот же объем вычислительной работы в одиночном потоке, то есть в последовательной «классической» программе ( файл p4-3.cc ):
i nt main(int argc, char *argv[]) {
int numpar = 1;
if (argc > 1 && atoi(argv[1]) > 0)
numpar = atoi(argv[1]);
_clockperiod clcold;
ClockPeriod(CLOCK_REALTIME, NULL, &clcold, 0);
if (argc > 2 && atoi(argv[2]) > 0) {
_clockperiod clcnew = { atoi(argv[2]) * 1000, 0 };
ClockPeriod(CLOCK_REALTIME, &clcnew, &clcold, 0);
}
timespec interval;
sched_rr_get_interval(0, &interval);
cout << "Rescheduling interval = "
<< (double)interval.tv_nsec / 1000000. << " msec." << endl;
uint64_t t = ClockCycles();
workproc(1000 * numpar);
t = ClockCycles() - t;
cout << "Single scheduling time. " << cycle2milisec(t)
<< " msec. [" << t << " cycles]" << endl;
ClockPeriod(CLOCK_REALTIME, &clcold, NULL, 0);
exit(EXIT_SUCCESS);
}
Выполняем 3 полученных теста для различных значений периода системного тика (показано группами по 3 запуска) в таком порядке: одиночный процесс, параллельные потоки, параллельные процессы:
# nice -n-19 p4-3 10
Rescheduling interval = 3.99939 msec
Single scheduling time: 5928.8 msec [3169850746 cycles]
# nice -n-19 p4-2 10
Rescheduling interval = 3.99939 msec.
Threads scheduling time: 5919.82 msec. [3165049513 cycles]
# nice -n-19 p4-1 10
Rescheduling interval = 3.99939 msec.
Forks scheduling time: 5962.21 msec. [3187713371 cycles]
# nice -n-19 p4-3 10 50
Rescheduling interval = 0.197788 msec
Single scheduling time: 6427.33 msec. [3436394566 cycles]
# nice -n-19 p4-2 10 50
Rescheduling interval = 0.197788 msec.
Threads scheduling time: 6207.96 msec. [3319104030 cycles]
# nice -n-19 p4-1 10 50
Rescheduling interval = 0.197788 msec
Forks scheduling time 6029.23 msec. [3223548073 cycles]
# nice -n-19 p4-3 10 20
Rescheduling interval = 0.077104 msec.
Single scheduling time: 6745.37 msec. [3606433666 cycles]
# nice -n-19 p4-2 10 20
Rescheduling interval = 0.077104 msec
Threads scheduling time: 6762.69 msec [3615692975 cycles]
# nice -n-19 p4-1 10 20
Rescheduling interval = 0.077104 msec
Forks scheduling time: 6647.42 msec [3554062343 cycles]
# nice -n-19 p4-3 10 11
Rescheduling interval = 0.04358 msec
Single scheduling time. 7517.74 msec [4019381476 cycles]
# nice -n-19 p4-2 10 11
Rescheduling interval = 0.04358 msec
Threads scheduling time: 7638.89 msec. [4084155676 cycles]
# nice -n-19 p4-1 10 11
Rescheduling interval = 0.04358 msec.
Forks scheduling time: 7679 29 msec. [4105758575 cycles]
# nice -n-19 p4-3 10 10
Rescheduling interval = 0.036876 msec.
Single scheduling time: 7937.35 msec. [4243731124 cycles]
# nice -n-19 p4-2 10 10
Rescheduling interval = 0.036876 msec.
Threads scheduling time. 8136.42 msec. [4350159949 cycles]
# nice -n-19 p4-1 10 10
Rescheduling interval = 0.036876 msec
Forks scheduling time: 8172.35 msec [4369372230 cycles]
Результаты могут показаться достаточно неожиданными: во всех 3-х вариантах (в группах) это практически одни и те же цифры — различия затрат на выполнение и в едином последовательном потоке, и во многих параллельных процессах (как предельные случаи) не превышают 0,5–2%! Но результат есть результат, и его нужно как-то интерпретировать, ведь, как известно, «из песни слова не выкинешь».
Эти результаты позволяют (пусть грубо и оценочно) «разложить» затраты производительности между обслуживанием системного таймера (службы времени ОС) и диспетчеризацией. Еще раз обратимся к отдельным выборочным результатам:
# nice -n-19 p4-3 10
Rescheduling interval = 3.99939 msec.
Single scheduling time: 5928.8 msec. [3169850746 cycles]
To есть на протяжении «работы» было 5928,8/0,9998475 = 5929 прерываний от службы времени.
# nice -n-19 p4-3 10 10
Rescheduling interval = 0.036876 msec
Single scheduling time: 7937.35 msec. [4243731124 cycles]
Читать дальше
Конец ознакомительного отрывка
Купить книгу