Жанры книг
Мы в соц.сетях
ParaKnig📚 » Компьютеры и Интернет » Интернет » QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович
<< На главную

QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович

Читать онлайн QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 29 30 31 32 33 34 35 36 37 ... 106
Перейти на страницу:

int main(int argc, char *argv[]) {

 uint64_t t = ClockCycles();

 pthread_t tid;

 pthread_create(&amp;tid, NULL, threadfunc, NULL);

 pthread_join(tid, NULL);

 t = ClockCycles() - t;

 cout &lt;&lt; &quot;Thread time, &quot; &lt;&lt; cycle2milisec(t) &lt;&lt; &quot; msec. [&quot; &lt;&lt; t &lt;&lt;

  &quot; cycles]&quot; &lt;&lt; endl;

 exit(EXIT_SUCCESS);

}

На результаты этого теста (в отличие от предыдущего) уже достаточно существенно влияет приоритет, под которым выполняется задача, поэтому проделаем его с достаточно высоким приоритетом (29):

# nice -n-19 p2-2

Thread time: 0.147139 msec. [78667 cycles]

# nice -n-19 p2-1

Fork time: 2.5366 msec. [1356179 cycles]

Вот так… время порождения нового «пустого» процесса, даже минимального размера (размер исполняемого файла этого процесса чуть больше 4 Кбайт), почти в 20 раз больше затрат на создание потока! А для процессов большого объема эта разница может доходить до 3–4 порядков (см. результаты первого теста).

Далее рассмотрим сравнительную эффективность с другой стороны: будет ли диспетчеризация многочисленных потоков, принадлежащих одному процессу, эффективнее диспетчеризации такого же количества отдельных процессов? Для процессов задача текстуально выглядит так ( файл p4-1.cc):

void workproc(int how = 1) {

 const int nsingl = 1000, msingl = 30;

 for (int j = 0; j &lt; how; j++) // ... имитация вычислений

  for (uint64_t i = 0; i &lt; msingl; i++)

   for (uint64_t k = 0; k &lt; nsingl; k++)

    k = (k + 1) - 1;

}

int main(int argc, char *argv[]) {

 int numpar = 1;

 if (argc &gt; 1 &amp;&amp; atoi(argv[1]) &gt; 0)

  numpar = atoi(argv[1]);

 _clockperiod clcold;

 ClockPeriod(CLOCK_REALTIME, NULL, &amp;clcold, 0);

 if (argc &gt; 2 &amp;&amp; atoi(argv[2]) &gt; 0) {

  _clockperiod clcnew = { atoi(argv[2]) * 1000, 0 };

   ClockPeriod(CLOCK_REALTIME, &amp;clcnew, &amp;clcold, 0);

 }

 timespec interval;

 sched_rr_get_interval(0, &amp;interval);

 cout &lt;&lt; &quot;Rescheduling interval = &quot;

  &lt;&lt; (double)interval.tv_nsec / 1000000 &lt;&lt; &quot; msec.&quot; &lt;&lt; endl;

 uint64_t t = ClockCycles();

 for (int i = 0, i &lt; numpar; i++) {

  pid_t pid = fork();

  if (pid == -1) perror(&quot;fork&quot;), exit(EXIT_FAILURE);

  if (pid == 0) {

   workproc(1000);

   exit(EXIT_SUCCESS);

  }

 }

 for (int i = 0; i &lt; numpar; i++) wait3(NULL, WEXITE0, NULL);

 t = ClockCycles() - t;

 cout &lt;&lt; &quot;Forks scheduling time&quot; &lt;&lt; cycle2milisec(t)

  &lt;&lt; &quot; msec [&quot; &lt;&lt; t &lt;&lt; &quot; cycles]&quot; &lt;&lt; endl;

 ClockPeriod(CLOCK_REALTIME, &amp;clcold, NULL, 0);

 exit(EXIT_SUCCESS);

}

Имитатором активной вычислительной нагрузки программы является функция workproc(), отличительной особенностью которой является то, что она при активной (хоть и бессмысленной) загрузке процессора не делает на всем интервале своего выполнения никаких системных вызовов, которые могли бы привести к вытеснению выполняющего ее потока.

Первым параметром программы является количество процессов, на которые распределяется общий объем вычислений. Но самое главное: начнем управлять размером периода временного системного тика.

Примечание

По умолчанию системный тик (для QNX 6.2.1) равен 1 мсек., но в принципе его значение можно уменьшать функцией ClockPeriod()вплоть до 10 мксек. Кстати, в описании именно этой функции присутствует замечание о том, что « …период решедулирования равен 4 тикам, и это соотношение в системе нельзя изменить».

Второй параметр запуска программы (при его наличии) и определяет размер периода системного тика, выраженный в микросекундах. (В конце выполнения задач подобного рода, изменяющих размер системного тика, нужно обязательнопринять меры к восстановлению его прежнего значения даже в случаях экстремального и аварийного завершения задачи!) Для повышения достоверности тестов величина размера интервала диспетчеризации контролируется независимым образом (вызовом sched_rr_get_interval()).

При распараллеливании вычислительного объема между потоками эквивалентный код ( файл p4-2.cc) будет иметь вид (используется та же функция workproc()), которую мы повторно не показываем):

void* threadfunc(void* data) {

 workproc(100);

 pthread_exit(NULL);

}

int main(int argc, char *argv[]) {

 int numpar = 1;

 if (argc &gt; 1 &amp;&amp; atoi(argv[1]) &gt; 0)

  numpar = atoi(argv[1]);

 pthread_t *tids = new pthread_t [numpar];

 _clockperiod clcold;

1 ... 29 30 31 32 33 34 35 36 37 ... 106
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович бесплатно.
Комментарии
Открыть боковую панель
Комментарии
Лариса
Лариса 11.03.2026 - 20:17
Странно,здесь имя девочки Аграфена,а на других сайтах я прослушала три книги этого цикла с именем Дарвина.Зачем менять имя и путать читателей? Опечатка- не Дарвина,  а  Дарина.
Григорий
Григорий 09.04.2025 - 22:24
Лучшая книга всех времен
Женя
Женя 02.04.2025 - 16:08
Любимая книга