Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
учебник_Вс.doc
Скачиваний:
14
Добавлен:
01.03.2025
Размер:
13 Мб
Скачать
☆

11.4.Анализ тупиковых ситуаций при обмене

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

#include <stdio.h>

#include "mpi.h"

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

{

int ierr,rank,size,prev,next,buf[2];

MPI_Request reqs[4];

MPI_Status status[4];

ierr=MPI__Init () ;

ierr=MPI_Comm_size(MPI_COMM_WORLD, &size);

ierr=MPI_Comm_rank(MPI_COMM_WORLD, &rank)/

prev=rank==0?size-l:rank-1;

next=rank==size-l?0:rank+1;

ierr=MPI_Irecv(&buf[0],1,MPI_INT,prev,5,

MPI_COMM_WORLD,Sreqs[0]);

ierr=MPI_Irecv(&buf[1],1,MPI_INT,next,6,

MPI__COMM_WORLD, Sreqs [1] ) ;

ierr=MPI_Isend(&rank,1,MPI_INT,prev,6,

MPI_COMM_WORLD,&reqs[2]);

ierr=MPI_Isend(&rank,1,MPI_INT, next, 5, _W0RLD, &size) ; ierr=MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank!=0) //this is slave while (1)

{

slave(N);

ierr=MPI_Send(a,N,MPI_DOUBLE,0,5,MPI_COMM_WORLD);

} else // if this is process with index 0 (master)

{

for (int i=l;i<size-l;i++)

ierr=MPI_Irecv(&a[i],N,MPI_DOUBLE,i,5,MPI_COMM_WORLD,&req[i]);

while (1)

MPI_COMM_WORLD,&reqs[3]);

ierr=MPI__Waitall (4 , reqs, status) ;

printf ( "process %i prev=%i next=%i\n",buf[0],buf[1]); }

Схема использования процедуры MPI_Waitsome для организации коммуникационной схемы <master-slave> (все процессы общаются с одним выделенным процессом). демонстрируется в следующем примере. Все процессы, кроме процесса 0, на каждой итерации цикла определяют с помощью вызова процедуры slave свою локальную часть массива а, после чего посылают ее главному процессу. Процесс 0 сначала инициализирует неблокирующие приемы от всех остальных процессов, после чего дожидается прихода хотя бы одного сообщения. Для пришедших сообщений процесс 0 вызывает процедуру обработки master, после чего снова выставляет неблокирующие приемы. Таким образом, процесс 0 обрабатывает те порции данных, которые готовы на данный момент. При этом для корректности работы программы нужно обеспечить, чтобы процесс 0 успевал обработать приходящие сообщения, то есть, чтобы процедура slave работала значительно дольше процедуры master (в противном случае и распараллеливание не имеет особого смысла). Кроме того, в примере написан бесконечный цикл, поэтому для конкретной программы нужно предусмотреть условие завершения.

#include' <stdio.h>

#include "mpi.h"

const int N=1000,MAXPROC=128;

double a[MAXPROC] [N];

void slave(int n)

{ // something

'}

void master(int n)

{

}

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

{

int ierr,rank,size; int num,indexes[MAXPROC]; MPI_Request req[MAXPROC]; MPI_Status statuses[MAXPROC]; ierr=MPI Init();

ierr=MPI_Comm_size(MPI_C0MM

{

ierr=MPI_Waitsome(size-1, req,&num,indexes,statuses); for (int i=l;i<num;i++)

{

master (indexes[i])/

ierr=MPI_Irecv(a[indexes[i]],N,MPI_DOUBLE, indexes[i],5,MPI_COMM_WORLD,req[indexes[i]]); } } } ierr=MPI_Finalize(); }