Мегаобучалка Главная | О нас | Обратная связь


Прием/передача сообщений между отдельными процессами



2015-11-27 2804 Обсуждений (0)
Прием/передача сообщений между отдельными процессами 4.83 из 5.00 6 оценок




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

 

 

Прием/передача сообщений с блокировкой задаются конструкциями следующе­го вида.

int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm)

• buf — адрес начала буфера с посылаемым сообщением;

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

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

• dest — номер процесса-получателя;

• msgtag — идентификатор сообщения;

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

Блокирующая посылка сообщения с идентификатором msgtag, состоящего из count элементов типа datatype, процессу с номером dest. Все элементы посы­лаемого сообщения расположены подряд в буфере buf. Значение count может быть нулем. Разрешается передавать сообщение самому себе. Тип передавае­мых элементов datatype должен указываться с помощью предопределенных констант типа, например, mpi_int, mpi_long, mpi_short, mpi_long_double, mpi_char, mpi_unsigned_char, mpi_float и т.п. Для каждого типа данных языков Фортран и Си есть своя константа. Полный список предопределенных имен типов можно найти в файле mpi.h.

 

 

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

 

 

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

 

 

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

 

 

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

 

 

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

 

 

int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm, MPI_Status *status)

• out buf — адрес начала буфера для приема сообщения;

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

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

• source — номер процесса- отправителя;

• msgtag — идентификатор принимаемого сообщения;

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

• out status — параметры принятого сообщения.

Прием сообщения с идентификатором msgtag от процесса source с блокиров­кой. Число элементов в принимаемом сообщении не должно превосходить зна­чения count. Если число принятых элементов меньше значения count, то гаран­тируется, что в буфере buf изменятся только элементы, соответствующие эле­ментам принятого сообщения. Если нужно узнать точное число элементов в принимаемом сообщении, то можно воспользоваться функцией MPI_Get_count. Блокировка гарантирует, что после возврата из функции все элементы сообще­ния уже будут приняты и расположены в буфере buf.

Ниже приведен пример программы, в которой каждый процесс выводит на консоль «Здравствуй MPI мир! Я “номер процесса – rank” из “количество запущенных процессов – size” ». Процессы после их порождения функцией MPI_Init завершатся, выполнив функцию MPI_Finalize.

 

#include<mpi.h>

#include<stdio.h>

int main(int argc, char** argv)

{

int rank, size;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD,&rank);

MPI_Comm_size(MPI_COMM_WORLD,&size);

printf("Hello, MPI world! I am %d of %d\n",rank,size);

MPI_Finalize();

return 0;

}

 

Ниже приведен пример программы, в которой если будет запущено процессов числом не равным 2, на экран каждый из процессов выдаст сообщение о том, сколько запущено процессов. Если число процессов равно 2м, то Первый процесс выдаст сообщение на консоль, что он имеет номер 1 из 2х, а также выведет информацию об workmate.

 

#include <mpi.h>

#include <stdio.h>

#include <unistd.h>

int main(int argc, char** argv)

{

int rank,size;

char hostname[100];

MPI_Status st;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (size!=2)

{

printf("This example should be run on 2 processors, now there are %f\n", size);

MPI_Finalize();

return 0;

}

else

{

MPI_Comm_rank(MPI_COMM_WORLD,&rank);

if(rank==0)

{

gethostname(hostname, 100);

MPI_Send(hostname, 100, MPI_CHAR, 1, 99, MPI_COMM_WORLD);

}

else

{

MPI_Recv(hostname, 100, MPI_CHAR, 0, 99, MPI_COMM_WORLD,&st);

printf("I am %d of %d. My workmate is %s\n", rank,size,hostname);

}

MPI_Finalize();

return 0;

}

}

 

Ниже приведен пример программы, в которой нулевой процесс посылает сооб­щение процессу с номером один и ждет от него ответа. Если программа будет запущена с большим числом процессов, то реально выполнять пересылки все равно станут только нулевой и первый процессы. Остальные процессы после их порождения функцией MPI_Init сразу завершатся, выполнив функцию MPI_Finalize.

