MPI 打包与解包函数 MPI_Pack(),MPI_Unpack()


▶ MPI 中与数据打包传输有关的几个函数

● 函数 MPI_Pack() 与 MPI_Unpack() 的原型

 1 MPI_METHOD MPI_Pack(
 2     _In_opt_ const void* inbuf,               // 指向待打包数据的指针
 3     _In_range_(>= , 0) int incount,           // 带打包数据元素个数
 4     _In_ MPI_Datatype datatype,               // 数据类型 
 5     _mpi_writes_bytes_(outsize) void* outbuf, // 指向打包输出缓冲区的指针
 6     _In_range_(>= , 0) int outsize,           // 缓冲区大小(单位为 Byte)
 7     _mpi_position_(outsize) int* position,    // 输出缓冲区中第一个用于打包的位置(地址偏移量)
 8     _In_ MPI_Comm comm                        // 通信子
 9 );
10 
11 MPI_METHOD MPI_Unpack(
12     _mpi_reads_bytes_(insize) const void* inbuf,// 指向待解包缓冲区的指针
13     _In_range_(>= , 0) int insize,              // 缓冲区大小(单位为 Byte)
14     _mpi_position_(insize) int* position,       // 输出缓冲区中第一个用于打包的位置(地址偏移量)
15     _When_(insize > 0, _Out_opt_) void* outbuf, // 指向解包后数据的指针
16     _In_range_(>= , 0) int outcount,            // 解包元素个数
17     _In_ MPI_Datatype datatype,                 // 数据类型
18     _In_ MPI_Comm comm                          // 通信子
19 );

● 使用范例

 1 int main(int argc, char *argv[])
 2 {
 3     int rank, size, i, position;
 4     char c[100], buffer[110];// 缓冲区大小 110,即 110 Byte
 5 
 6     MPI_Init(&argc, &argv);
 7     MPI_Comm_size(MPI_COMM_WORLD, &size);
 8     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 9 
10     position = 0;   // position 需要赋值为一个非负数,否则报错(?)
11     if (rank == 0)  // 0 号进程打包 1 个整形变量和 1 个字符型数组到同一片内存中,发送给 1 号进程
12     {
13         for (i = 0; i < 100; c[i] = i, i++);
14         i = 120994;
15         MPI_Pack(&i, 1, MPI_INT, buffer, 110, &position, MPI_COMM_WORLD);// 打包和解包缓冲区时要注明大小(单位为 Byte)
16         MPI_Pack(c, 100, MPI_CHAR, buffer, 110, &position, MPI_COMM_WORLD);
17         MPI_Send(buffer, position, MPI_PACKED, 1, 0, MPI_COMM_WORLD);
18     }
19     if (rank == 1)
20     {
21         MPI_Recv(buffer, 110, MPI_PACKED, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
22         MPI_Unpack(buffer, 110, &position, &i, 1, MPI_INT, MPI_COMM_WORLD);
23         MPI_Unpack(buffer, 110, &position, c, 100, MPI_CHAR, MPI_COMM_WORLD);
24         printf("i=%d, c[0] = %d, c[99] = %d\n", i, (int)c[0], (int)c[99]);
25         fflush(stdout);
26     }
27 
28     MPI_Finalize();
29     return 0;
30 }

● 输出结果

D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n 2 -l MPIProjectTemp.exe
[1]i=120994, c[0] = 0, c[99] = 99

 

▶ 函数 MPI_Size(),计算打包所需的缓冲区大小。上面的打包和解包过程中使用的是静态内存空间,对于较为复杂的数据类型,可以用 MPI 内建函数来计算需要的空间大小,防止缓冲区不足或者空间浪费。

● 函数原型

1 MPI_METHOD MPI_Pack_size(
2     _In_range_(>= , 0) int incount,         // 数据数量
3     _In_ MPI_Datatype datatype,             // 数据类型
4     _In_ MPI_Comm comm,                     // 通信子
5     _mpi_out_(size, MPI_UNDEFINED) int *size// 输出所需尺寸(单位为 Byte)
6 );

● 使用范例

 1 {
 2     int size,a[10000];
 3     char *buffer;
 4     MPI_Datatype col;
 5     MPI_Type_vector(10, 1, 100, MPI_INT, &col);
 6     MPI_Type_commit(&col);                            // 声明并提交一个数据类型
 7     MPI_Pack_size(1, col, MPI_COMM_WORLD, &size);     // 计算打包一个这样的类型需要的空间大小
 8     buffer = (char *)malloc((unsigned)size);          // 动态声明一个缓冲区用于打包
 9     MPI_Pack(a, 1, col, buffer, size, &position, MPI_COMM_WORLD);
10 }

 

▶ 函数 MPI_Pack_external(),MPI_Unpack_external(),MPI_Pack_external_size(),与上面的打包、解包、求大小函数类似,将需要打包的数据转换成连续的内存空间进行传递

● 函数原型,相比上面的打包、解包、求空间大小的函数,多了数据描述参数,少了通信子参数

 1 MPI_METHOD MPI_Pack_external(
 2     _In_z_ const char* datarep,               // 数据描述,与保存格式有关,不能随意写
 3     _In_opt_ const void* inbuf,               
 4     _In_range_(>= , 0) int incount,
 5     _In_ MPI_Datatype datatype,
 6     _mpi_writes_bytes_(outsize) void* outbuf,
 7     _In_range_(>= , 0) MPI_Aint outsize,
 8     _mpi_position_(outsize) MPI_Aint* position
 9 );
10 
11 MPI_METHOD MPI_Unpack_external(
12     _In_z_ const char* datarep,
13     _In_reads_bytes_opt_(insize) const void* inbuf,
14     _In_range_(>= , 0) MPI_Aint insize,
15     _mpi_position_(insize) MPI_Aint* position,
16     _When_(insize > 0, _Out_opt_) void* outbuf,
17     _In_range_(>= , 0) int outcount,
18     _In_ MPI_Datatype datatype
19 );
20 
21 MPI_METHOD MPI_Pack_external_size(
22     _In_z_ const char* datarep,
23     _In_range_(>= , 0) int incount,
24     _In_ MPI_Datatype datatype,
25     _Out_ MPI_Aint* size
26 );

● 使用范例

 1 {
 2     int comSize, comRank;
 3     MPI_Aint dataSize, position;
 4     double data[5];
 5     char *buf;
 6 
 7     MPI_Init(&argc, &argv);    
 8     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
 9     
10     MPI_Pack_external_size("external32", 5, MPI_DOUBLE, &dataSize);
11     buf = (char *)malloc(dataSize);
12 
13     position = 0;
14     if (comRank == 0)
15     {                 
16         MPI_Pack_external("external32", &data, 5, MPI_DOUBLE, buf, dataSize, &position);
17         MPI_Send(buf, position, MPI_PACKED, 1, 0, MPI_COMM_WORLD);
18     }
19     else
20     {
21         MPI_Recv(buf, dataSize, MPI_PACKED, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);        
22         MPI_Unpack_external("external32", buf, dataSize, &position, &data, 5, MPI_DOUBLE);
23     }
24     MPI_Finalize();
25     return 0;
26 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM