为什么这两个MPI发送的行为有所不同?

时间:2012-09-30 16:39:48

标签: c mpi

我在MPI进程之间有一个类似模式通信的管道。其中进程将消息作为管道阶段发送给对方。 以下示例显示了以这种模式进行通信的三个进程。

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

    //declare stage function
    void* testcall(void* d);

    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 k;  
            int x[3] = {10,11,12};
            void* data = malloc(sizeof(int));             
            for( k=0 ; k< 3;k++){           
                data = &x[k];           
                MPI_Send(data,4,MPI_BYTE,1,0,MPI_COMM_WORLD);   
            }
        }

        if(rank==1){                                
            void* rcv = malloc(sizeof(int));
            void* snd = malloc(sizeof(int));
            int k;
            for( k=0 ; k< 3;k++){
                MPI_Recv(rcv,4,MPI_BYTE,0,0,MPI_COMM_WORLD,&status);              
                snd = testcall(rcv);                        
                int z = *(int *) snd;  
                printf("RCV 1: %d \n",z);
                MPI_Send(&snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);
            }
        }

        if(rank==2){
            void* rcv2 = malloc(sizeof(int));
            void* snd2 = malloc(sizeof(int));
            int k;
            for( k=0 ; k< 3;k++){
                MPI_Recv(rcv2,4,MPI_BYTE,1,0,MPI_COMM_WORLD,&status);
                snd2 = testcall(rcv2);
                int z = *(int *) snd2;
                printf("RCV 2: %d \n",z);
            }
        }

        MPI_Finalize();
        return 0;
    }

    void* testcall(void* d){
        int z = *(int *) d;
        int k = z * 2;
        void* rslt = malloc(sizeof(int));
        rslt = &k;
        return rslt;
    }

输出:

RCV1:20

RCV1:22

RCV1:24

RCV:2136566600

RCV:2136566600

RCV:2136566600

我的代码有一个问题。从进程0发送到进程1成功,并在打印时给我正确的信息。

从进程1发送到进程2似乎成功,但是当我尝试打印时,它只是一个意外的数字(如上面的输出所示)。

我不明白为什么这两个发送的行为有所不同。 (两者都发送一个由void指针指向的值。为什么第二次发送是错误的)?

请帮忙。

1 个答案:

答案 0 :(得分:2)

void* testcall(void* d){
    int z = *(int *) d;
    int k = z * 2;
    void* rslt = malloc(sizeof(int));
    rslt = &k;
    return rslt;
}

此代码不能满足您的期望。 rslt = &k;行使用rslt的地址覆盖k指针的值(您可以在其他几个语句中执行此操作)。首先,这会导致内存泄漏,因为malloc分配的内存区域的地址会丢失。其次,k是一个自动(堆栈)变量,其位置将在testcall返回后用于其他目的。它仅适用于您的情况,因为testcall()int z = *(int *) snd;之间不存在其他函数调用。正确的功能应该是:

void* testcall(void* d){
    int z = *(int *) d;
    int k = z * 2;
    int* rslt = malloc(sizeof(int));
    *rslt = k;
    return rslt;
}

然后这行来自等级1代码:

MPI_Send(&snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);

snd本身就是一个指针。您正在发送指针的地址,这就是为什么等级2打印奇怪值的原因。正确的陈述应为:

MPI_Send(snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);

输出:

RCV 1: 20
RCV 1: 22
RCV 1: 24
RCV 2: 40
RCV 2: 44
RCV 2: 48