Функция MPI_Pack упаковывает элементы предопределенного или производного типа MPI, помещая их побайтное представление в выходной буфер.
Функция MPI_Pack упаковывает incount элементов типа datatype из области памяти с начальным адресом inbuf. Результат упаковки помещается в выходной буфер с начальным адресом outbuf и размером outsize байт. Параметр position указывает текущую позицию в байтах, начиная с которой будут размещаться упакованные данные. На выходе из подпрограммы значение position увеличивается на число упакованных байт, указывая на первый свободный байт. Параметр comm при последующей посылке упакованного сообщения будет использован как коммуникатор.
Функция MPI_Unpack извлекает заданное число элементов некоторого типа из побайтного представления элементов во входном массиве.
Функция MPI_Unpack извлекает outcount элементов типа datatype из побайтного представления элементов в массиве inbuf, начиная с адреса position. После возврата из функции параметр position увеличивается на размер распакованного сообщения. Результат распаковки помещается в область памяти с начальным адресом outbuf.
Для посылки элементов разного типа из нескольких областей памяти их следует предварительно запаковать в один массив, последовательно обращаясь к функции упаковки MPI_Pack. При первом вызове функции упаковки параметр position, как правило, устанавливается в 0, чтобы упакованное представление размещалось с начала буфера. Для непрерывного заполнения буфера необходимо в каждом последующем вызове использовать значение параметра position, полученное из предыдущего вызова.
Упакованный буфер пересылается любыми коммуникационными операциями с указанием типа MPI_PACKED и коммуникатора comm, который использовался при обращениях к функции MPI_Pack.
Полученное упакованное сообщение распаковывается в различные массивы или переменные. Это реализуется последовательными вызовами функции распаковки MPI_Unpack с указанием числа элементов, которое следует извлечь при каждом вызове, и с передачей значения position, возвращенного предыдущим вызовом. При первом вызове функции параметр position следует установить в 0. В общем случае, при первом обращении должно быть установлено то значение параметра position, которое было использовано при первом обращении к функции упаковки данных. Очевидно, что для правильной распаковки данных очередность извлечения данных должна быть той же самой, как и при упаковке.
Функция MPI_Pack_size помогает определить размер буфера, необходимый для упаковки некоторого количества данных типа datatype.
Первые три параметра функции MPI_Pack_size такие же, как у функции MPI_Pack. После обращения к функции параметр size будет содержать размер сообщения в байтах после его упаковки.
Рассмотрим пример рассылки разнотипных данных из 0-го процесса с использованием функций MPI_Pack и MPI_Unpack.
Программа pack.c
#include "mpi.h" #include <stdio.h> int main(int argc,char *argv[]) { int iam,nproc; int a[2]; int position; float tmp1,tmp2; double x,y; char tmp[256]; FILE *param; char buff[100]; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&iam); MPI_Comm_size(MPI_COMM_WORLD,&nproc); if ( iam == 0) { param = fopen("param.dat","r"); fgets(tmp,256,param); sscanf(tmp,"%f %f %d %d",&tmp1,&tmp2,&a[0],&a[1]); x = tmp1; y = tmp2; position = 0; MPI_Pack(&x,1,MPI_DOUBLE,buff,100,&position,MPI_COMM_WORLD); MPI_Pack(&y,1,MPI_DOUBLE,buff,100,&position,MPI_COMM_WORLD); MPI_Pack(&a,2,MPI_INT,buff,100,&position,MPI_COMM_WORLD); fclose(param); } MPI_Bcast(buff,100,MPI_PACKED,0,MPI_COMM_WORLD); if ( iam != 0 ){ position = 0; MPI_Unpack(buff,100,&position,&x,1,MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack(buff,100,&position,&y,1,MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack(buff,100,&position,a,2,MPI_INT, MPI_COMM_WORLD); } if ( iam == nproc - 1 ) { printf("%f %f %d %d\n",x,y,a[0],a[1]); } MPI_Finalize(); return 0; }
Программа pack.f
program pack include 'mpif.h' integer i,j,IAM,NPROC,ierr integer a(2), position double precision x,y CHARACTER*100 buff CALL MPI_INIT(ierr) CALL MPI_COMM_SIZE(MPI_COMM_WORLD,NPROC,ierr) CALL MPI_COMM_RANK(MPI_COMM_WORLD,IAM,ierr) if (IAM.eq.0) then open(11,FILE='param.dat',STATUS='OLD') read(11,*) x,y, a position = 0 CALL MPI_Pack(x,1,MPI_DOUBLE_PRECISION,buff,100,position, *MPI_COMM_WORLD,ierr) CALL MPI_Pack(y,1,MPI_DOUBLE_PRECISION,buff,100,position, *MPI_COMM_WORLD,ierr) CALL MPI_Pack(a,2,MPI_INTEGER,buff,100,position, *MPI_COMM_WORLD,ierr) end if CALL MPI_Bcast(buff,100,MPI_PACKED,0,MPI_COMM_WORLD,ierr) if (IAM.ne.0) then position = 0 CALL MPI_Unpack(buff,100,position,x,1,MPI_DOUBLE_PRECISION, *MPI_COMM_WORLD,ierr) CALL MPI_Unpack(buff,100,position,y,1,MPI_DOUBLE_PRECISION, *MPI_COMM_WORLD,ierr) CALL MPI_Unpack(buff,100,position,a,2,MPI_INTEGER, *MPI_COMM_WORLD,ierr) end if if (IAM.eq.NPROC-1) then write(*,*) x,y, a end if CALL MPI_FINALIZE(ierr) end