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