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

Тут можно читать онлайн Олег Цилюрик - QNX/UNIX: Анатомия параллелизма - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Символ-Плюс, год 2006. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    QNX/UNIX: Анатомия параллелизма
  • Автор:
  • Жанр:
  • Издательство:
    Символ-Плюс
  • Год:
    2006
  • Город:
    Санкт-Петербург
  • ISBN:
    5-93286-088-Х
  • Рейтинг:
    4.56/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 100
    • 1
    • 2
    • 3
    • 4
    • 5

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма краткое содержание

QNX/UNIX: Анатомия параллелизма - описание и краткое содержание, автор Олег Цилюрик, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

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

QNX/UNIX: Анатомия параллелизма - читать онлайн бесплатно ознакомительный отрывок

QNX/UNIX: Анатомия параллелизма - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Олег Цилюрик
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

#include

#include

#include

#include

#include

#include

#include

static void out(char s) {

int policy;

sched_param param;

pthread_getschedparam(pthread_self(), &policy, &param);

cout << s << param.sched_curpriority << flush;

}

// целевые функции каждой из последовательностей только

// выводят свой символ-идентификатор и следующий за ним

// приоритет, на котором выполняется целевая функция

static void mon1(void) { out('.'); }

static void mon2(void) { out('*'); }

static void mon3(void) { out('+'); }

// это всего лишь перерасчет временных интервалов,

// измеренных в тактах процессора (в наносекундах)

inline uint64_t cycles2nsec(uint64_t с) {

const static uint64_t cps =

// частота процессора

SYSPAGE_ENTRY(qtime)->cycles_per_sec;

return (с * 1000000000) / cps;

}

// структура, необходимая только для накопления статистики параметров

// ряда временных отметок: среднего, среднеквадратичного отклонения,

// минимального и максимального значений

struct timestat {

private:

uint64_t prev;

public:

uint64_t num;

double mean, disp, tmin, tmax;

timestat(void) {

mean = disp = tmin = tmax = 0.0;

num = 0;

}

// новая временная отметка в ряду:

void operator++(void) {

uint64_t next = ClockCycles(), delta;

if (num i= 0) {

double delta = cycles2nsec(next — prev);

if (num == 1) tmin = tmax = delta;

else tmin = min(tmin, delta), tmax = max(tmax, delta);

mean += delta;

disp += delta * delta;

}

prev = next;

num++;

}

// подвести итог ряда;

void operator !(void) {

mean /= (num - 1);

disp = sqrt(disp / (num - 1) - mean * mean);

}

}

// предварительное описание функции потока объекта

void* syncthread(void*);

class thrblock {

private:

static int code;

bool ok, st;

public:

pthread_t tid;

struct sigevent event;

timer_t timer;

int chid;

void* (*func)(void*);

sched_param param;

// структура только для статистики:

timestat sync;

// конструктор класса - он не только инициализирует структуру данных

// создаваемого объекта, но и запускает отдельный поток для его исполнения

thrblock(

// параметры конструктора

// - целевая функция последовательности

void (*dofunc)(void);

// - период ее синхронизации

unsigned long millisec;

// - приоритет возбуждения синхросерии

unsigned short priority;

// - копить ли статистику временных интервалов?

bool statist = false

) {

// создание канала для получения уведомлений от таймера

if (!(ok = ((chid = ChannelCreate(0)) >= 0))) return;

// создать соединение по каналу, которое будет использовать таймер

event.sigev_coid =

ConnectAttach(ND_LOCAL_NODE, 0, chid, NTO_SIDE_CHANNEL, 0);

if (!(ok = (event.sigev_coid >= 0))) return;

// занести целевую функцию, заодно выполнив

// трюк преобразования над ее типом

func = (void*(*)(void*))dofunc;

int policy;

// запомнить приоритет вызывающей программы

// под этим приоритетом и вызывать целевую функцию

pthread_getschedparam(pthread_self(), &policy, &param);

st = statist;

event.sigev_code = code++;

event.sigev_notify = SIGEV_PULSE;

// а вот это приоритет, с которым нужно будет пробуждаться от таймера!

event.sigev_priority = priority;

// создание таймера

if (!(ok = (timer_create(CLOCK_REALTIME, &event, &timer) == 0))) return;

// запуск отдельного потока, который по сигналу

// таймера будет выполнять целевую функцию

if (!(ok = (pthread_create(&tid, NULL, &syncthread, (void*)this) == EOK)))

return;

// и только после этого можно установить период срабатывания

// таймера, после чего он фактически и запускается

struct itimerspec itime;

nsec2timespec(&itime.it_value, millisec * 1000000ull);

itime it_interval = itime.it_value;

if (!(ok = (timer_settime(timer, 0, &itime, NULL) == 0))) return;

}

// признак того, что объект создан успешно и его поток запущен:

bool OK(void) { return ok; }

bool statistic(void) { return st; }

};

int thrblock.code = _PULSE_CODE_MINAVAIL;

// функция потока объекта

void* syncthread(void *block) {

thrblock *p = (thrblock*)block;

struct _pulse buf;

pthread_attr_t attr;

while(true) {

// ожидание пульса от периодического таймера объекта

MsgReceivePulse(p->chid, &buf, sizeof(struct _pulse), NULL);

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

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

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

pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);

pthread_attr_setschedparam(&attr, &p->param);

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

pthread_create(NULL, &attr, p->func, NULL);

if (p->statistic()) ++p->sync;

}

}

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

inline static void empty(int signo) {}

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

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

signal(SIGINT, empty);

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

void(*funcs[])(void) = { &mon1, &mon2, &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 < num; i++) {

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

priority[i], true);

if (!tb[i]->OK())

perror("synchro thread create"), exit(EXIT_FAILURE);

}

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

pause();

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

cout << endl << "Monitoring finalisation!" << endl;

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

const double n2m = 1000000.;

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

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

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

cout << i << '\t' << p->num << "\t=> " << p->mean / n2m << " [" <<

p->tmin / n2m << "..." << p->tmax / n2m << "]\t~" << p->disp / n2m <<

" (" << p->disp / p->mean * 100 << "%)" << endl;

}

return EXIT_SUCCESS;

}

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

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Олег Цилюрик читать все книги автора по порядку

Олег Цилюрик - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге QNX/UNIX: Анатомия параллелизма, автор: Олег Цилюрик. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x