#include "mpi.h"

#include <stdio.h>

int main(int argc, char **argv)

{

int numtasks, rank, dest, src, rc, tag=1;

char inmsg, outmsg='x';

MPI_Status Stat;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0) {

dest = 1;

src = 1;

rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag,

MPI_COMM_WORLD);

rc = MPI_Recv(&inmsg, 1, MPI_CHAR, src, tag,

MPI_COMM_WORLD, &Stat);

}

Else

if (rank == 1) {

dest = 0;

src = 0;

rc = MPI_Recv(&inmsg, 1, MPI_CHAR, src, tag,

MPI_COMM_WORLD, &Stat);

rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag,

MPI_COMM_WORLD);

}

MPI_Finalize();

}

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

#include "mpi.h"

#include <stdio.h>

main(int argc, char **argv)

{

int me, size;

int SOME_TAG=0;

MPI_Status status;

MPI_Init (&argc, &argv);

MPI_Comm_rank (MPI_COMM_WORLD, &me);

MPI_Comm_size (MPI_COMM_WORLD, &size);

f ((me % 2) == 0) {

if ((me+1) < size /*посылают все процессы кроме последнего*/

MPI_Send (…, me+1, SOME_TAG, MPI_COMM_WORLD);

}

Else

MPI_Recv (…, me-1, SOME_TAG, MPI_COMM_WORLD, &status);

MPI_Finalize();

}

В качестве номера процесса-отправителя можно указать предопределенную константу mpi_any_source — признак того, что подходит сообщение от любого процесса. В качестве идентификатора принимаемого сообщения можно указать константу mpi_any_tag — это признак того, что подходит сообщение с любым идентификатором. При одновременном использовании этих двух констант бу­дет принято любое сообщение от любого процесса.

 

Параметры принятого сообщения всегда можно определить по соответствую­щим полям структуры status. Предопределенный тип MPi_Status описан в файле mpi-h. В языке Си параметр status является структурой, содержащей поля с именами mpi_source, mpi_tag и mpi_error. Реальные значения номера процесса-отправителя, идентификатора сообщения и кода ошибки доступны через status.MPiSOURCE, status.MPiTAG и status.MPiERROR. В Фортране параметр status является целочисленным массивом размера mpi_status_size. Константы mpi_source, mpi_tag и mpi_error являются индексами по данному массиву для доступа к значениям соответствующих полей, например status(MPI_SOURCE).

 

 

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

 

 

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

Последнее замечание относительно использования блокирующих функций приема и посылки связано с возможным возникновением тупиковой ситуации. Предположим, что работают два параллельных процесса и они хотят обменять­ся данными. Было бы вполне естественно в каждом процессе сначала восполь­зоваться функцией MPi_Send, а затем MPi_Recv. Но именно этого и не стоит де­лать. Дело в том, что мы заранее не знаем, как реализована функция MPi_Send. Если разработчики для гарантии корректного повторного использования буфе­ра посылки заложили схему, при которой посылающий процесс ждет начала приема, то возникнет классический тупик. Первый процесс не может вернуться из функции посылки, поскольку второй не начинает прием сообщения. А вто­рой процесс не может начать прием сообщения, поскольку сам по похожей причине застрял на посылке. Выход из этой ситуации прост. Нужно использо­вать либо неблокирующие функции приема/передачи, либо функцию совме­щенной передачи и приема. Оба варианта мы обсудим ниже.

 

 

int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count)

• status — параметры принятого сообщения;

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

• OUT count — число элементов сообщения.

По значению параметра status данная функция определяет число уже приня­тых (после обращения к MPI_Recv) или принимаемых (после обращения к MPI_Probe или MPI_Iprobe) элементов сообщения типа datatype. Данная функ­ция, в частности, необходима для определения размера области памяти, выде­ляемой для хранения принимаемого сообщения.

 

 

int MPI_Probe(int source, int msgtag, MPI_Comm comm, MPI_Status *status)

• source — номер процесса-отправителя или mpi_any_source;

• msgtag — идентификатор ожидаемого сообщения или mpi_any_tag;

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

• out status — параметры найденного подходящего сообщения.

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

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

 

 

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

int MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request)

• buf — адрес начала буфера c посылаемым сообщением;

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

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

• dest — номер процесса-получателя;

• msgtag — идентификатор сообщения;

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

• OUT request — идентификатор асинхронной операции.

Передача сообщения аналогична вызову MPI_Send, однако возврат из функции MPI_Isend происходит сразу после инициализации процесса передачи без ожи­дания обработки всего сообщения, находящегося в буфере buf. Это означает, что нельзя повторно использовать данный буфер для других целей без получе­ния дополнительной информации, подтверждающей завершение данной посыл­ки. Определить тот момент времени, когда можно повторно использовать бу­фер buf без опасения испортить передаваемое сообщение, можно с помощью параметра request и функций MPI_Wait и MPI_Test.

Аналогично трем модификациям функции MPI_Send, предусмотрены три до­полнительных варианта функций MPI_Ibsend, MPI_Issend, MPI_Irsend. К изло­женной выше семантике работы этих функций добавляется асинхронность.

 

 

int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm, MPI_Request *request)

• out buf — адрес начала буфера для приема сообщения;

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

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

• source — номер процесса- отправителя;

• msgtag — идентификатор принимаемого сообщения;

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

• out request — идентификатор операции асинхронного приема сообще­ния.

Прием сообщения, аналогичный MPI_Recv, однако возврат из функции проис­ходит сразу после инициализации процесса приема без ожидания получения всего сообщения и его записи в буфере buf. Окончание процесса приема можно определить с помощью параметра request и процедур типа MPI_Wait и MPITest.

 

 

Сообщение, отправленное любой из функций MPI_Send, MPI_Isend и любой из трех их модификаций, может быть принято любой из процедур MPI_Recv и MPI_Irecv.

С помощью данной функции легко обойти возможную тупиковую ситуацию, о которой говорилось ранее. Заменим вызов функции приема сообщения с блоки­ровкой на вызов функции MPI_Irecv. Расположим его перед вызовом функции MPI_Send, т.е. преобразуем фрагмент следующим образом:

В такой ситуации тупик гарантированно не возникнет, поскольку к моменту вызова функции MPI_Send запрос на прием сообщения уже будет выставлен.

 

 

int MPI_Wait(MPI_Request *request, MPI_Status *status)

• request— идентификатор операции асинхронного приема или передачи;

• out status — параметры сообщения.

Ожидание завершения асинхронной операции, ассоциированной с идентифика­тором request и запущенной функцией MPI_Isend или MPI_Irecv. Пока асин­хронная операция не будет завершена, процесс, выполнивший функцию MPi_Wait, будет заблокирован. Если речь идет о приеме, атрибуты и длину при­нятого сообщения можно определить обычным образом с помощью параметра status.

 

 

int MPI_Waitall(int count, MPIRequest *requests, MPIStatus *statuses)

• count — число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• OUT statuses — параметры сообщений.

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

 

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

 

#include "mpi.h"

#include <stdio.h>

int main(int argc, char **argv)

{

int numtasks, rank, next, prev, buf[2], tag1=1, tag2=2;

MPI_Request reqs[4];

MPI_Status stats[4];

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

prev = rank – 1;

next = rank + 1;

if (rank == 0) prev = numtasks – 1;

if (rank == (numtasks – 1)) next = 0;

MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD,&reqs[0]);

MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD,&reqs[1]);

MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD,&reqs[2]);

MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD,&reqs[3]);

MPI_Waitall(4, reqs, stats);

MPI_Finalize();

}

 

int MPI_Waitany( int count, MPI_Request *requests, int *index, MPI_Status *status)

• count— число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• outindex— номер завершенной операции обмена;

• outstatus — параметры сообщений.

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

 

 

int MPI_Waitsome( int incount, MPI_Request *requests, int *outcount, int *indexes, MPI_Status *statuses)

• incount— число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• out outcount — число идентификаторов завершившихся операций обме­на;

• outindexes— массив номеров завершившихся операции обмена;

• outstatuses— параметры завершившихся сообщений.

Выполнение процесса блокируется до тех пор, пока хотя бы одна из операций обмена, ассоциированных с указанными идентификаторами, не будет заверше­на. Параметр outcount содержит число завершенных операций, а первые outcount элементов массива indexes содержат номера элементов массива requests с их идентификаторами. Первые outcount элементов массива statuses содержат параметры завершенных операций.

 

 

int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status)

• request — идентификатор операции асинхронного приема или передачи;

• out flag — признак завершенности операции обмена;

• out status — параметры сообщения.

Проверка завершенности асинхронных функций MPI_Isend или MPI_Irecv, ас­социированных с идентификатором request. В параметре flag функция MPI_Test возвращает значение 1, если соответствующая операция завершена, и значение 0 в противном случае. Если завершена процедура приема, то атрибуты и длину полученного сообщения можно определить обычным образом с помо­щью параметра status.

 

 

int MPI_Testall( int count, MPI_Request *requests, int *flag, MPI_Status *statuses)

• count — число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• out flag — признак завершенности операций обмена;

• OUT statuses — параметры сообщений.

В параметре flag функция возвращает значение 1, если все операции, ассоции­рованные с указанными идентификаторами, завершены. В этом случае пара­метры сообщений будут указаны в массиве statuses. Если какая-либо из опе­раций не завершилась, то возвращается 0, и определенность элементов массива statuses не гарантируется.

 

 

int MPI_Testany(int count, MPI_Request *requests, int *index, int *flag, MPI_Status *status)

• count — число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• out index — номер завершенной операции обмена;

• out flag — признак завершенности операции обмена;

• out status — параметры сообщения.

Если к моменту вызова функции MPI_Testany хотя бы одна из операций асин­хронного обмена завершилась, то в параметре flag возвращается значение 1, index содержит номер соответствующего элемента в массиве requests, а status — параметры сообщения. В противном случае в параметре flag будет возвращено значение 0.

 

 

int MPI_Testsome( int incount, MPI_Request *requests, int *outcount, int *indexes, MPI_Status *statuses)

• incount — число идентификаторов асинхронных операций;

• requests — идентификаторы операций асинхронного приема или пере­дачи;

• out outcount — число идентификаторов завершившихся операций обме­на;

• out indexes — массив номеров завершившихся операции обмена;

• out statuses — параметры завершившихся операций.

Данная функция работает так же, как и MPi_Waitsome, за исключением того, что возврат происходит немедленно. Если ни одна из указанных операций не завершилась, то значение outcount будет равно нулю.

 

 

int MPI_Iprobe( int source, int msgtag, MPI_Comm comm, int *flag, MPIStatus *status)

• source — номер процесса-отправителя или mpi_any_source;

• msgtag — идентификатор ожидаемого сообщения или mpi_any_tag;

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

• out flag — признак завершенности операции обмена;

• out status — параметры подходящего сообщения.

Получение информации о поступлении и структуре ожидаемого сообщения без блокировки. В параметре flag возвращается значение 1, если сообщение с под­ходящими атрибутами уже может быть принято (в этом случае ее действие полностью аналогично MPI_Probe), и значение 0, если сообщения с указанными атрибутами еще нет.

 

 

