Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции / Лекция 9

.odt
Скачиваний:
29
Добавлен:
06.07.2016
Размер:
66.93 Кб
Скачать

Технологии и методы программирования. Лекция 9.

Обмен сообщениями. Коммуникаторы.

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

Для получения количества процессов у коммуникатора используется функция MPI_Comm_size(MPI_Comm comm, &size), для получения номера-ранга процесса - MPI_Comm_rank(MPI_Comm comm, &rank). Ранг крайне важен при управлении работой процессов.

Рассмотрим передачу сообщений между процессами. Для простой отправки сообщения используется функция MPI_Send(void* buf, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm), где buf - область памяти, где лежит сообщение, count — число элементов в сообщении, type — один из внутренних типов элементов MPI, dest — ранг процесса-получателя, tag — идентификатор сообщения, используемый для фильтрации сообщений получателем, comm — коммуникатор. После завершения передачи буфер можно использовать для передачи другого сообщения, так как пока сообщение не будет принято — функция не завершиться, и выполнение не будет продолжено.

Базовые типы данных:

Тип MPI

Соответствующий тип С

MPI_CHAR

signed char

MPI_SHORT

signed short int

MPI_INT

signed int

MPI_LONG

signed long int

MPI_UNSIGNED_CHAR

unsigned char

MPI_UNSIGNED_SHORT

unsigned short int

MPI_UNSIGNED

unsigned int

MPI_UNSIGNED_LONG

unsigned long int

MPI_FLOAT

float

MPI_DOUBLE

double

MPI_LONG_DOUBLE

long double

MPI_BYTE

-

MPI_PACKED

-

Приём сообщений осуществляется функцией MPI_Recv(void *buf, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Status *status), где source — ранг процесса-отправителя, status — указатель на структуру данных, в которой содержится информация о результатах выполнения приёма сообщения. При приёме буфер должен быть достаточно велик для сообщения (может быть и больше), а тип элементов должен совпадать с типом, указанном при отправке. Если необходимо принять сообщение от любого процесса, указывается source=MPI_ANY_SOURCE, а для приёма сообщения с любым тэгом — tag=MPI_ANY_TAG. После приёма сообщения ранг отправителья находится в status.MPI_SOURCE, тэг — аналогично, status.MPI_TAG. Для определения количества посланных элементов используется функция MPI_Get_count(MPI_Status *status, MPI_DATA_TYPE type, int *count).

Функция MPI_Recv может вызываться до или после MPI_Send, но при этом работа процесса-получателя всегда приостанавливается до приёма сообщения.

При распределённых вычислениях, при рассылке сообщений иногда теряется детерминированность:

Пример:

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

Описание Proc_Num, Proc_Rank, status.

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORD, *Proc_Num);

MPI_Comm_rank(MPI_COMM_WORLD, *Proc_Rank);

if (Proc_Rank==0){

printf(“Выполняется процесс ”, Proc_Rank);

for (int i=1; i<Proc_Num-1; i++){

MPI_Recv(&Proc_Rank, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

printf(“”, Prov_Rank);

}

}

MPI_Send(&Proc_Rank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

MPI_Finalize();

return 0;

Какое сообщение будет выведено первым? Неизвестно, это зависит от того, какой из потоков первым выполнится, то есть присутствует состояние гонки между процессами. Чтобы приём шёл строго по порядку, в функции MPI_Recv вместо MPI_ANY_SOURCE необходимо указать I. Тогда порядок приёма будет зависеть от ранга, а не от фактического порядка поступления сообщений.

Соседние файлы в папке Лекции