Чтение онлайн

ЖАНРЫ

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
, больше интервала диспетчеризации системы (в системе установлена диспетчеризация по умолчанию - круговая, или карусельная).

Поделиться с друзьями: