Главная страница

Учебное пособие саранск издательство свмо 2013 2 удк 004. 42 Ббк з97 Авторский знак о753


Скачать 6.58 Mb.
НазваниеУчебное пособие саранск издательство свмо 2013 2 удк 004. 42 Ббк з97 Авторский знак о753
Дата03.04.2022
Размер6.58 Mb.
Формат файлаpdf
Имя файлаParProg_MPI_OpenMP.pdf
ТипУчебное пособие
#439244
страница2 из 8
1   2   3   4   5   6   7   8
int MPI_Comm_size(MPI_Comm comm, int *size),
• comm — коммуникатор, размер которого определяется,
• size — определяемое количество процессов в коммуникаторе.
Для определения ранга процесса используется функция:
int MPI_Comm_rank(MPI_Comm comm, int *rank), где
• comm — коммуникатор, в котором определяется ранг процесса,
• rank — ранг процесса в коммуникаторе.
Как правило, вызов функций MPI_Comm_size и MPI_Comm_rank выполняется сразу после MPI_Init для получения общего количества процессов и ранга текущего процесса:
#include "mpi.h"
int main(int argc, char *argv[]) {
int ProcNum, ProcRank;
<программный код без использования функций MPI>
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
<программный код с использованием функций MPI>
MPI_Finalize();
<программный код без использования функций MPI>
return 0;
}
Следует отметить:

13
 коммуникатор MPI_COMM_WORLD, как отмечалось ранее, создается по умолчанию и представляет все процессы выполняемой параллельной программы;
 ранг, получаемый при помощи функции MPI_Comm_rank, является рангом процесса, выполнившего вызов этой функции, т. е. переменная ProcRank примет различные значения у разных процессов [9].
2.3 Типы данных
MPI допускает возможность запуска процессов параллельной программы на компьютерах различных платформ, обеспечивая при этом автоматическое преобразование данных при пересылках. В таблице приведено соответствие предопределенных в MPI типов стандартным типам языка С.
Таблица 2.1. Соответствие типов данных в С и MPI
тип MPI
тип языка C
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
В таблице 2.1 перечислен обязательный минимум поддерживаемых стандартных типов, однако, если в базовой системе представлены и другие типы, то их поддержку будет осуществлять и MPI, например, если в системе есть поддержка комплексных переменных двойной точности
DOUBLE
COMPLEX, то будет присутствовать тип
MPI_DOUBLE_COMPLEX.
Типы
MPI_BYTE и
MPI_PACKED используются для передачи двоичной информации без какого-либо преобразования. Кроме того, программисту предоставляются средства создания собственных типов на базе стандартных [10].

14
2.4 Процедуры передачи/приема сообщений между отдельными
процессами
Все процедуры передачи сообщений в MPI можно разделить на две группы. В одну группу входят процедуры, которые предназначены для взаимодействия только двух процессоров программы. Такие операции называются операциями типа точка-точка. Процедуры другой группы предполагают, что в операцию должны быть вовлечены все процессы некоторого коммуникатора. Такие операции называются коллективными.
Рассмотрим первый тип операций. В таких взаимодействиях участвуют два процесса, один из которых является отправителем сообщения, а второй – получателем. Процесс-отправитель вызывает одну из процедур передачи данных и явно указывает номер получателя в некотором коммуникаторе, а процесс-получатель вызывает одну из процедур приема с указанием того же коммуникатора, причем в некоторых случаях он может не знать точный номер процесса- отправителя в данном коммуникаторе.
Все процедуры данной группы делятся на два класса: процедуры с блокировкой (с синхронизацией) и процедуры без блокировки
(асинхронные). Процедуры с блокировкой приостанавливают работу процесса до выполнения некоторого условия, а возврат из асинхронных процедур происходит немедленно после инициализации соответствующей коммуникационной операции. Использование синхронных процедур может привести к тупиковым ситуациям. Использование асинхронных операций к тупиковым ситуациям не приводит, однако требует более аккуратного использования массивов данных.
2.4.1 Обмен сообщениями с блокировкой
Для передачи сообщения процесс-отправитель должен выполнить функцию:
int MPI_Send(void *buf, int count, MPI_Datatype type, int dest, int tag,
MPI_Comm comm), где
• buf — адрес буфера памяти, в котором располагаются данные отправляемого сообщения;
• count — количество элементов данных в сообщении;
• type — тип элементов данных пересылаемого сообщения;
• dest — ранг процесса, которому отправляется сообщение;
• tag — значение-тег, используемое для идентификации сообщения;
• comm — коммуникатор, в рамках которого выполняется передача данных [4].

15
Следует отметить:
• отправляемое сообщение определяется через указание блока памяти (буфера), в котором это сообщение располагается. Используемая для указания буфера триада (buf, count, type) входит в состав параметров практически всех функций передачи данных;
• процессы, между которыми выполняется передача данных, в обязательном порядке должны принадлежать коммуникатору, указываемому в функции MPI_Send;
• параметр tag используется только при необходимости различения передаваемых сообщений, в противном случае в качестве значения параметра может быть использовано произвольное положительное целое число
(см. также описание функции MPI_Recv).
Сразу же после завершения функции MPI_Send процесс- отправитель может начать повторно использовать буфер памяти, в котором располагалось отправляемое сообщение. Также следует понимать, что в момент завершения функции MPI_Send состояние самого пересылаемого сообщения может быть совершенно различным: сообщение может располагаться в процессе-отправителе, может находиться в состоянии передачи, может храниться в процессе-получателе или же может быть принято процессом-получателем при помощи функции
MPI_Recv. Тем самым, завершение функции MPI_Send означает лишь, что операция передачи начала выполняться и пересылка сообщения рано или поздно будет выполнена.
Чтобы расширить возможности передачи сообщений, в MPI введены дополнительные три процедуры. Все параметры у этих процедур такие же, как и у MPI_Send, однако у каждой из них есть своя особенность.
MPI предоставляет следующие модификации процедуры передачи данных с блокировкой MPI_Send:

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

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

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

MPI_RSend – передача сообщений по готовности. Данной процедурой можно воспользоваться только в том случае, если процесс- получатель уже инициировал прием сообщения. В противном случае вызов процедуры является ошибочным и результат ее выполнения не определен. Гарантировать инициализацию приема сообщения перед вызовом процедуры MPI_RSend можно с помощью операций, осуществляющих явную или неявную синхронизацию процессов
(например, MPI_Barrier или MPI_SSend). Во многих реализациях процедура сокращает протокол взаимодействия между отправителем и получателем, уменьшая накладные расходы на организацию передачи данных.
Для приема сообщения процесс-получатель должен выполнить функцию:
int MPI_Recv(void *buf, int count, MPI_Datatype type, int source, int
tag, MPI_Comm comm, MPI_Status *status), где
• buf, count, type — буфер памяти для приема сообщения, назначение каждого отдельного параметра соответствует описанию в MPI_Send;
• source — ранг процесса, от которого должен быть выполнен прием сообщения;
• tag — тег сообщения, которое должно быть принято для процесса;
• comm — коммуникатор, в рамках которого выполняется передача данных;
• status – указатель на структуру данных с информацией о результате выполнения операции приема данных.
Следует отметить:
• буфер памяти должен быть достаточным для приема сообщения.
При нехватке памяти часть сообщения будет потеряна и в коде завершения функции будет зафиксирована ошибка переполнения; с другой стороны, принимаемое сообщение может быть и короче, чем размер приемного буфера, в таком случае изменятся только участки буфера, затронутые принятым сообщением;
• типы элементов передаваемого и принимаемого сообщения должны совпадать;
• при необходимости приема сообщения от любого процесса- отправителя для параметра source может быть указано значение

17
MPI_ANY_SOURCE (в отличие от функции передачи MPI_Send, которая отсылает сообщение строго определенному адресату);
• при необходимости приема сообщения с любым тегом для параметра tag может быть указано значение MPI_ANY_TAG (при использовании функции MPI_Send должно быть указано конкретное значение тега);
• в отличие от параметров "процесс-получатель" и "тег", параметр "коммуникатор" не имеет значения, означающего "любой коммуникатор";
• параметр status позволяет определить ряд характеристик принятого сообщения:
status.MPI_SOURCE — ранг процесса-отправителя принятого сообщения;
status.MPI_TAG — тег принятого сообщения.
Приведенные значения MPI_ANY_SOURCE и MPI_ANY_TAG иногда называют джокерами.
Значение переменной status позволяет определить количество элементов данных в принятом сообщении при помощи функции:
int MPI_Get_count(MPI_Status *status, MPI_Datatype type,int
*count), где
• status — статус операции MPI_Recv;
• type — тип принятых данных;
• count — количество элементов данных в сообщении.
Вызов функции MPI_Recv не обязан быть согласованным со временем вызова соответствующей функции передачи сообщения
MPI_Send – прием сообщения может быть инициирован до момента, в момент или после момента начала отправки сообщения.
По завершении функции MPI_Recv в заданном буфере памяти будет располагаться принятое сообщение. Так как функция MPI_Recv является блокирующей для процесса-получателя, его выполнение приостанавливается до завершения работы функции. Таким образом, если по каким-то причинам ожидаемое для приема сообщение будет отсутствовать, выполнение параллельной программы будет блокировано.
2.4.2 Обмен сообщениями без блокировки
В отличие от функций с блокировкой, возврат из функций данной группы происходит сразу без какой-либо блокировки процессов. На фоне дальнейшего выполнения программы одновременно происходит и обработка асинхронно запущенной операции. Данная возможность полезна для создания эффективных программ. В самом деле, программист знает, что в некоторый момент ему потребуется массив, который вычисляет другой процесс. Он заранее выставляет в программе

