Россия, Новосибирск, НГПУ, 2009 |
Программирование на языке MC#
5.4.2. Пакетный алгоритм
В данном разделе описывается модификация наивного алгоритма "решето Эратосфена", существенно улучшающая эффективность параллельной (распределенной) программы, и которая дает существенное ускорение при поиске простых чисел в длинных интервалах (например, для N >= 106 ).
Основная идея предлагаемого алгоритма заключается в переходе от использования потоков одиночных данных (потоков отдельных натуральных чисел) к потокам пакетов натуральных чисел.
Пакет - это массив натуральных чисел фиксированного размера (задаваемого в программе значением PACKAGE_SIZE ), пустые хвостовые элементы которого заполняются нулями.
При этом, функции наивного алгоритма обобщаются в данном варианте естественным образом:
- async Sieve( handler int []() getNatPack, channel (int []) sendPrimesPack) - с помощью обработчика getNatPack получает первый пакет из потока, обрабатывает его функцией SynchronousSieve, получая пакет простых чисел head, и отправляя его по каналу sendPrimesPack; остальные пакеты из входного потока фильтруются с помощью функции filter по модулю пакета head и направляются на вход следующей в цепочке рекурсивной функции Sieve ;
- void filter( int [] head, handler int [] () getNatPack, channel ( int []) cfiltered) - функция, которая фильтрует пакеты из входного потока, получаемые с помощью обработчика getNatPack, по модулю пакета простых чисел head, отправляя результирующие пакеты в канал cfiltered; при этом, все результирующие пакеты (кроме, может быть, последнего) имеют длину PACKAGE_SIZE (строго говоря, и последний пакет имеет длину PACKAGE_SIZE, но его хвостовая часть может быть заполнена нулями).
Полный текст программы Eratosthenes2 приведен ниже, а также в приложении [ "Программирование на языке MC#" ].
5.5. Программа all2all
Программа all2all предназначена для демонстрации способа, с помощью которого можно обеспечить взаимодействие внутри множества асинхронных (распределенных) процессов в соответствии с принципом "все со всеми". В определенном смысле, эта программа показывает, как можно реализовать на языке MC# глобальные (в терминах MPI, "широковещательные"(broadcast) ) операции передачи данных. Данный подход часто используется в программах, реализующих параллелизм по данным, когда отдельные процессы (процессоры) должны обмениваться сообщениями как со своими соседями, так и со всеми процессами, участвующими в вычислениях.
Ниже будет представлен вариант программы all2all с распределенными ( movable- ) процессами.
В этой программе, каждый распределенный процесс представляется методом Start объекта класса DistribProcess. Для взаимодействия между собой, каждый распределенный процесс создает объект класса BDChannel (Bidirectional channel), содержащий канал Send и обработчик Receive:
Обменявшись между собой такими объектами, распределенные процессы могут посылать и принимать сообщения друг от друга независимо от их физического расположения. Обмен объектами класса BDChannel реализуется через главный процесс, который исполняется на машине, где исходно было запущено распределенное приложение:
Каждый распределенный процесс (объект класса DistribProcess ) выполняет в данной программе следующую последовательность действий:
- Создает свой собственный объект класса BDChannel и отсылает его главному процессу.
- Принимает от главного процесса массив объектов класса BDChannel всех остальных процессов (включая свой собственный).
- Пользуясь этим массивом, посылает сообщение всем остальным процессам в группе.
- Принимает сообщения от всех процессов в группе.
- Посылает сигнал об окончании своей работы главному процессу.
Полный текст программы All2all приведен в приложении [ "Программирование на языке MC#" ].