使用MPI_BYTE接收任何数据类型

时间:2012-09-28 09:45:22

标签: c mpi

我有一些特殊问题:在一个简单的MPI_Send / MPI_Recv程序中,假设我们知道要发送的消息类型,但在接收端我们不知道我们将收到哪种类型的数据。

所以我尝试首先尝试如下:

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

    int main(int args, char** argv){
            int rank, size;
            MPI_Status status;
            MPI_Init(&args,&argv);
            MPI_Comm_rank(MPI_COMM_WORLD,&rank);
            MPI_Comm_size(MPI_COMM_WORLD,&size);

            if(rank==0){
                    int x = 10;
                    MPI_Send(&x,4,MPI_BYTE,1,0,MPI_COMM_WORLD);
            }
            if(rank==1){
                    void* datax;
                    int count = sizeof(int);
                    datax = malloc(count);
                    MPI_Recv(datax,count,MPI_BYTE,0,0,MPI_COMM_WORLD,&status);
                    //Now check if the value is received correctly
                    int z = (int) datax;
                    printf("RCV: %d \n",z);
            }

            MPI_Finalize();
            return 0;
    }

程序正确编译并运行,但收到​​的值是一些内存垃圾值不正确(在这种情况下为10)。

有什么建议吗?

感谢,

1 个答案:

答案 0 :(得分:4)

虽然你的评论解决了编程错误,但在MPI中发送和接收未知类型(甚至是未知大小)的数据的方法要好得多。

区分不同消息类型的一种常用方法是为每种类型使用不同的标记号。在您的代码中,您在MPI_Send电话中使用了标签号0。使用描述邮件类型的标记号,然后在MPI_Recv调用之前使用MPI_Probe找出您将要收到的邮件类型。例如,您的代码可以像这样修改:

if (rank == 0) {
    MPI_Send(data_buf, data_size, MPI_BYTE, 1, tag_that_describes_message_type, MPI_COMM_WORLD)
} else if (rank == 1) {
    MPI_Status status;
    // Probe for a message coming from rank 0 with any tag.
    MPI_Probe(0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    // Find out what type of message is ready to be received by accessing the MPI_TAG variable in the status struct
    if (status.MPI_TAG == 0) {
        // Receive messages of this type. Maybe you sent an array of ints?
        MPI_Recv(...)
    } else if (status.MPI_TAG == 1) {
        // Receive messages of this type. Maybe you sent an array of floats? Handle it here.
        MPI_Recv(...)
    } else if ...

MPI_Probe也可用于在收到消息之前查找消息的大小,从而允许您动态接收几乎任何类型的消息。有关为此目的使用MPI_Probe的更好解释和说明,请转到this tutorial

如果您需要发送大量不同类型的数据(太多而无法使用标记号进行枚举),请将您的邮件打包到Google Protocol Buffer,然后将其作为MPI_BYTE的数组接收(就像您一样)在您的示例中执行),然后在接收方将其解压缩。协议缓冲区的C实现是here