Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_MPI_OpenMP.doc
Скачиваний:
15
Добавлен:
16.11.2019
Размер:
1.09 Mб
Скачать

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

Int rank, size;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf("rank=%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("size=%d\n",size);

MPI_Finalize();

}

Типы данных MPI

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

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

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

Двухточечные обмены

Передача и прием сообщений процессами являются основным механизмом MPI. Основные операции двухточечных обменов это - send и receive. В MPI реализовано два типа обменов, блокирующие обмены и не блокирующие обмены, в каждом из двух типов может использоваться 4 режима связи: стандартный, буферизующий(B), синхронный (S), по готовности (R).

Блокирующие обмены.

M PI_Send()

M PI_Bsend() MPI_Recv()

M PI_Ssend()

MPI_Rsend()

Для всех режимов передачи используется одна функция приема MPI_Recv.

Функция передачи – стандартный режим:

Int mpi_Send(void* buf, int count, mpi_Datatype datatype, int dest, int tag, mpi_Comm comm)

Функция приема:

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

OUT

buf

адрес буфера передачи/приема

IN

count

количество элементов в буфере передачи/приема

IN

datatype

тип передаваемых/принимаемых данных

IN

dest/source

ранг (номер процесса) источника (куда/от кого)

IN

tag

тэг сообщения (integer)

IN

comm

коммуникатор

OUT

status

объект статуса (Status)

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

Tag – это целое число, которое является отличительным признаком сообщения. Если на одном процессе несколько операций передачи сообщения (как у нас, на 0-вом процессе), то они не могут иметь одинаковый tag.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Send процесс 0 -> Recv остальные процессы

// mpirunnp <кол-во_процессов> <имя_исполняемого_файла>

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <mpi.h>

#include <iostream>

using namespace std;

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

{

int proc, size;

MPI_Status stat[2];

MPI_Init( &argc, &argv);

MPI_Comm_rank( MPI_COMM_WORLD, &proc);

MPI_Comm_size( MPI_COMM_WORLD, &size);

double b[10];

if (proc == 0) /* код для процесса с номером 0*/

{

double a[10];

for(int i=0; i<10; i++)

a[i]=(double)proc;

for(i=1; i<size; i++){ /*передача массива */

MPI_Send(&a[0], 10, MPI_DOUBLE, i, 100, MPI_COMM_WORLD);

}

}

else /* код для остальных процессов */

{ /* прием массива на остальных процессах */

MPI_Recv(&b[0], 10, MPI_DOUBLE, 0, 100, MPI_COMM_WORLD, &stat[0]);

for(i=0; i<10; i++)

cout<<b[i]<<”\t|;

}

MPI_Finalize();

}

Возвращаемая статусная информация

MPI_Status - это структура, которая содержит три поля:

  • MPI_SOURCE,

  • MPI_TAG,

  • MPI_ERROR.

Следовательно, status.MPI_SOURCE, status.MPI_TAG и status.MPI_ERROR содержат: ранк источника, тэг и код ошибки принятого сообщения.

Аргумент status также возвращает информацию о длине принятого сообщения. Так как, эта информация не является полем структуры status, то чтобы получить значение длины сообщения нужно вызвать функцию MPI_GET_COUNT.