Параллельное программирование: Учебное пособие, страница 104

·  теги сообщений назначаются системой.

5.3.1  Широковещательная рассылка

Широковещательная рассылка (broadcast – радиовещание) выполняется одним выделенным процессом, который называется главным (root - корень), а все остальные процессы, принимающие участие в обмене, получают по одной копии сообщения от главного процесса (рис. 5.6).


Рисунок. 5.6. Широковещательная рассылка.

Выполняется широковещательная рассылка с помощью подпрограммы  MPI_Bcast (Bcast – сокращение от broadcast) :

int MPI_Bcast(void *buffer, int count,

MPI_Datatype datatype, int root, MPI_Comm comm)

Параметры этой процедуры имеют следующий смысл:

·  buffer — адрес буфера;

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

·  datatype — тип данных MPI;

·  root — ранг главного процесса, выполняющего широковещательную рассылку;

·  comm — коммуникатор.

5.3.2  Коллективный обмен с синхронизацией

Синхронизация с помощью барьера является простейшей формой синхронизации коллективных обменов. Она не требует пересылки данных. Подпрограмма MPI_Barrier блокирует выполнение каждого процесса из коммуникатора comm до тех пор, пока все процессы не вызовут эту подпрограмму:

int MPI_Barrier(MPI_Comm comm)

Текст 5.13. Пример использования коллективного обмена

#include "mpi.h"

#include <stdio.h>

int main(int argc, char *argv[])

{

char data[24];

int myrank, count = 25;

MPI_Status status;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

if (myrank == 0)

{

strcpy(data, "Hi, Parallel Programmer!");

MPI_Bcast(&data, count,MPI_BYTE, 0,

MPI_COMM_WORLD);

printf("send: %s\n", data);

}

else

{

MPI_Bcast(&data, count,MPI_BYTE, 0,

MPI_COMM_WORLD);

printf("received: %s\n", data);

}

MPI_Finalize();

return 0;

}

В результате выполнения этой программы получим:

mpiexec –host -machinefile -n 3 – myprogr

send: Hi, Parallel Programmer!

received: Hi, Parallel Programmer!

received: Hi, Parallel Programmer!

5.3.3  Управление областью взаимодействия и группой процессов

Любому процессу, содаваемаемой параллельной программы, априори предоставлена возможность обмениваться данными с другими процессами через глобальный (системный) коммуникатор с именем MPI_COMM_WORLD. Однако, использование лишь одного канала обмена данными для всех возможных передач может сделать параллельную программу весьма уязвимой для возникновения тупиковых ситуаций, перехватов сообщений и нарушения их порядка следования. Поэтому в MPI имеются средства создания собственных новых и преобразования существующих коммуникаторов, которые в принципе могут использоваться только для выделенного множества процессов.

Создание именных коммуникаторов, имена которых можно передавать в качестве параметра в процедурах, позволяет строить модульные программы, на базе которых можно составлять целые библиотеки параллельных подпрограмм. Обычно в подпрограммах используются аргументы, позволяющие определить ранги источника и получателя данных обмена и их метки (теги). Последние позволяют различать сообщения, отправленные для разных целей, но механизма слежения за тегами недостаточно для поддержки модульности. Модульность библиотечных подпрограмм предполагает полную независимость имен, рангов, тегов от примененных имен, рангов и тегов в разрабатываемом параллельном приложении. Поэтому вызов такой библиотечной процедуры может вызвать непредсказуемое поведение разработанной параллельной программы.

Решением проблемы модульности и сохранения предсказуемого поведения программы, работающей с библиотечными процедурами, являются коммуникаторы. Используя средства MPI, можно создать новый коммуникатор, содержащий, например, те же процессы, что и исходный, но с новым контекстом (т. е. с новыми свойствами). Обмен возможен только в рамках одного контекста, а обмены в разных коммуникаторах происходят независимо. Новый коммуникатор можно передать в качестве аргумента библиотечной подпрограмме, как в следующем примере:

.   .   .