Последнее изменение файла: 2011.10.21
Скопировано с www.bog.pp.ru: 2024.11.23
Стандарт MPI 1.0 (message passing interface) принят в 1994 году организацией MPI Forum
Модель вычислений SPMP (single program multiple processes),
копия программы должна быть доступна в момент запуска на всех узлах.
Единая программа состоит из множества процессов, каждый из которых
имеет собственное адресное пространство.
Обмен данными и синхронизация осуществляется явно с помощью обмена сообщениями.
Реализация стандарта представляется в виде библиотек для C и Fortran.
Сложен как для реализации, так и для использования.
Версия 2.0 принята в 1997 году - динамическое создание и удаление процессов,
односторонние коммуникации, обмен через общую память, распараллеливание ввода-вывода..
Основные задачи, которые могут решаться вручную или автоматически
в различных моделях организации параллельных работ:
- разбиение приложения на параллельные процессы - вручную
- отображение процессов на процессоры - вручную
- распределение данных по элементам памяти - вручную
- отображение коммуникаций на физические соединения
- синхронизация процессов - вручную
MPI иногда называют "параллельным ассемблером".
Количество процессов и процессоров обычно определяется в момент запуска.
Номера процессов (ранги) нумеруются с нуля. Процессы могут объединяться в группы,
допустимо вложение групп. Процессы внутри группы также перенумерованы.
Каждая группа имеет идентификатор (коммуникатор).
Имеется универсальная группа с идентификатором MPI_COMM_WORLD.
Обмен сообщениями - асинхронный, что позволяет совмещать обмен с вычислениями.
Имеются широковещательные операции как передачи, так и приёма и редукции.
Возможно автоматическое преобразование представления информации в гетерогенных сетях.
Каждое сообщение содержит заголовок (MPI_Status): номер процесса-отправителя (MPI_Source),
номер процесса получателя, идентификатор (MPI_Tag, от 0 до 32767), код ошибки (MPI_Error).
Операции передачи сообщений
- парные (point-to-point)
- коллективные (collective)
Типы передаваемых элементов данных
- MPI_[UNSIGNED_]CHAR
- MPI_[UNSIGNED_]SHORT
- MPI_INT
- MPI_UNSIGNED
- MPI_[UNSIGNED_]LONG
- MPI_FLOAT
- MPI_DOUBLE
- MPI_LONG_DOUBLE
Функции (возвращают MPI_SUCCESS в случае успеха):
- управляющие
- int MPI_Init( int* argc, char*** argv)
- int MPI_Finalize( void )
- int MPI_Comm_size( MPI_Comm идентификатор, int* size) - возвращает число процессов
в группе
- int MPI_Comm_rank( MPI_Comm comm, int* rank) - возвращает номер процесса в группе
- double MPI_Wtime(void) - число секунд с абсолютной точки в прошлом
- int MPI_Comm_split - разбить группу
- int MPI_Comm_free( MPI_Comm идентификатор) - удалить группу
- парные сообщения (синхронность приёма и передачи не зависят друг от друга)
- int MPI_Send(void* buf, int число-элементов, MPI_Datatype тип-элементов,
int получатель, int msgtag, MPI_Comm идентификатор-группы) -
данные сразу после передачи можно использовать, но сообщение может быть не передано!
- int MPI_Isend(void* buf, int число-элементов, MPI_Datatype тип-элементов,
int получатель, int msgtag, MPI_Comm идентификатор-группы, MPI_Request *идентификатор-запроса) -
асинхронная передача, т.е. буфер занят (MPI_Wait и MPI_Test)
- int MPI_Recv(void* buf, int число-элементов, MPI_Datatype тип-элементов,
int отправитель, int msgtag, MPI_Comm идентификатор-группы, MPI_Status *status) -
чтение с блокировкой, количесто полученных элементов извлекается с помощью MPI_Probe();
можно использовать MPI_ANY_SOURCE и MPI_ANY_TAG; последовательность сообщений сохраняется
- int MPI_Irecv(void* buf, int число-элементов, MPI_Datatype тип-элементов,
int отправитель, int msgtag, MPI_Comm идентификатор-группы, MPI_Status *status,
MPI_Request *идентификатор-запроса) - чтение без блокировки,
наличие результата в буфере по MPI_Wait и MPI_Test
- int MPI_Sendrecv
- int MPI_Get_count(MPI_Status *status, MPI_Datatype тип-элементов, int *count) - количество
принятых или принимаемых (MPI_Probe) элементов данных
- int MPI_Probe(int отправитель, int msgtag, MPI_Comm идентификатор-группы, MPI_Status *status) -
ожидание прихода подходящего сообщения и отчёт о его размере и статусе
- int MPI_Iprobe(int отправитель, int msgtag, MPI_Comm идентификатор-группы, int *flag, MPI_Status *status)
проверка наличия подходящего сообщения без блокировки
- int MPI_Wait(MPI_Request *request, MPI_Status *status) - ожидание завершения асинхронной
посылки или приёма с указанным идентификатором
- int MPI_Waitall(int count, MPI_Request *массив-запросов, MPI_Status *statuses)
- int MPI_Waitany(int count, MPI_Request *массив-запросов, int *index, MPI_Status *status)
- int MPI_Waitsome(int incount, MPI_Request *массив-запросов, int *outcount,
int *indexes, MPI_Status *statuses)
- int MPI_Test( MPI_Request *request, int *flag, MPI_Status *status) - проверка завершения
(flag - 0 или 1)
- int MPI_Testall(int count, MPI_Request *requests, int *flag, MPI_Status *statuses)
- int MPI_Testany(int count, MPI_Request *requests, int *index, int *flag, MPI_Status *status)
- int MPI_Testsome(int incount, MPI_Request *requests, int *outcount, int *indexes,
MPI_Status *statuses)
- группировка запросов (группировка приёма и передачи не зависят друг от друга)
- MPI_Send_init
- MPI_Recv_init
- MPI_Startall
- групповые сообщения
- int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int source, MPI_Comm comm) -
рассылка всем, включая отправителя
- int MPI_Gather(void *буфер-отправителя, int scount, MPI_Datatype stype,
void *буфер-получателя, int rcount, MPI_Datatype rtype,
int получатель, MPI_Comm идентификатор-группы)
- сборка данных, рассылаемых всеми процессами, процессом-получателем;
полученные данные сортируются по номеру процесса отправителя
- int MPI_Allreduce( void *sbuf, void *результат, int число-элементов, MPI_Datatype тип-элементов,
MPI_Op операция, MPI_Comm идентификатор-группы) - выполняется ассоциативная и коммутативная
операция (MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD) над входными (sbuf) элементами всех процессов,
запись в "результат" у всех процессов
- int MPI_Reduce( void *sbuf, void *результат, int число-элементов, MPI_Datatype тип-элементов,
MPI_Op операция, int получатель, MPI_Comm идентификатор-группы) - запись результата только
у получателя
- int MPI_Barrier(MPI_Comm идентификатор-группы) - ждать пока остальные процессы дойдут
до этого места
Пример программы запускаемой в несколько процессов. Текст
#include
#include
int main(int argc, char **argv)
{
int mpi_id, nthreads, i=0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_id);
MPI_Comm_size(MPI_COMM_WORLD, &nthreads);
if( mpi_id == 0) {
printf ("there are MPI threads: %i\n", nthreads);
}
printf ("thread: %i\n", mpi_id);
{
for(;;) i++;
}
MPI_Finalize();
}
Компиляция
module load OpenMPI
mpicc -c -o hello_mpi.o hello_mpi.c
mpicc hello_mpi.o -s -lcrypto -lm -o hello_mpi
Запуск на одном компьютере:
mpirun -np 2 ./hello_mpi
Запуск на нескольких компьютерах (используется SSH по ключу,
/usr/lib64/openmpi/1.2.7-gcc/etc/openmpi-mca-params.conf):
for node in 192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.4; do scp hello_mpi $node:
cat > openmpi_host <<EOF
192.168.0.1 slots=8
192.168.0.2 slots=8
192.168.0.3 slots=8
192.168.0.4 slots=8
EOF
mpirun -hostfile openmpi_host -np 32 -mca btl tcp,self ./hello_mpi
Другие реализации MPI - LAM (по слухам, разработчики перешли в OpenMPI) и mpich2.
mpich2 - реализация MPI 2.0 - в пакетах mpich2-1.2.1-2.3.el6.x86_64, mpich2-devel-1.2.1-2.3.el6.x86_64
и mpich2-doc-1.2.1-2.3.el6.noarch. Имеется поддержка системы модулей
для переключения реализации MPI (mpich2-i386 и mpich2-x86_64).
Создать ~.mpd.conf с правами 600 и добавить строку MPD_SECRETWORD=пароль.
После этого можно запускать mpd.
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru