Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 58 59 60 [ 61 ] 62 63 64 ... 144


83.2. Поддержка параллельности

Множество библиотек и расширений было написано с целью поддержать параллельность. Ученые мужи были твердо убеждены в том, что многопроцессорные системы вскоре получат гораздо большее распространение, че.м сейчас. Насколько я .могу судить, такое убеждение поддерживается в течение вот уже 20 лет.

Многопроцессорные системы действительно становятся обычным дело.м, но то же .можно сказать и о быстрых однопроцессорных машинах. Поэтому нужны, по крайней мере, две формы поддержки параллельности: многопоточность на одном процессоре и многопроцессность на нескольких. Кроме того, дополнительные требования предъявляются к програм.ма.м, предназначенным для работы в сети. Из-за этого многообразия я рекомендовал реализовывать параллелизм в библиотеках, а не в самом языке. Такие языковые средства, как, скажем, задачи в Ada, были бы неудобны почти для всех пользователей.

Во.зможпо спроектировать библиотеки для поддержки параллельности так, что по удобству и эффективности они почти не будут уступать встроенным сред-ства.м. Но, опираясь па библиотеки, можно поддержать самые разные модели параллельности, что обеспечит пользователям гораздо большее удобство, чем единая встроенная модель. Проблемы же переносимости, возникаюшие при использовании нескольких таких библиотек, .можно разрешить с помощью тонкого слоя интерфейсных классов.

При.меры библиотек для поддержки параллельности можно найти в [Stroustrup, 1980b], [Shopiro, 1987], [Faust, 1990] и [Parrington, 1990]. Примеры расширений, в которых поддержаны некоторые виды параллельности, - это Concurrent C-I-+ [Gehani, 1988], Compositional С++ [Chandy, 1993] и Micro С++ [Ruhr, 1992]. Кроме того, для поддержки потоков и облегченных процессов доступны различные ко.ммерческие пакеты.

8.3.2.1. Пример задачи

В качестве примера програм.мы, в которой механизмы параллельности вынесены в библиотеку, приведу алгоритм нахождения простых чисел (peniero Эратосфена), где каждое простое число обрабатывается отдельной задачей. В примере используются очереди из библиотеки поддержки многозадачности [Stroustrup, 1980b], куда помешаются целые числа, служащие для задач фильтрами:

#include <task.h>

tinclude <iostream.h>

class Int message : public object {

int i ; public:

Int message(int n) : i(n) {) int val() { return i; }

В очередях хранятся сообщения от классов, производных от obj ect. Использование имени object доказывает, что библиотека была разработана довольно давно. В современной программе для реализации очереди я бы использовал шаблоны, чтобы обеспечить безопасность типов, но сейчас сохраню стиль, присущий



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

class sieve : public tasl< {

qtail* dest; public:

sievelir.t prime, qhead* source);

Ю1асс, производный от task, способен работать параллельно с другими зада-ча.ми. Вся полезная работа выполняется в конструкторах задачи или в вызывае-мо.м из них коде. В нашем примере каждый sieve является задачей. Объект sieve получает число из входной очереди и проверяет, делится ли оно па простое число, связанное с .эти.м sieve. Если нет - sieve передает число датыпе, следу-юп1ему sieve. Если его нет, то мы нашли новое простое число и може.м создать новый sieve для его представления.

sieve::sieve(int prime, qhead* source) : dest(O) {

cout << npocToe\c prime \n; for(;;) (

Int message* p = (Int message*) source->get(); int n = p->val(); if (n%prime) { if (dest) {

dest->put(p);

continue;

найдено простое число: создать новый объект sieve

dest = new qtail;

new sieve(n,dest->head0);

delete p;

Сообщение создается в свободной па.мяти и удаляется те.м объектом sieve, который это сообщение получил. Задачи работают под управлением планировщика, то есть система обеспечения многозадачности - это ие просто система сопрограмм, где управление передается явно.

Чтобы завершить программу, на.м понадобится создать первый sieve в функции main():

int main О {

int n = 2;



qtail* q = new qtail;

new sieve(n,q->head0); создать первый объект sieve for (;;) {

q->put(new Int message(++n));

thistask->delay(1); дадим возможность поработать

Программа будет работать, пока полностью не исчерпает системные ресурсы. Я не позаботился о ее корректном завершении. Это далеко не самый эффективный способ вычисления простых чисел. На каждое простое число требуются одна задача и множество контекстных переключений. Программа могла бы работать как симулятор на одном процессоре с адресным пространством, разделяемым всеми задачами, или как настоящая параллельная программа на нескольких процессорах. Я тестировал ее в режиме симулятора па DEC VAX для 10 тыс. простых чисел (они же задачи). Еще более удивительный вариант решета Эратосфена на С++ см. в работе [Sethi, 1989].

8.3.2.2. Блокировка

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

class Lock {

... public:

Lack(Real lock&); поставить блокировку -LockО; снять блокировку

void my fct() {

Lock lck(q21ock); поставить блокировку на q2 использовать q2

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

8.4. Другие библиотеки

в это.м параграфе представлен небольшой список других библиотек на С++, чтобы проиллюстрировать их разнообразие. Кроме упомянутых, существует



1 ... 58 59 60 [ 61 ] 62 63 64 ... 144

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика