-->

QNX/UNIX: Анатомия параллелизма

На нашем литературном портале можно бесплатно читать книгу QNX/UNIX: Анатомия параллелизма, Цилюрик Олег Иванович-- . Жанр: Программирование / ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
QNX/UNIX: Анатомия параллелизма
Название: QNX/UNIX: Анатомия параллелизма
Дата добавления: 16 январь 2020
Количество просмотров: 317
Читать онлайн

QNX/UNIX: Анатомия параллелизма читать книгу онлайн

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

Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.

В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 34 35 36 37 38 39 40 41 42 ... 106 ВПЕРЕД
Перейти на страницу:

  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  // восстановить приоритет целевой функции до уровня того,

  // кто ее устанавливал, вызывая конструктор

<b>  pthread_attr_setinheritsched(&amp;attr, PTHREAD_EXPLICIT_SCHED);</b>

<b>  pthread_attr_setschedparam(&amp;attr, &amp;p-&gt;param);</b>

  // запуск целевой функции в отдельном &quot;отсоединенном&quot; потоке

  pthread_create(NULL, &amp;attr, p-&gt;func, NULL);

  if (p-&gt;statistic()) ++p-&gt;sync;

 }

}

// 'пустой' обработчик сигнала SIGINT (реакция на ^С)

inline static void empty(int signo) {}

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

 // с этой точки стандартная реакция на ^С отменяется...

 signal(SIGINT, empty);

 // массив целевых функций

 void(*funcs[])(void) = { &amp;mon1, &amp;mon2, &amp;mon3 };

 // периоды их синхросерий запуска

 int period[] = { 317, 171, 77 };

 // приоритеты, на которых отрабатывается реакция

 // синхросерий на каждый из таймеров синхросерий

 int priority[] = { 15, 5, 25 };

 int num = sizeof(funcs) / sizeof(*funcs);

 // запуск 3-х синхронизированных последовательностей

 // выполнения (созданием объектов)

 thrblock** tb = new (thrblock*)[num];

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

  tb[i] = new thrblock(funcs[i], period[i],

  priority[i], true);

  if (!tb[i]-&gt;OK())

  perror(&quot;synchro thread create&quot;), exit(EXIT_FAILURE);

 }

 // ... а теперь ожидаем ^С.

 pause();

 // подсчет статистики и завершение программы

 cout &lt;&lt; endl &lt;&lt; &quot;Monitoring finalisation!&quot; &lt;&lt; endl;

 // вывод временных интервалов будем делать в миллисекундах:

 const double n2m = 1000000.;

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

  timestat *p = &amp;tb[i]-&gt;sync;

  !(*p); // подсчет статистики по объекту

  cout &lt;&lt; i &lt;&lt; 't' &lt;&lt; p-&gt;num &lt;&lt; &quot;t=&gt; &quot; &lt;&lt; p-&gt;mean / n2m &lt;&lt; &quot; [&quot; &lt;&lt;

   p-&gt;tmin / n2m &lt;&lt; &quot;...&quot; &lt;&lt; p-&gt;tmax / n2m &lt;&lt; &quot;]t~&quot; &lt;&lt; p-&gt;disp / n2m &lt;&lt;

   &quot; (&quot; &lt;&lt; p-&gt;disp / p-&gt;mean * 100 &lt;&lt; &quot;%)&quot; &lt;&lt; endl;

 }

 return EXIT_SUCCESS;

}

Вся функциональность программы сосредоточена в одном классе —

thrblock
, который может в неизменном виде использоваться для разных приложений. Необычной особенностью объекта этого класса является то, что он выполнен в технике «активных объектов», навеянной поверхностным знакомством с языками программирования школы Н. Вирта — ActiveOberon и Zormon. В ней говорится, что конструктор такого объекта не только создает объект данных, но и запускает (как вариант) отдельный поток выполнения для каждого создаваемого объекта. В нашем случае задача потоковой функции состоит в вызове целевой функции, адрес которой был передан конструктору объекта в качестве одного из параметров. [26]

Ниже представлены отличия нашей реализации от простого цикла с задержкой, обсуждавшейся выше (помимо исправлений очевидных недостатков):

• Для каждого синхронизирующего таймера установлен свой приоритет «пробуждения», и он может быть достаточно высоким, для того чтобы предотвратить вытеснение этого синхронизирующего потока.

• После «пробуждения» по таймеру запускается целевая функция, но выполняется это отдельным потоком, причем потоком «отсоединенным». Другими словами, процесс выполнения целевой функции никак не влияет на общую схему синхронизации.

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

Запустим наше тестовое приложение:

# t3

+10+10*10+10+10.10*10+10+10*10+10+10.10*10+10+10+10*10+10.10+10*10+10+10*10+10.10+10*10+10+10*10+10.10+10+10*10+10+10+10.10+10+10*10+10+10.10*10+10+10+10*10+10.10+10*10+10+10*10+10+10.10*10+10+10*10+10+10.10+10*10+10+10*10+10.10+10*10+10+10*10+10.10+10+10*10+10+10*10^C

Monitoring finalisation!

0 32  =&gt; 316.919 [316.867...317.895] ~0.178511 (0.056327%)

1 59  =&gt; 170.955 [168.583...173.296] ~0.92472 (0.540914%)

2 132 =&gt; 76.9796 [76.942...77.9524]  ~0.085977 (0.111688%)

Первое, что мы должны отметить, — это очень приличную точность выдержки периода синхронизации (последняя колонка вывода). Для того чтобы убедиться в том, что целевая функция при этом выполняется под приоритетом породившего ее потока, закомментируем строки, выделенные жирным шрифтом в коде программы:

# t3

+25+25*5+25+25.15*5+25+25*5+25+25.15*5+25+25+25*5+25.15+25*5+25+25*5+25.15+25*5+25+25*5*5+25.15+25+25*5+25+25*5.15+25+25*5+25+25.15*5+25+25+25*5+25.15+25*5+25+25*5+25+25.15*5+25+25*5+25+25^C

Monitoring finalisation!

0 32 =&gt; 316.919 [316.797...317.915] ~0.185331 (0.0584792%)

1 ... 34 35 36 37 38 39 40 41 42 ... 106 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название