QNX/UNIX: Анатомия параллелизма
Шрифт:
workproc((int)data);
trtime[id].f = ClockCycles;
pthread_barrier_wait(&bfinish);
return NULL;
}
int main(int argc, char *argv[]) {
// здесь только обработка многочисленных ключей...
int opt, val, nthr = 1, nall = SHRT_MAX;
while ((opt = getopt(argc, argv, "t:n:p:a:")) != -1) {
switch(opt) {
case 't':
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
if (val > 0 && val <= SHRT_MAX) nthr = val;
break;
case 'p':
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
if (val != getprio(0))
if (setprio(0, val) == -1)
perror("priority isn't a valid"), exit(EXIT_FAILURE);
break;
case 'n':
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
if (val > 0)
nsingl *= val;
break;
case 'a':
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
if (val > 0) nall = val;
break;
default:
exit(EXIT_FAILURE);
}
}
// ...
вот здесь начинается собственно сама программа.
if (nthr > 1)
cout << "Multi-thread evaluation, thread number = " << nthr;
else cout << "Single-thread evaluation";
cout << " , priority level: " << getprio(0) << endl;
__clockperiod clcout;
ClockPeriod(CLOCK_REALTIME, NULL, &clcout, 0);
// интервал диспетчеризации - 4 периода tickslice
// (системного тика):
cout << "rescheduling = \t"
<< clcout.nsec * 4 / 1000000. << endl;
// калибровка
времени выполнения в одном потоке
const int NCALIBR = 512;
uint64_t tmin = 0, tmax = 0;
tmin = ClockCycles;
workproc(NCALIBR);
tmax = ClockCycles;
cout << "calculating = \t"
<< cycle2milisec(tmax - tmin) / NCALIBR << endl;
// а теперь контроль времени многих потоков
if (pthread_barrier_init(&bstart, NULL, nthr) != EOK)
perror("barrier init"), exit(EXIT_FAILURE);
if (pthread_barrier_init(&bfinish, NULL, nthr + 1) != EOK)
perror("barrier init"), exit(EXIT_FAILURE);
trtime = new interv[nthr];
int cur = 0, prev = 0;
for (int i = 0; i < nthr; i++) {
// границы участков работы для каждого потока.
cur = (int)floor((double)nall / (double)nthr * (i + 1) + .5);
prev = (int)floor((double)nall / (double)nthr * i + 5);
if (pthread_create(NULL, NULL, threadfunc, (void*)(cur - prev)) != EOK)
perror("thread create"), exit(EXIT_FAILURE);
}
pthread_barrier_wait(&bfinish);
for (int i=0; i < nthr; i++ ) {
tmin = (i == 0) ? trtime[0].s : __min(tmin, trtime[i].s);
tmax = ( i == 0 ) ? trtime[0].f : __max(tmax, trtime[i].f);
}
cout << "evaluation = \t"
<< cycle2milisec(tmax - tmin) / nall << endl;
pthread_barrier_destroy(&bstart);
pthread_barrier_destroy(&bfinish);
delete trtime;
exit(EXIT_SUCCESS);
}
Логика этого приложения крайне проста:
• Есть некоторая продолжительная по времени рабочая функция (
workproc
), выполняющая массированные вычисления. • Многократно (это число определяется ключом запуска
а
)выполняется рабочая функция. Хорошо (то есть корректнее), если время ее единичного выполнения, которое задается ключом n
, больше интервала диспетчеризации системы (в системе установлена диспетчеризация по умолчанию - круговая, или карусельная).
Поделиться с друзьями: