Transcript comm
КОЛЛЕКТИВНЫЕ ВЗАИМОДЕЙСТВИЯ ПРОЦЕССОВ
• Барьерная синхронизация всех процессов группы.
• Широковещательная передача (broadcast) от одного процесса
всем остальным процессам группы.
• Сбор данных из всех процессов группы в один процесс.
• Рассылка данных одним процессом группы всем процессам
группы.
• Сбор данных, когда все процессы группы получают результат.
• Раздача/сбор данных из всех процессов группы всем процессам
группы.
• Глобальные операции редукции, такие как сложение,
нахождение максимума, минимума или определенные
пользователем функции, где результат возвращается всем
процессам группы или в один процесс.
• Составная операция редукции и раздачи.
• Префиксная операция редукции, при которой в процессе i
появляется результат редукции 0, 1, …, i, i ≤ n, где n – число
процессов в группе.
Ключевым понятием в коллективных функциях является группа
участвующих процессов, но в качестве явного аргумента выступает
коммуникатор.
В операциях коллективного взаимодействия процессов участвуют
все процессы коммуникатора!
Как и для блокирующих процедур, возврат означает то, что разрешен
свободный доступ к буферу приема или посылки.
Сообщения, вызванные коллективными операциями, не пересекутся с
другими сообщениями.
int MPI_Barrier (MPI_Comm comm)
– функция барьерной синхронизации, блокирует
вызывающий процесс, пока все процессы группы не
вызовут ее.
IN comm коммуникатор (дескриптор)
int MPI_Bcast(void* buffer, int count, MPI_Datatype datatype, int root,
MPI_Comm comm ) -функция широковещательной передачи посылает
сообщение из корневого процесса всем процессам группы, включая себя.
INOUT buffer адрес начала буфера (альтернатива)
IN count количество записей в буфере (целое)
IN datatype тип данных в буфере (дескриптор)
IN root номер корневого процесса (целое)
IN comm коммуникатор (дескриптор)
процесс
ы
данные
root
int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm
comm)
- операция сборки данных. Каждый процесс, включая корневой, посылает
содержимое своего буфера в корневой процесс.
IN sendbuf начальный адрес буфера процесса-отправителя
(альтернатива)
IN sendcount количество элементов в отсылаемом сообщении (целое)
IN sendtype тип элементов в отсылаемом сообщении (дескриптор)
OUT recvbuf начальный адрес буфера процесса сборки данных
(альтернатива, существенен только для корневого процесса)
IN recvcount количество элементов в принимаемом сообщении (целое,
имеет значение только для корневого процесса)
IN recvtype тип данных элементов в буфере процессаполучателя(дескриптор)
IN root номер процесса-получателя (целое)
IN comm коммуникатор (дескриптор)
int MPI_Scatter (void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm
comm) - операция рассылки данных. Каждый процесс, включая корневой,
получает содержимое своего части буфера из корневой процессора
(обратно MPI_GATHER).
IN sendbuf начальный адрес буфера рассылки (альтернатива,
используется только корневым процессом)
IN sendcount количество элементов, посылаемых каждому процессу
(целое, используется только корневым процессом)
IN sendtype тип данных элементов в буфере посылки (дескриптор,
используется только корневым процессом)
OUT recvbuf адрес буфера процесса-получателя (альтернатива)
IN recvcount количество элементов в буфере корневого процесса (целое)
IN recvtype тип данных элементов приемного буфера (дескриптор)
IN root номер процесса-получателя (целое)
IN comm коммуникатор (дескриптор)
процесс
ы
данные
Пример 1. Широковещательная передача 100 целых чисел от процесса 0 каждому
процессу в группе.
MPI_Comm comm;
int array[100];
int root = 0;
MPI_Bcast( array, 100, MPI_INT, root, comm );
Пример 2. Сбор 100 целых чисел с каждого процесса группы в корневой процесс
MPI_Comm comm;
int gsize,sendarray[100];
int root, *rbuf;
MPI_Comm_size( comm, &gsize);
rbuf = (int *)malloc(gsize*100*sizeof(int));
MPI_Gather(sendarray,100, MPI_INT, rbuf,100,MPI_INT,root, comm);
Пример 3. Обратен примеру 1, MPI_SCATTER рассылает 100 чисел из корневого
процесса каждому процессу в группе.
MPI_Comm comm;
int gsize,*sendbuf;
int root, rbuf[100];
MPI_Comm_size( comm, &gsize);
sendbuf = (int *)malloc(gsize*100*sizeof(int));
MPI_Scatter( sendbuf, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);
int MPI_Gatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, int root,
MPI_Comm comm) - операция сборки данных разной длины.
IN sendbuf начальный адрес буфера процесса-отправителя
(альтернатива)
IN sendcount количество элементов в отсылаемом сообщении (целое)
IN sendtype тип элементов в отсылаемом сообщении (дескриптор)
OUT recvbuf начальный адрес буфера процесса сборки данных
(альтернатива, существенно для корневого процесса)
IN recvcounts массив целых чисел (по размеру группы), содержащий
количество элементов, которые получены от каждого из процессов
(используется корневым процессом)
IN displs массив целых чисел (по размеру группы). Элемент i определяет
смещение относительно recvbuf, в котором размещаются данные из
процесса i (используется корневым процессом)
IN recvtype тип данных элементов в буфере процесса-получателя
(дескриптор)
IN root номер процесса-получателя (целое)
IN comm коммуникатор (дескриптор)
Пример 4. Каждый процесс посылает 100 чисел int корневому процессу, но каждое
множество (100 элементов) размещается с некоторым шагом
(stride ≥ 100 ) относительно конца размещения предыдущего множества.
MPI_Comm comm;
int gsize,sendarray[100], root, *rbuf, stride, *displs,i,*rcounts;
MPI_Comm_size( comm, &gsize);
rbuf = (int *)malloc(gsize*stride*sizeof(int));
displs = (int *)malloc(gsize*sizeof(int));
rcounts = (int *)malloc(gsize*sizeof(int));
for (i=0; i<gsize; ++i) {
displs[i] = i*stride;
rcounts[i] = 100; }
MPI_Gatherv( sendarray, 100, MPI_INT, rbuf, rcounts, displs,
MPI_INT, root, comm);
int MPI_Scatterv(void* sendbuf, int *sendcounts, int *displs, MPI_Datatype
sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
MPI_Comm comm) - операция рассылки данных разной длины.
IN sendbuf адрес буфера посылки (альтернатива, используется только
корневым процессом)
IN sendcounts целочисленный массив (размера группы), определяющий
число элементов, для отправки каждому процессу
IN displs целочисленный массив (размера группы). Элемент i указывает
смещение (относительно sendbuf, из которого берутся данные для
процесса )
IN sendtype тип элементов посылающего буфера (дескриптор)
OUT recvbuf адрес принимающего буфера (альтернатива)
IN recvcount число элементов в посылающем буфере (целое)
IN recvtype тип данных элементов принимающего буфера (дескриптор)
IN root номер посылающего процесса (целое)
IN comm коммуникатор (дескриптор)
Взаимодействия «ВСЕ СО ВСЕМИ»
int MPI_Allgather(void* sendbuf,int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
- сбор данных аналогично MPI_GATHER, где результат принимают все
процессы, а не только корневой процессор.
IN sendbuf начальный адрес посылающего буфера (альтернатива)
IN sendcount количество элементов в буфере (целое)
IN sendtype тип данных элементов в посылающем буфере (дескриптор)
OUT recvbuf адрес принимающего буфера (альтернатива)
IN recvcount количество элементов, полученных от любого процесса
(целое)
IN recvtype тип данных элементов принимающего буфера (дескриптор)
IN comm коммуникатор (дескриптор)
процесс
ы
данные
int MPI_Allgatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype,
MPI_Comm comm)
– сбор данных аналогично MPI_GATHERV, где результат принимают все
процессы, а не только корневой процессор.
IN sendbuf начальный адрес посылающего буфера (альтернатива)
IN sendcount количество элементов в посылающем буфере (целое)
IN sendtype тип данных элементов в посылающем буфере (дескриптор)
OUT recvbuf адрес принимающего буфера (альтернатива)
IN recvcounts целочисленный массив (размера группы), содержащий
количество элементов, полученных от каждого процесса
IN displs целочисленный массив (размера группы). Элемент i
представляет смещение области (относительно recvbuf), где помещаются
принимаемые данные от процесса i
IN recvtype тип данных элементов принимающего буфера (дескриптор)
IN comm коммуникатор (дескриптор)
int MPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void*
recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) расширение функции MPI_ALLGATHER для случая, когда каждый процесс
посылает различные данные каждому получателю.
IN sendbuf начальный адрес посылающего буфера (альтернатива)
IN sendcount количество элементов посылаемых в каждый процесс
(целое)
IN sendtype тип данных элементов посылающего буфера (дескриптор)
OUT recvbuf адрес принимающего буфера (альтернатива)
IN recvcount количество элементов, принятых от какого-либо процесса
(целое)
IN recvtype тип данных элементов принимающего буфера (дескриптор)
IN comm коммуникатор (дескриптор)
процесс
ы
данные
int MPI_Alltoallv(void* sendbuf, int *sendcounts, int *sdispls, MPI_Datatype
sendtype, void* recvbuf,int *recvcounts,int *rdispls, MPI_Datatype recvtype,
MPI_Comm comm) –
рассылка и сборка каждый каждому различных данных разной длины.
IN sendbuf начальный адрес посылающего буфера (альтернатива)
IN sendcounts целочисленный массив (размера группы), определяющий
количество посылаемых каждому процессу элементов
IN sdispls целочисленный массив (размера группы). Элемент j содержит
смещение области (относительно sendbuf), из которой берутся
данные для процесса j
IN sendtype тип данных элементов посылающего буфера (дескриптор)
OUT recvbuf адрес принимающего буфера (альтернатива)
IN recvcounts целочисленный массив (размера группы), содержит число
элементов, которые могут быть приняты от каждого процесса
IN rdispls целочисленный массив (размера группы). Элемент i определяет
смещение области (относительно recvbuf), в которой размещаются
данные, получаемые из процесса i
IN recvtype тип данных элементов принимающего буфера (дескриптор)
IN comm коммуникатор (дескриптор)
ГЛОБАЛЬНЫЕ ОПЕРАЦИИ РЕДУКЦИИ
int MPI_Reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, int root, MPI_Comm comm)
- объединяет элементы входного буфера каждого процесса в группе, используя
операцию op, и возвращает объединенное значение в выходной буфер процесса с
номером root.
IN sendbuf адрес посылающего буфера (альтернатива)
OUT recvbuf адрес принимающего буфера (альтернатива, используется только корневым процессом)
IN count количество элементов в посылающем буфере (целое)
IN datatype тип данных элементов посылающего буфера (дескриптор)
IN op операция редукции (дескриптор)
IN root номер главного процесса (целое)
IN comm коммуникатор (дескриптор)
Предопределенные операции редукции
Имя
MPI_MAX
MPI_MIN
MPI_SUM
MPI_PROD
MPI_LAND
MPI_BAND
MPI_LOR
MPI_BOR
MPI_LXOR
MPI_BXOR
MPI_MAXLOC
MPI_MINLOC
Значение
максимум
минимум
сумма
произведение
логическое И
поразрядное И
логическое ИЛИ
поразрядное ИЛИ
логическое исключающее ИЛИ
поразрядное исключающее ИЛИ
максимальное значение и местонахождения
минимальное значение и местонахождения
MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
Пример 5. Каждый процесс имеет массив 30 чисел типа double. Для каждой из 30
областей надо вычислить значение и номер процесса, содержащего наибольшее
значение.
/* каждый процесс имеет массив из чисел двойной точности: ain[30]*/
#include <stdlib.h>
double ain[30], aout[30];
int ind[30];
struct {
double val;
int rank;
} in[30], out[30];
int i, myrank, root=0;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
srand(time(NULL));
for (i=0; i<30; ++i) {
in[i].val = (double)rand()/RAND_MAX;
in[i].rank = myrank;
}
MPI_Reduce(in,out,30,MPI_DOUBLE_INT,MPI_MAXLOC,root,comm );
/* в этой точке результат помещается на корневой процесс */
if (myrank == root) { /* читаются выходные номера */
for (i=0; i<30; ++i) {
aout[i] = out[i].val;
ind[i] = out[i].rank; /* номер обратно преобразуется в целое */
}
int MPI_Allreduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype
datatype, MPI_Op op, MPI_Comm comm)
– отличается от MPI_REDUCE тем, что результат появляется в
принимающем буфере всех членов группы.
IN sendbuf начальный адрес посылающего буфера (альтернатива)
OUT recvbuf начальный адрес принимающего буфера (альтернатива)
IN count количество элементов в посылающем буфере (целое)
IN datatype тип данных элементов посылающего буфера ()
IN op операция (дескриптор)
IN comm коммуникатор (дескриптор)
int MPI_Reduce_scatter(void* sendbuf, void* recvbuf, int *recvcounts,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
- выполнение i recvcounts[i] независимых глобальных операций op над
соответствующими элементами массивов sendbuf
IN sendbuf начальный адрес посылающего буфера (альтернатива)
OUT recvbuf начальный адрес принимающего буфера (альтернатива)
IN recvcounts целочисленный массив, определяющий количество
элементов результата, распределенных каждому процессу. Массив должен
быть идентичен во всех вызывающих процессах
IN datatype тип данных элементов буфера ввода (дескриптор)
IN op операция (дескриптор)
IN comm коммуникатор (дескриптор)
int MPI_Scan(void* sendbuf, void* recvbuf, int count, MPI_Datatype
datatype, MPI_Op op, MPI_Comm comm )
- операция возвращает в приемный буфер процесса i редукцию значений в
посылающих буферах процессов с номерами 0, ..., i (включительно).
IN sendbuf начальный адрес посылающего буфера (альтернатива)
OUT recvbuf начальный адрес принимающего буфера (альтернатива)
IN count количество элементов в принимающем буфере (целое)
IN datatype тип данных элементов в принимающем буфере (дескриптор)
IN op операция (дескриптор)
IN comm коммуникатор (дескриптор)