Формирование сообщений при помощи упаковки и распаковки данных
Наряду с рассмотренными в п. 5.5.2 методами конструирования производных типов в MPI предусмотрен и явный способ сборки и разборки сообщений, содержащих значения разных типов и располагаемых в разных областях памяти.
Для использования данного подхода должен быть определен буфер памяти достаточного размера для сборки сообщения. Входящие в состав сообщения данные должны быть упакованы в буфер при помощи функции:
int MPI_Pack(void *data, int count, MPI_Datatype type, void *buf, int bufsize, int *bufpos, MPI_Comm comm),
где
data — буфер памяти с элементами для упаковки;
count — количество элементов в буфере;
type — тип данных для упаковываемых элементов;
buf — буфер памяти для упаковки;
bufsize — размер буфера в байтах;
bufpos — позиция для начала записи в буфер (в байтах от начала буфера);
comm — коммуникатор для упакованного сообщения.
Функция MPI_Pack упаковывает count элементов из буфера data в буфер упаковки buf, начиная с позиции bufpos. Общая схема процедуры упаковки показана на рис. 5.8а.
Рис. 5.8. Общая схема упаковки и распаковки данных
Начальное значение переменной bufpos должно быть сформировано до начала упаковки и далее устанавливается функцией MPI_Pack. Вызов функции MPI_Pack осуществляется последовательно для упаковки всех необходимых данных. Так, в ранее рассмотренном примере набора переменных a, b и n для их упаковки необходимо выполнить:
Для определения необходимого размера буфера для упаковки может быть применена функция:
int MPI_Pack_size(int count, MPI_Datatype type, MPI_Comm comm, int *size),
где
count — количество элементов в буфере;
type — тип данных для упаковываемых элементов;
comm — коммуникатор для упакованного сообщения;
size — рассчитаный размер буфера.
После упаковки всех необходимых данных подготовленный буфер может быть использован в функциях передачи данных с указанием типа MPI_PACKED.
После получения сообщения с типом MPI_PACKED данные могут быть распакованы при помощи функции:
int MPI_Unpack(void *buf, int bufsize, int *bufpos, void *data, int count, MPI_Datatype type, MPI_Comm comm),
где
buf — буфер памяти с упакованными данными;
bufsize — размер буфера в байтах;
bufpos — позиция начала данных в буфере (в байтах от начала буфера);
data — буфер памяти для распаковываемых данных;
count — количество элементов в буфере;
type — тип распаковываемых данных;
comm — коммуникатор для упакованного сообщения.
Функция MPI_Unpack распаковывает, начиная с позиции bufpos, очередную порцию данных из буфера buf и помещает распакованные данные в буфер data. Общая схема процедуры распаковки показана на рис. 5.8б.
Начальное значение переменной bufpos должно быть сформировано до начала распаковки и далее устанавливается функцией MPI_Unpack. Вызов функции MPI_Unpack осуществляется последовательно для распаковки всех упакованных данных, при этом порядок распаковки должен соответствовать порядку упаковки. Так, в ранее рассмотренном примере упаковки для распаковки упакованных данных необходимо выполнить:
В заключение выскажем ряд рекомендаций по применению упаковки для формирования сообщений. Поскольку такой подход приводит к появлению дополнительных действий по упаковке и распаковке данных, то данный способ может быть оправдан при сравнительно небольших размерах сообщений и при малом количестве повторений. Упаковка и распаковка может оказаться полезной при явном использовании буферов для буферизованного способа передачи данных.