18 асинхронный запрос на получение данного массива, а до того момента, когда массив реально потребуется, он может выполнять любую другую полезную работу. Опять же, во многих случаях совершенно не обязательно дожидаться окончания посылки сообщения для выполнения последующих вычислений.
int MPI_Isend(void* buf, int count, MPI_Datatype type,int dest, int tag,
MPI_Comm comm, MPI_Request *request)
• buf — адрес буфера памяти, в котором располагаются данные отправляемого сообщения;
• count — количество элементов данных в сообщении;
• type — тип элементов данных пересылаемого сообщения;
• dest — ранг процесса, которому отправляется сообщение;
• tag — значение-тег, используемое для идентификации сообщения;
• comm — коммуникатор, в рамках которого выполняется передача данных;
• request – имя (заголовка) запроса
Неблокированая передача данных инициализирует посылающее действие, но не заканчивает его. Функция возвратит управление прежде, чем сообщение скопировано вне посылающегося буфера.
Неблокированная посылающая функция указывает, что система может начинать копировать данные вне посылающегося буфера. Посылающий процесс не должен иметь доступа к посылаемому буферу после того, как неблокированное посылающее действие инициировано, до тех пор, пока функция завершения не возвратит управление.
int MPI_Irecv(void* buf, int count, MPI_Datatype type, int source, int
tag, MPI_Comm comm, MPI_Request *request)
• buf — адрес буфера памяти, в котором располагаются данные получаемого сообщения;
• count — количество элементов данных в сообщении;
• type — тип элементов данных;
• source — ранг процесса, от которого должен быть выполнен прием сообщения;
• tag — тег сообщения, которое должно быть принято для процесса;
• comm — коммуникатор, в рамках которого выполняется передача данных;
• request – имя (заголовка) запроса.
Неблокированный прием данных инициализирует получающее действие, но не заканчивает его. Функция возвратит управление прежде, чем сообщение записано в буфер приема данных. Неблокированная получающая функция указывает, что система может начинать писать данные в буфер приема данных. Приемник не должен иметь доступа к

19 буферу приема после того, как неблокированное получающее действие инициировано, до тех пор, пока функция завершения не возвратит управление.
Эти обе функции размещают данные в системном буфере и возвращают заголовок этого запроса в request. Request используется, чтобы опросить состояние связи.
Чтобы закончить неблокированные посылку и получение данных, используются завершающиефункции MPI_Wait и MPI_Test. Завершение посылающего процесса указывает, что он теперь свободен к доступу посылающегося буфера. Завершение получающего процесса указывает, что буфер приема данных содержит сообщение, приемник свободен к его доступу.
int MPI_Wait(MPI_Request *request, MPI_Status *status)
• request – имя запроса;
• status – статус объекта;
Запрос к MPI_Wait возвращает управление после того, как операция, идентифицированная request, выполнилась. Это блокированная функция.
Если объект системы, указанный request, был первоначально создан неблокированными посылающей или получающей функциями, то этот объект освобождается функцией MPI_Wait, и request устанавливается в
MPI_REQUEST_NULL.
Статус объекта содержит информацию относительно выполненной операции.
int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status)
• request – имя запроса;
• flag – true, если операция выполнилась, иначе false;
• status – статус объекта
Запрос к MPI_TEST возвращает flag = true, если операция, идентифицированная request, выполнилась. В этом случае статус состояния содержит информацию относительно законченной операции.
Если объект системы, указанный request, был первоначально создан неблокированными посылающей или получающей функциями, то этот объект освобождается функцией MPI_TEST, и request устанавливается в
MPI_REQUEST_NULL.
Запрос возвращает flag = false, если операция не выполнилась. В этом случае значение статуса состояния не определено. Это неблокированная функция [8].
2.4.3 Обмен сообщениями при помощи одной функции
В MPI есть группа процедур, совмещающих функции приема и передачи. Они достаточно часто применяются при программировании "каскадных" или "линейных" схем, когда необходимо осуществлять обмен

20 однотипными данными между процессорами. Примером является функция:
int MPI_Sendrecv (void* sendbuffer, int sendcount, MPI_Datatype
senddatatype, int dest, int sendtag, void* recvbuffer, int recvcount,
MPI_Datatype recvdatatype, int src, int recvtag MPI_Comm comm,
MPI_Status* status), где
• sendbuffer – адрес массива передаваемых данных;
• sendcount – количество элементов в массиве;
• senddatatype – тип передаваемых элементов;
• dest – ранг адресата;
• sendtag – тег передаваемого сообщения;
• recvbuffer – адрес буфера для приема;
• recvcount – количество элементов в буфере приема;
• recvdatatype – тип элементов в буфере приема;
• src – ранг источника;
• recvtag – тег принимаемого сообщения;
• comm – коммуникатор;
1   2   3   4   5   6   7   8


написать администратору сайта