[MPI] MPI 打包与解包 (MPI_pack、 MPI_unpack)

学习资料 《高性能计算之并行编程技术 -- MPI并行程序设计》

原理

       打包(Pack)和解包(Unpack)操作是为了发送不连续的数据, 在发送前显示地把数据包装大一个连续的缓冲区, 在接收之后从连续的缓冲区中解包。

函数

MPI_PACK

        MPI_PACK把由inbuf,incount, datatype指定的发送缓冲区中的incount个datatype类型的消息放到起始为 outbuf 的连续空间,该空间共有 outcount 个字节。 输入缓冲区可以是 MPI_SEND 允许的任何通信缓冲区。 入口参数 position 的值是输出缓冲区中用于打包的起始地址,打包后它的值根据打包消息的大小来增加, 出口参数 position 的值是被打包的消息占用的输出缓冲区后面的第一个地址。 通过连续几次对不同位置的消息调用打包操作, 就将不连续的消息放到了一个连续的空间。 comm参数是将在后面用于发送打包的消息时用的通信域。 (NOTE:这里要连续多次调用打包操作)

 函数原型

 int MPI_Pack(void* inbuf, int incount, MPI_Datatype datatype, void* outbuf, int outcount, int *position , MPI_Comm comm)

 inbuf, 输入缓冲区起始地址(可选数据类型)

 incount, 输入数据项个数(整型)

 datatype, 每个输入数据项的类型(句柄)

 outbuf, 输出缓冲区开始地址(可选数据类型)

 outcount, 输出缓冲区大小(整型)

 position, 缓冲区当前位置(整型)

 comm,通信域

 

MPI_UNPACK

       MPI_UNPACK 和 MPI_PACK 对应, 它从 inbuf 和 insize 指定的缓冲区空间将不连续的消息解开,放到 outbuf, outcount, datatype 指定的缓冲区中。 输出缓冲区可以是 MPI_RECV 允许的任何通信缓冲区。 输入缓冲区是一个连续的存储空间,大小为insize字节, 开始地址为 inbuf。入口参数 position的初始值是输出缓冲区中被打包消息占用的起始地址, 解包后它的值根据打包消息的大小来增加,因此出口参数 position的值是输出缓冲区中被解包的消息占用空间后面的第一个地址。 通过连续几次对已打包的消息调用与打包时相应的解包操作,就可以将连续的消息解开放到一个不连续的空间。comm参数是用于接收消息的通信域。

函数原型

 int  MPI_Unpack(void* inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm)

 inbuf, 输入缓冲区起始(可选数据类型)

 insize, 输入数据项数目(整型)

 position, 缓冲区当前位置,字节(整型)

  outbuf, 输出缓冲区开始(可选数据类型)

 outcount, 输出缓冲区大小,字节(整型)

 datatype, 每个输入数据项的类型(句柄)

  comm,打包的消息的通信域(句柄)

 

程序例子

#include <stdio.h>
#include "mpi.h"

//高性能计算之并行编程技术 -- MPI并行程序设计 14.6节例子
//ROOT进程将读入一个整数和一个双精度数打包,然后广播给所有进程,各进程再将数据解包后打印

int main(int argc,char **argv){
    int rank;
    int packsize, position;
    int a;
    double b;
    char packbuf[100];

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);

    do{
       if(rank==0) {
           scanf("%d %lf",&a,&b);
           packsize=0;  /*打包开始位置*/
           MPI_Pack(&a,1,MPI_INT,packbuf,100,&packsize,MPI_COMM_WORLD); /*将整数a打包*/
           MPI_Pack(&b,1,MPI_DOUBLE,packbuf,100,&packsize,MPI_COMM_WORLD); /*将双精度数b打包*/
       }  

       MPI_Bcast(&packsize,1,MPI_INT,0,MPI_COMM_WORLD); /*广播打包数据的大小*/
       MPI_Bcast(packbuf,packsize,MPI_PACKED,0,MPI_COMM_WORLD); /*广播打包的数据*/

       if(rank !=0 ){
           position=0;
           MPI_Unpack(packbuf,packsize,&position,&a,1,MPI_INT,MPI_COMM_WORLD); /*其他进程先将a解包*/
           MPI_Unpack(packbuf,packsize,&position,&b,1,MPI_DOUBLE,MPI_COMM_WORLD); /*再将b解包*/
       }  
 
       printf("Process %d got %d and %lf\n",rank,a,b);
    }while(a>=0); /*若a为负数则结束,否则继续上述过程*/

    MPI_Finalize();

    return 0;
}


 

posted on 2012-11-10 20:41  applesun0757  阅读(3505)  评论(0)    收藏  举报