|
Программирование >> Полиморфизм без виртуальных функций в с++
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. Другие библиотеки в это.м параграфе представлен небольшой список других библиотек на С++, чтобы проиллюстрировать их разнообразие. Кроме упомянутых, существует
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |