Коллективные взаимодействия процессов

В операциях коллективного взаимодействия процессов участвуют все процессы коммуникатора. Соответствующая процедура должна быть вызвана каждым процессом, быть может, со своим набором параметров. Возврат из процедуры коллективного взаимодействия может произойти в тот момент, когда участие процесса в данной операции уже закончено. Как и для блокирующих процедур, возврат означает то, что разрешен свободный доступ к буферу приема или по­сылки. Асинхронных коллективных операций в MPI нет.

В коллективных операциях можно использовать те же коммуникаторы, что и были использованы для операций типа точка-точка. MPI гарантирует, что со­общения, вызванные коллективными операциями, никак не повлияют на вы­полнение других операций и не пересекутся с сообщениями, появившимися в результате индивидуального взаимодействия процессов.

Вообще говоря, нельзя рассчитывать на синхронизацию процессов с помощью коллективных операций. Если какой-то процесс уже завершил свое участие в коллективной операции, то это не означает ни того, что данная операция за­вершена другими процессами коммуникатора, ни даже того, что она ими начата (конечно же, если это возможно по смыслу операции).

В коллективных операциях не используются идентификаторы сообщений.

int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int source, MPI_Comm comm)

• outbuf— адрес начала буфера посылки сообщения;

• count— число передаваемых элементов в сообщении;

• datatype — тип передаваемых элементов;

• source — номер рассылающего процесса;

• comm — идентификатор коммуникатора.

Рассылка сообщения от процесса source всем процессам данного коммуника­тора, включая рассылающий процесс. При возврате из процедуры содержимое буфера buf процесса source будет скопировано в локальный буфер каждого процесса коммуникатора comm. Значения параметров count, datatype, source и comm должны быть одинаковыми у всех процессов. В результате выполнения следующего оператора всеми процессами коммуникатора comm: MPI_Bcast(array, 100, MPIINT, 0, comm);

первые сто целых чисел из массива array нулевого процесса будут скопирова­ны в локальные буфера array каждого процесса коммуникатора comm.

int MPI_Gather( void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int dest, MPI_Comm comm)

• sbuf — адрес начала буфера посылки;

• scount — число элементов в посылаемом сообщении;

• stype — тип элементов отсылаемого сообщения;

• out rbuf — адрес начала буфера сборки данных;

• rcount — число элементов в принимаемом сообщении;

• rtype — тип элементов принимаемого сообщения;

• dest — номер процесса, на котором происходит сборка данных;

• comm — идентификатор коммуникатора.

Сборка данных со всех процессов в буфере rbuf процесса dest. Каждый про­цесс, включая dest, посылает содержимое своего буфера sbuf процессу dest. Собирающий процесс сохраняет данные в буфере rbuf, располагая их в порядке возрастания номеров процессов. На процессе dest существенными являются значения всех параметров, а на всех остальных процессах — только значения параметров sbuf, scount, stype, dest и comm. Значения параметров dest и comm должны быть одинаковыми у всех процессов. Параметр rcount у процесса dest обозначает число элементов типа rtype, принимаемых не от всех процес­сов в сумме, а от каждого процесса. С помощью похожей функции MPI_Gatherv можно принимать от процессов массивы данных различной длины.

int MPI_Scatter(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int source, MPI_Comm comm)

• sbuf — адрес начала буфера посылки;

• scount — число элементов в посылаемом сообщении;

• stype — тип элементов отсылаемого сообщения;

• out rbuf — адрес начала буфера сборки данных;

• rcount — число элементов в принимаемом сообщении;

• rtype — тип элементов принимаемого сообщения;

• source — номер процесса, на котором происходит сборка данных;

• comm — идентификатор коммуникатора.

Функция MPI_Scatter по своему действию является обратной к MPI_Gather. Процесс source рассылает порции данных из массива sbuf всем n процессам приложения. Можно считать, что массив sbuf делится на n равных частей, со­стоящих из scount элементов типа stype, после чего i-я часть посылается i-му процессу. На процессе source существенными являются значения всех пара­метров, а на всех остальных процессах — только значения параметров rbuf, rcount, rtype, source и comm. Значения параметров source и comm должны быть одинаковыми у всех процессов. Аналогично функции MPI_Gatherv, с по­мощью функции MPI_Scatterv процессам можно отослать порции данных раз­личной длины.

В следующем примере показано использование функции MPI_Scatter для рас­сылки строк массива. Напомним, что в языке Си, в отличие от Фортрана, мас­сивы хранятся в памяти по строкам.

#include "mpi.h"

#include <stdio.h>

#define SIZE 4

int main(int argc, char **argv)

{

int numtasks, rank, sendcount, recvcount, source;

float sendbuf[SIZE][SIZE] = {

{1.0, 2.0, 3.0, 4.0},

{5.0, 6.0, 7.0, 8.0},

{9.0, 10.0, 11.0, 12.0},

{13.0, 14.0, 15.0, 16.0} };

float recvbuf[SIZE];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

if (numtasks == SIZE) {

source = 1;

sendcount = SIZE;

recvcount = SIZE;

Наши рекомендации