Объединение запросов на взаимодействие. Процедуры данной группы позво­ляют снизить накладные расходы, возникающие в рамках одного процессора при обработке приема/передачи и перемещении необходимой информации ме­жду процессом и сетевым контроллером. Несколько запросов на прием и/или передачу могут объединяться вместе для того, чтобы далее их можно было бы запустить одной командой. Способ приема сообщения никак не зависит от спо­соба его посылки: сообщение, отправленное с помощью объединения запросов либо обычным способом, может быть принято как обычным способом, так и с помощью объединения запросов.

 

 

int MPI_Send_init( void *buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request)

• buf — адрес начала буфера с посылаемым сообщением;

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

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

• dest — номер процесса-получателя;

• msgtag — идентификатор сообщения;

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

• out request — идентификатор асинхронной передачи.

Формирование запроса на выполнение пересылки данных. Все параметры точ­но такие же, как и у подпрограммы MPI_Isend, однако в отличие от нее пере­сылка не начинается до вызова подпрограммы MPI_Startall. Как и прежде, дополнительно предусмотрены варианты и для трех модификаций посылки со­общений: MPI_Bsend_init, MPI_Ssend_init, MPI_Rsend_init.

 

 

int MPI_Recv_init( void *buf, int count, MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm, MPI_Request *request)

• out buf — адрес начала буфера приема сообщения;

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

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

• source — номер процесса- отправителя;

• msgtag — идентификатор сообщения;

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

• out request — идентификатор асинхронного приема.

Формирование запроса на выполнение приема сообщения. Все параметры точ­но такие же, как и у функции MPI_Irecv, однако в отличие от нее реальный прием не начинается до вызова функции MPI_Startall.

 

 

MPI_Startall(int count, MPI_Request *requests)

• count— число запросов на взаимодействие;

• outrequests— массив идентификаторов приема/передачи

Запуск всех отложенных операций передачи и приема, ассоциированных с эле­ментами массива запросов requests и инициированных функциями MPI_Recv_init, MPI_Send_init или ее тремя модификациями. Все отложенные взаимодействия запускаются в режиме без блокировки, а их завершение можно определить обычным образом с помощью функций семейств MPI_Wait и MPITest.

 

 

Совмещенные прием и передача сообщений. Совмещение приема и передачи сообщений между процессами позволяет легко обходить множество подводных камней, связанных с возможными тупиковыми ситуациями. Предположим, что в линейке процессов необходимо организовать обмен данными между i-м и (i+D-ым процессами. Если воспользоваться стандартными блокирующими функциями посылки сообщений, то возможен тупик, обсуждавшийся ранее.

Один из способов обхода такой ситуации состоит в использовании функции со­вмещенного приема и передачи.

int MPI_Sendrecv( void *sbuf, int scount, MPI_Datatype stype, int dest, int stag, void *rbuf, int rcount, MPI_Datatype rtype, int source, MPI_Datatype rtag, MPI_Comm comm, MPI_Status *status)

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

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

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

• dest — номер процесса-получателя;

• stag — идентификатор посылаемого сообщения;

• out rbuf — адрес начала буфера приема сообщения;

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

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

• source — номер процесса- отправителя;

• rtag — идентификатор принимаемого сообщения;

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

• out status — параметры принятого сообщения.

Данная операция объединяет в едином запросе посылку и прием сообщений. Естественно, что реализация этой функции гарантирует отсутствие тупиков, которые могли бы возникнуть между процессами при использовании обычных блокирующих операций MPi_Send и MPi_Recv. Принимающий и отправляющий процессы могут являться одним и тем же процессом. Буфера приема и посылки обязательно должны быть различными. Сообщение, отправленное операцией MPiSendrecv, может быть принято обычным образом, и точно также операция MPi_Sendrecv может принять сообщение, отправленное обычной операцией MPiSend.

 

 



2015-11-27 2804 Обсуждений (0)
Прием/передача сообщений между отдельными процессами 4.83 из 5.00 6 оценок









Обсуждение в статье: Прием/передача сообщений между отдельными процессами

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

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



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (2804)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.009 сек.)