- •Использование технологии параллельного программирования mpi-2
- •1 Введение
- •1.1 Аппаратные средства для параллельных вычислений
- •1.2 Коммуникационные библиотеки
- •1.3 Средства автоматизированного распараллеливания
- •2 Кластерные системы и стандарт параллельного программирования mpi
- •2.1 Стандарт mpi
- •2.2 Запуск mpi-2 на кластере
- •2.3 Статическая параллельная программа с использованием mpi
- •2.4 Динамическая параллельная программа с использованием mpi
- •Литература
2.2 Запуск mpi-2 на кластере
В данной работе для экспериментов был использован кластер на основе сети персональных компьютеров и библиотека MPICH2 [6]. Этот пакет можно получить и использовать бесплатно. В состав MPICH2 входит библиотека программирования, загрузчик приложений, утилиты.
Прежде всего необходимо скачать и установить на все узлы кластера пакет MPICH2. Исходные тексты или уже скомпилированные пакеты под разные платформы можно получить на сайте [6].
В данном случае MPICH2 v.1.0.3 собирался из исходных текстов для ОС FreeBSD v.5.3 на процессоре Intel Pentium III. Процесс инсталляции библиотеки описан в MPICH2 Installer's Guide.
MPICH2 использует rsh (remote shell). Поэтому необходимо запустить на каждом узле rshd (remote shell server) и согласовать права доступа, т.е. по команде rsh mynode система должна сразу ''пускать'' вас не спрашивая пароль. Для обеспечения более высокого уровня сетевой безопасности можно использовать ssh - OpenSSH remote login client.
Компиляция MPI-программы на языке С выполняется утилитой mpicc, представляющей собой надстройку над C-компилятором, установленным в данной ОС. Так же есть аналогичные утилиты для языков С++ - mpiCC и FORTRAN77 - mpif77.
mpicc myprog.c -o myprog
mpiCC myprog.cpp -o myprog
mpif77 myprog.f -o myprog
Перед запуском ''бинарника'' myprog необходимо разослать его на все узлы кластера, причем локальный путь до myprog должен быть одинаковый на всех машинах, например - /usr/mpibin/myprog.
Вместо процедуры копирования программы на узлы можно использовать NFS (Network File System) :
на головной машине запускаем NFS-сервер и открываем каталог с myprog
на каждом рабочем узле кластера, монтируем NFS головной машины, используя единый для всех узлов локальный путь.
В отличии от MPICH1, который использовал только rsh, в случае MPICH2 процессы на узлах управляются специальным демоном mpd. Перед началом работы надо запустить его с головной машины на всех узлах при помощи mpdboot.
mpdboot --totalnum=2 --file=hosts.mpd --user=mechanoid --verbose
где hosts.mpd - текстовый файл со списком используемых узлов кластера.
Проверка состояния mpd выполняется при помощи mpdtrace:
$ mpdtrace -l
node2.home.net_51160 (192.168.0.2)
node1.home.net_53057 (192.168.0.1)
Завершение работы mpd выполняется при помощи mpdexit
$ mpdexit node2.home.net_51160
При выключении одного узла выключаются все остальные.
Запуск MPI-программы производится командой :
mpiexec -n N myprog
где N - начальное количество параллельных процессов.
После этого происходит запуск N копий MPI-программы myprog.
mpiexec сам распределяет процессы по узлам, ''общаясь'' с mpd, в данном случае нет надобности указывать список узлов как в mpirun для MPICH1.
2.3 Статическая параллельная программа с использованием mpi
Параллельная программа описывает некоторое количество процессов (веток параллельной программы) и порядок их взаимодействия. В статической модели стандарта MPI-1 количество таких веток фиксировано и задается при запуске программы.
MPI-программа начинается с вызова функции MPI_INIT(), которая включает процесс в среду MPI, и завершается вызовом функции MPI_FINALIZE(). При запуске каждая ветка параллельной программы получает MPI-идентификатор - ранг, который можно узнать при помощи функции MPI_COMM_RANK(). Для обмена данными между процессами в рамках MPI существует много разных функций: MPI_SEND() - обмен точка-точка, посылка сообщения для одного процесса, MPI_RECV() - обмен точка-точка, прием сообщения, MPI_BCAST() - широковещательная посылка один-всем, MPI_REDUCE() - сбор и обработка данных, посылка все-одному и еще много других.
Приведем пример статической MPI-программы вычисления числа как суммы ряда на языке FORTRAN77, текст программы [http://mechanoid.narod.ru/parallel/mpi2/pi.f].
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* $Id: pi.f,v 1.4 2006/03/06 12:31:32 mechanoid Exp mechanoid $
*
* pi parallel calculate with MPI
*
* OS : FreeBSD 5.3
* COMPILER : mpif77 for MPICH2 v.1.0.3
* gcc version 3.4.2 [FreeBSD]
* GNU ld version 2.15 [FreeBSD]
*
* AUTHOR : Evgeny S. Borisov
*
* Glushkov Institute of Cybernetics
* National Academy of Sciences of Ukraine
*
* http://www.mechanoid.kiev.ua
* e-mail : par@mechanoid.kiev.ua
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
program pi_calculate
implicit none
include 'mpif.h'
* размер интервала, на котором будем считать сумму
integer N
parameter(N=10000000)
* номер процесса
integer iam
* количество ветвей параллельной программы
integer nprocs
* имя узла, на котором выполняется процесс
character*18 pname
integer ierr, i,nlen
real*8 pi, h, x, res
* инициализация MPI
call MPI_INIT(ierr)
* получаем количество ветвей параллельной программы
call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
* получаем номер процесса
call MPI_COMM_RANK(MPI_COMM_WORLD, iam, ierr)
* получаем имя узла, на котором выполняется процесс
call MPI_GET_PROCESSOR_NAME(pname,nlen,ierr);
* процесс 0 печатает размер интервала, на котором будем считать сумму
if(iam .eq. 0) then
write(*,*) 'N = ', N
endif
write(*,*)'Process ',iam,' of ',nprocs,' started on ',pname
* считаем частичную сумму
pi = 0.0
h = 1.0/N
do i= 1+iam , N, nprocs
x = h*(i-0.5)
pi = pi+(4.0/(1.0+x*x))
enddo
pi = h * pi
* процесс 0 получает результаты от ветвей и суммирует их
call MPI_REDUCE(pi,res,1,MPI_REAL8,MPI_SUM,0,MPI_COMM_WORLD,ierr)
* процесс 0 печатает конечный результат
if(iam .eq. 0) then
write(*,*) 'pi = ', res
endif
* завершение работы
call MPI_FINALIZE(ierr)
stop
end
*
* результаты запуска на кластере из двух Pentium III 700MHz, FAST ETHERNET 100Mbs
*
* два узла
*
* mechanoid@node2 /usr/home/mechanoid/MPI/pi/f
* $ time mpiexec -n 2 ./pi
* N = 1000000000
* Process 0 of 2 started on node2.home.net
* Process 1 of 2 started on node1.home.net
* pi = 3.1415926
*
* real 0m24.265s
* user 0m0.396s
* sys 0m0.045s
*
* один узел
*
* mechanoid@node2 /usr/home/mechanoid/MPI/pi/f
* $ time mpiexec -n 1 ./pi
* N = 1000000000
* Process 0 of 1 started on node2.home.net
* pi = 3.1415926
*
* real 0m46.724s
* user 0m0.355s
* sys 0m0.090s
*
Результаты работы программы, на кластере из двух PC на процессоре Pentium III 700MHz, сеть FAST ETHERNET 100Mbs, размер интервала, на котором считали сумму, равен 108
один узел, время работы - 47 секунд
$ mpiexec -n 1 ./pi
Process 0 of 1 started on node2.home.net
pi = 3.1415926
два узла, время работы - 24 секунды
$ time mpiexec -n 2 ./pi
Process 0 of 2 started on node2.home.net
Process 1 of 2 started on node1.home.net
pi = 3.1415926