Теория и практика параллельных вычислений

         

Формирование сообщений при помощи упаковки и распаковки данных


Наряду с рассмотренными в п. 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 для их упаковки необходимо выполнить:

bufpos = 0; MPI_Pack(&a, 1, MPI_DOUBLE, buf, buflen, &bufpos, comm); MPI_Pack(&b, 1, MPI_DOUBLE, buf, buflen, &bufpos, comm); MPI_Pack(&n, 1, MPI_INT, buf, buflen, &bufpos, comm);

Для определения необходимого размера буфера для упаковки может быть применена функция:

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 осуществляется последовательно для распаковки всех упакованных данных, при этом порядок распаковки должен соответствовать порядку упаковки. Так, в ранее рассмотренном примере упаковки для распаковки упакованных данных необходимо выполнить:

bufpos = 0; MPI_Unpack(buf, buflen, &bufpos, &a, 1, MPI_DOUBLE, comm); MPI_Unpack(buf, buflen, &bufpos, &b, 1, MPI_DOUBLE, comm); MPI_Unpack(buf, buflen, &bufpos, &n, 1, MPI_INT, comm);

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


Содержание раздела