Посылка сообщений в PVM предназначена для передачи данных между различными процессам и состоит из трех шагов. Во-первых, буфер данных перед посылкой должен быть проинициализирован с использованием функций pvm_initsend() или pvm_mkbuf(). Во-вторых, пересылаемые данные должны быть "упакованы" в этот буфер. Для упаковки используется некоторе количество комбинаций вызовов функции pvm_pk*(). В FORTRANе упаковка данных производится подпрограмой pvmfpack(). Третий шаг заключается в пересылке данных адресатам. Для этой цели в зависимости от списка адресатов используется вызов функции pvm_send(), в параметрах которой указывается конкретный процесс-приемник, или функции pvm_mcast(), используемой для всенаправленной передачи (то есть всем процессам сразу).
Сообщение принимается процессом-адресатом с помощью соответствующей функции, после чего происходит распаковка принятого блока, извлечение хранящихся в нем даных и заполнение ими соотвествующих локальных переменных или массивов. Процедура приема сообщений может быть сконфигурирована в нескольких вариантах:
- для приема любых сообщений
- для приема любых сообщений от определенного источника
- для приема любых сообщений с определенным message tag
- для приема любых сообщений с определенным message tag от определенного источника
Кроме того, существует функция для проверки факта доставки сообщения адресату.
Буфер сообщения
call pvmfinitsend( encoding, bufid )
Если пользователь использует только один буфер сообщения (обычно так и делается), то единственная необходимая для работы с буфером функция - это pvm_initsend(). Эта функция вызывается непосредственно перед упаковкой новой порции пересылаемых данных в буфер сообщения. Функция pvm_initsend освобождает буфер и создает новый для упаковки в него даных. Схема кодировки упаковываемых в буфер данных указывается заданием переменной encoding. Возвращаемое в переменную bufid значение является идентификатором буфера.
Переменная encoding может принимать следующие значения:
PvmDataDefault - XDR кодировка, используемая в PVM по умолчанию. Эта кодировка используется обычно в гетерогенных кластерах, когда PVM не может знать понимает ли принимающая сторона передаваемый формат данных. Например, когда данные передаются с Linux-машины на Windows-машину. В случае, когда в кластере используется только один тип операционной машины или когда пользователь уверен, что принимающая сторона поймет все правильно, следует использовать тип кодировки PvmDataRaw.
PvmDataRaw - без кодировки. Даные передаются без каких либо изменений. Если принимающая сторона не сможет правильно прочитать этот формат, это вызовет возврат кода ошибки в процессе распаковки.
PvmDataInPlace - данные остаются на месте, не перемещаясь в буфер посылки. Этот тип кодировки можно использовать для снижения накладных расходов, связанных с перемещением данных в буфер. В этом случае буфер содержит только длины и указатели на передаваемые данные. Когда вызвана pvm_send(), данные копируются непосредственно с того места, где они асположены. Использование этой кодировки накладывает одно ограничение. Передаваемые данные не должны быть изменены между моментом, когда началась их упаковка и моментом окончания передачи буфера сообщения адресату. Однако, при использовании данного типа упаковки, имеется одно заметное преимущество. Функция упаковки pvm_initsend может быть вызвана только один раз в начале прогарммы. Например в начале работы программы мы можем упаковать данные из области перекрытия (см. главу "Декомпозиция данных") и передавать их множество раз по мере необходимости.
Упаковка данных
Для FORTRANа существует только одна функция, которая управялет упаковкой данных всех типов.
call pvmfpack( what, xp, nitem, stride, info )
В пареметре what указывается тип упаковываемых данных. Параметр xp является первым элементом массива данных. Пареметры nitem и stride описаны выше. Параметр info - возвращаемое значение. Значения параметра what представлены в следующей таблице:
STRING 0 REAL4 4 BYTE1 1 COMPLEX8 5 INTEGER2 2 REAL8 6 INTEGER4 3 COMPLEX16 7
Константы, соответствующие значениям параметра what определены в файле pvm3/include/fpvm3.h. Некоторые производители могут расширять этот список дополнительными данными, например INTEGER8, REAL16 и др.
Приведем пример использования всех этих функций:
CALL PVMFINITSEND(PVMRAW, INFO) CALL PVMFPACK( INTEGER4, NSIZE, 1, 1, INFO ) CALL PVMFPACK( STRING, `row 5 of NXN matrix', 19, 1, INFO ) CALL PVMFPACK( REAL8, A(5,1), NSIZE, NSIZE , INFO ) CALL PVMFSEND( TID, MSGTAG, INFO )
Прием и посылка данных
call pvmfsend( tid, msgtag, info ) call pvmfmcast( ntask, tids, msgtag, info )
Функция pvm_send() помечает сообщение тагом msgtag и выполняет немедленную пересылку данных процессу с соответствющим идентификатором tid.
Функция pvm_mcast() помечает сообщение тагом msgtag и выполняет немедленную пересылку данных все процессам, имеющим идентификаторы, совпадающими со значениями, хранящимися в массиве tids. Длина массива tids равна ntask.
Следующие функции предназначены для совмещения работы по упаковке данных и их пересылке:
call pvmfpsend( tid, msgtag, xp, cnt, type, info )
Эти функции упаковывают массив определенного параметром type типа в буфер и передают его процессу, идентифицированному параметром tid. В FORTRANе типы данных определены так же, как и для процедуры pvmfpack().
Система PVM содержит несколько методов для организации приема сообщений. Причем отсутствует соотыктствие функций. То есть нет такого ограничения, когда сообщение, посланное процедурой pvm_psend должно быть обязательно принято процедурой с именем тип pvm_precv. Вне зависимости от того, как было послано сообщение, принято оно может быть либым из возможных вариантов. То же замечание касается адресной и мультикастной (multicast) передачи.
Следующие процедуры осуществляют блокирующий прием сообщений:
call pvmfrecv( tid, msgtag, bufid )
Эти процедуры инициируют процесс ожидания поступления сообщения, помеченного тагом msgtag от процеса с идентификатором tid (если сообщение еще не пришло). В случае, когда значения параметров tid и/или msgtag равны -1, осуществляется ожидание сообщения от любого процесса и/или сообщения с любым тагом.
После того, как сообщение получено, эти процедуры возвращают управление вызвавшей их программе, передав в bufid идентификатор буфера, в который помещено полученное сообщение. Значение bufid<0 сигнализирует о возникшей ошибке.
Аналогом блокирующей функции являются функция
call pvmfnrecv( tid, msgtag, bufid )
Параметры и возвращаемое значение этой функции аналогичны используемым в блокирующей функции. Отличие заключается в том, что вызов pvm_nrecv не инициирует процесс ожидания сообщения. В случае, если ожидаемое сообщение еще не поступило, в bufid возвращается 0. Функция pvm_nrecv может быть вызвана в процессе счета неоднократно.
В случае, когда ожидание сообщения не должно прерывать выполнение программы, для проверки факта получения сообщения можно использовать слудующую функцию:
call pvmfprobe( tid, msgtag, bufid )
Если ожидаемое сообщение еще не пришло, эта функция возвращает bufid=0. По пришествии сообщения в bufid возвращается значение отличное от нуля. Функцию можно вызывать неоднократно, заполняя время между вызовами какой-либо другой продуктивной работой. Функция pvm_probe не получает сообщение, для его получение необходимо воспользоваться одной из соответствующих функций.
Вместо последовательного вызова процедур блокирующего приема сообщения и распаковки буфера с извлечением данных в локальные переменные можно использовать функцию
call pvmfprecv( tid, msgtag, xp, cnt, type, rtid, rtag, rcnt, info )
Эту функцию можно использовать для приема сообщений, в которых содержатся однотипные данные. Вызов этой функции инициирует процесс ожидания сообщения, помеченного тагом msgtag от процесса с идентификатором tid. По поступлении сообщения pvm_precv распаковывает данные общим объемом len * (size of data type) в буфер buf.
Типы данных в FORTRAN-программах такие же, как это дано в описании функции pvmfpack.
Описание параметров функций:
| tid | ID процесса откуда мы ждем сообщение. "-1" означает "любой процесс". |
| msgtag | Ожидаемый таг сообщения. "-1" означает "любое сообщение". |
| vp | Указатель на массив (переменную) куда будут помещены полученные данные. |
| xp | Массив (переменная) куда будут помещены полученные данные. (FORTRAN) |
| cnt | Количество ожидаемых элементов указанного типа. |
| type | Тип получаемых данных (см. выше). |
| rtid | Возвращаемый параметр. ID процесса, откуда пришло сообщение. |
| rtag | Возвращаемый параметр. Таг (метка) полученного сообщения. |
| rcnt | Возвращаемый параметр. Длина полученного сообщения (кол-во элементов). |
| info | Содержит на выходе PvmOk если все нормально и отрицательное значение в случае ошибки. |
Распаковка полученных данных
Функции распаковки данных, записанных в приемном буфере, применяются в той же последовательности, в какой применялись функции упаковки данных в посылаемое сообщение.
call pvmfunpack( what, xp, nitem, stride, info )
Параметр xp - массив, куда будут помещены распакованные данные.
Параметры nitem и stride имеют тот же смысл, что и в соответствующих функциях упаковки (см. выше).
Параметр what был так же описан выше.

