【问题标题】:MPI Programming in C - MPI_Send() and MPI_Recv() Address TroubleC 语言中的 MPI 编程 - MPI_Send() 和 MPI_Recv() 地址问题
【发布时间】:2014-12-02 21:38:06
【问题描述】:

我目前正在使用 MPI 编写一个 C 程序,我遇到了关于 MPI_Send() 和 MPI_Recv() 函数的障碍,希望大家能帮助我。我的目标是发送(使用 MPI_Send())和接收(使用 MPI_Recv())“a[0][0]”的地址(定义如下),然后在我之后显示该地址的内容从 MPI_Recv() 收到它,以确认我的发送和接收工作正常。我在下面概述了我的问题:

我有一个二维数组“a”,它的工作方式如下: a[0][0] 包含我的目标地址 *a[0][0] 包含我的目标值

即printf("a[0][0] Value = %3.2f, a[0][0] Address = %p\n", *a[0][0], a[0][0]);

所以,我运行我的程序并为 a 分配了内存。 Debug 确认 a[0][0] 包含地址 0x83d6260,并且存储在地址 0x83d6260 的值是 0.58。换句话说,“a[0][0] = 0x83d6260”和“*a[0][0] = 0.58”。

所以,我将地址“a[0][0]”作为 MPI_Send() 的第一个参数传递: -> MPI_Send(a[0][0], 1, MPI_FLOAT, i, 0, MPI_COMM_WORLD); // 我把 1 作为第二个参数,因为我只想接收这个地址

MPI_Send()执行返回0,即MPI_SUCCESS,表示成功,我的Debug确认“0x83d6260”就是传递的地址。

但是,当我尝试使用 MPI_Recv() 接收地址时,出现分段错误: MPI_Recv(a[0][0], 1, MPI_FLOAT, iNumProcs-1, 0, MPI_COMM_WORLD, &status);

地址 0x83d6260 已使用 MPI_Send() 成功发送,但我无法使用 MPI_Recv() 接收相同的地址。我的问题是 - 为什么 MPI_Recv() 会导致段错误?我想在 MPI_Recv() 调用之后立即打印 a[0][0] 中包含的值,但是程序崩溃了。

【问题讨论】:

    标签: c++ c mpi


    【解决方案1】:

    MPI_Send(a[0][0], 1, MPI_FLOAT ...) 将发送大小为 sizeof(float) 的内存,从 a[0][0] 开始

    所以基本上发送的值是*(reinterpret_cast<float*>(a[0][0]))

    因此,如果a[0][0] 是0x0x83d6260 并且*a[0][0] 是0.58f 那么MPI_Recv(&buff, 1, MPI_FLOAT...) 将设置buffer(float 类型,需要分配)为0.58

    重要的是不同的 MPI 程序不应该共享指针(即使它们在同一个节点上运行)。如果您能够从排名中的一个访问地址,它们不会共享虚拟内存分页和事件,如果您尝试在他们的上下文中访问相同的地址,其他的应该给您一个段错误

    编辑

    这段代码对我有用:

    #include <stdio.h>
    #include <stdlib.h>
    #include "mpi.h"
    int main(int argc, char* argv[])
    {
        int size, rank;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);
        switch(rank)
        {
            case 0:
            {
                float*** a;
                a        = malloc(sizeof(float**));
                a[0]     = malloc(sizeof(float* ));
                a[0][0]  = malloc(sizeof(float  ));
                *a[0][0] = 0.58;
                MPI_Send(a[0][0], 1, MPI_FLOAT, 1, 0, MPI_COMM_WORLD);
                printf("rank 0 send done\n");
                free(a[0][0]);
                free(a[0]   );
                free(a      );
                break;
            }
            case 1:
            {
                float buffer;
                MPI_Recv(&buffer, 1, MPI_FLOAT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                printf("rank 1 recv done : %f\n", buffer);
                break;
            }
        }
        MPI_Finalize();
        return 0;
    }
    

    结果是:

    mpicc mpi.c && mpirun ./a.out -n 2
    > rank 0 send done
    > rank 1 recv done : 0.580000
    

    【讨论】:

    • 哇,非常感谢,您说的完全正确。让你抽出时间来帮助我……我什至不知道如何感谢你。我现在在 MPI_Recv() 中获得了我想要的值。再次非常感谢您,我已经接受了您的解决方案。
    【解决方案2】:

    我认为问题在于您试图将值放入指针数组中(这可能导致段错误)。尝试创建一个新的缓冲区来接收值:

    MPI_Send(a[0][0], 1, MPI_FLOAT, i, 0, MPI_COMM_WORLD);
    
    ....
    
    double buff;
    MPI_Recv(&buff, 1, MPI_FLOAT, iNumProcs-1, 0, MPI_COMM_WORLD, &status);
    

    如果我没记错的话,MPI_Send/Recv 将取消引用给你值的指针,而不是地址。

    您也没有向我们提供足够的信息来判断您的源/目标值是否正确。

    【讨论】:

      猜你喜欢
      • 2015-12-30
      • 1970-01-01
      • 2011-11-11
      • 2015-04-22
      • 2019-03-18
      • 2015-05-14
      • 2014-04-17
      • 2011-01-24
      • 2017-10-25
      相关资源
      最近更新 更多