Опубликован: 22.04.2008 | Уровень: профессионал | Доступ: платный
Лекция 2:

Основы программирования на MPI

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >

2.3. Методы передачи данных в MPI: "точка-точка" и радиовещательные (broadcast) сообщения

Операции передачи данных в MPI типа "точка-точка" представляют собой передачу сообщений между, в точности, двумя MPI-процессами. Один процесс, при этом, выполняет команду Send (послать), тогда как другой процесс выполняет команду Receive (принять).

Выполнение команд Send и Receive осуществляется посредством вызова соответствующих MPI-функций, которые имеют различные типы, или, другими словами, различное назначение:

  • Блокирующий Send / блокирующий Receive
  • Неблокирующий Send / неблокирующий Receive
  • Синхронный Send
  • Буферированный Send
  • Комбинированный Send / Receive
  • Send по готовности ( "ready" Send ).

С любым типом операции Send может состоять в паре любой тип операции Receive.

Функции передачи данных типа "точка-точка" имеют список аргументов одного из следующих форматов:

  • Блокирующий Send:
    MPI_Send ( buffer, count, type, dest, tag, comm )
  • Неблокирующий Send:
    MPI_Isend ( buffer, count, type, dest, tag, comm, request )
  • Блокирующий Receive:
    MPI_Recv ( buffer, count, type, source, tag, comm., status )
  • Неблокирующий Receive:
    MPI_Irecv ( buffer, count, type, source, tag, comm., request )

Аргументы в этих функциях имеют следующее назначение:

  1. buffer - место хранения данных, которые посылаются или принимаются;
  2. count - количество элементов данных конкретного типа, которые посылаются или принимаются;
  3. type - тип элементарных данных, задаваемый через встроенные MPI-типы, такие как (для языка С): MPI_CHAR, MPI_SHORT, MPI_INT, MPI_LONG, MPI_FLOAT, MPI_DOUBLE, MPI_BYTE, MPI_PACKED и др.
  4. dest - указывает процесс, которому должно быть доставлено сообщение - задается через ранг принимающего процесса;
  5. source - аргумент функций приема сообщений, указывающий номер посылающего процесса; указание значения MPI_ANY_SOURCE означает прием сообщения от любого процесса;
  6. tag - произвольное неотрицательное целое число, присваиваемое программистом для однозначной идентификации сообщения; у парных операций Send и Reсeive эти числа должны совпадать; указание у операции Receive значения MPI_ANY_TAG может быть использовано для приема любого сообщения, независимо от значения tag ;
  7. comm - указывает на коммуникатор, в рамках которого трактуются значения аргументов dest и source ; чаще всего используется встроенный коммуникатор MPI_COMM_WORLD ;
  8. status - для операции Receive, указывает источник (source) сообщения и его тег ( tag ); в языке С, этот аргумент есть указатель на встроенную структуру MPI_Status ; из этой же структуры может быть получено количество принятых байт посредством функции MPI_Get_count ;
  9. request - используется в неблокирующих операциях Send и Receive, и задает уникальный "номер запроса"; в языке С, этот аргумент является указателем на встроенную структуру MPI_Request.

К наиболее часто используемым блокирующим функциям передачи сообщений относятся следующие функции:

MPI_Send

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

Формат вызова:

MPI_Send ( &buf, count, datatype, dest, tag, comm. )

MPI_Recv

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

Формат вызова:

MPI_Recv ( &buf, count, datatype, source, tag, comm, &status )

MPI_Ssend

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

Формат вызова:

MPI_Ssend ( &buf, count, datatype, dest, tag, comm )

MPI_Bsend, MPI_Buffer_attach

Перед вызовом MPI_BSend, программист должен вызвать функцию MPI_Buffer_attach для размещения буфера, используемого в MPI_Bsend. Буферированная блокирующая операция посылки сообщения заканчивает свою работу, когда данные из программного буфера скопированы в буфер посылки.

Форматы вызовов:

MPI_Buffer_attach ( &buffer, size )
MPI_Bsend ( &buf, count, datatype, dest, tag, comm )

В нижеследующем примере, процесс 0 посылает однобайтовое сообщение процессу 1, и ждет от него аналогичного сообщения.


Основные особенности и отличия радиовещательных (коллективных) обменов данными от обменов типа "точка-точка" состоят в следующем:

  1. принимают и/или передают данные одновременно все процессы группы для указываемого коммуникатора;
  2. радиовещательная (коллективная) функция выполняет одновременно и прием, и передачу данных, а потому она имеет параметры, часть из которых относится к приему, а часть - к передаче данных;
  3. как правило, значения всех параметров (за исключением адресов буферов) должны быть идентичны во всех процессах;
  4. коллективные операции являются блокирующими;
  5. коллективные операции могут использоваться только для встроенных (predefined) MPI-типов данных, но не могут использоваться для производных (derived) MPI-типов данных.

MPI_Bcast

Посылает сообщение от процесса с рангом "root" (обычно, это процесс с рангом 0) всем другим процессам в группе.

Формат вызова:

MPI_Bcast ( &buffer, count, datatype, root, comm )

MPI_Gather

Собирает сообщения от каждого из процессов в группе в приемный буфер процесса с рангом 'root".

Формат вызова:

MPI_Gather ( &sendbuf, sendcount, sendtype, &recvbuf, recvcount,
             recvtype, root, comm )

Cледует заметить, что

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

MPI_Scatter

Эта функция является обратной к функции MPI_Gather: отдельные части передающего буфера процесса с рангом 'root& распределяются по приемным буферам всех других процессов в группе.

Формат вызова:

MPI_Scatter ( &sendbuf, sendcount, sendtype, &recvbuf, recvcount,
              recvtype, root, comm )

MPI_Allgather

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

Формат вызова:

MPI_Allgather ( &sendbuf, sendcount, sendtype, &recvbuf, recvcount,
                recvtype, comm )

MPI_Alltoall

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

Формат вызова:

MPI_Alltoall ( &sendbuf, sendcount, sendtype, &recvbuf, recvcount, 
               recvtype, comm )

В нижеследующем примере, с помощью функции MPI_Scatter строки массива рассылаются отдельным процессам:


Вывод на консоль данной программы будет таким:

rank= 0  Results: 1.000000 2.000000 3.000000 4.000000
rank= 1  Results: 5.000000 6.000000 7.000000 8.000000
rank= 2  Results: 9.000000 10.000000 11.000000 12.000000
rank= 3  Results: 13.000000 14.000000 15.000000 16.000000
< Лекция 1 || Лекция 2: 1234 || Лекция 3 >
Дмитрий Молокоедов
Дмитрий Молокоедов
Россия, Новосибирск, НГПУ, 2009
Паулус Шеетекела
Паулус Шеетекела
Россия, ТГТУ, 2010