【问题标题】:why this two MPI Sends behave differently?为什么这两个 MPI 发送行为不同?
【发布时间】:2012-09-21 16:41:02
【问题描述】:

我在 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 指针指向的值。为什么第二次发送是错误的)??

请帮忙。

【问题讨论】:

  • 你使用void指针和MPI_BYTE而不是intMPI_INT有什么特别的原因吗?
  • 是的,我正在尝试使每个阶段调用的函数都通用。每个函数都将接受 void* 参数并返回 void* 假设用户将使用此原型定义一个函数,并以字节为单位指定输入和输出的大小。

标签: c mpi


【解决方案1】:
void* testcall(void* d){
    int z = *(int *) d;
    int k = z * 2;
    void* rslt = malloc(sizeof(int));
    rslt = &k;
    return rslt;
}

此代码没有达到您的预期。 rslt = &amp;k; 行用k 的地址覆盖rslt 指针的值(您可以在其他几个语句中执行此操作)。首先,这会导致内存泄漏,因为由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;
}

那么第一行代码中的这一行:

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

snd 本身就是一个指针。您正在发送指针的地址,这就是为什么 rank 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

【讨论】:

    猜你喜欢
    • 2015-10-27
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 2018-01-28
    相关资源
    最近更新 更多