2

我有一些特殊的问题:在一个简单的 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)。

请问有什么建议吗?

谢谢,

4

1 回答 1

4

尽管您的评论解决了您的编程错误,但在 MPI 中发送和接收未知类型(甚至未知大小)的数据有更好的方法。

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

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用于此目的的更好解释和说明,请转到本教程

如果您需要发送广泛不同类型的数据(太多而无法用标签号枚举),请将您的消息打包到Google Protocol Buffer中,将其作为 s 数组接收MPI_BYTE(就像您在示例中所做的那样),然后将其解包在接收方。协议缓冲区的 AC 实现在这里

于 2012-11-28T02:32:40.640 回答