MPI_Bcast在if语句中?

时间:2013-01-24 22:17:18

标签: c parallel-processing mpi

我正在尝试使用MPI,当我在命令行上通过mpirun运行它时,我一直收到此错误。

----------------------------------------------------------------------------------------------
mpirun noticed that the job aborted, but has no info as to the process
that caused that situation.
----------------------------------------------------------------------------------------------

我不确定为什么,因为其他mpi程序运行得非常好。

这是我的代码。

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

int func(int num){
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (num == 0){
        num = 5;
        MPI_Bcast(&num, 1, MPI_INT, rank, MPI_COMM_WORLD);
    }
    return num;
}

int main(int argc, char **argv){
    int rank, size;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    printf("On processor %d, func returns %d\n", rank, func(rank));
    MPI_Finalize();
    return 0;
}

该程序仍然给我同样的错误。 MPI_Bcast是否在if语句中无效?如果你在不是根的情况下尝试广播,它仍然有效吗?

2 个答案:

答案 0 :(得分:3)

我在任何参考文档中看到MPI_Bcast的签名是int MPI_Bcast(void* buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm)。但是,您只传递了四个参数,看起来您忘记了第一个或第二个参数。

您的案例中num是什么,缓冲区是什么?答案可能会解决您的问题,但我也不确定为什么您的代码甚至会编译。如果num是您要广播的内容,请尝试MPI_Bcast(& num, 1, MPI_INT, rank, MPI_COMM_WORLD)是否适合您。

还有另一个非常严重的独立问题。您的堆栈上有一些int rank;,并在初始化之前将其传递给MPI_Bcast。谁在发送?如果是root,您也可以通过0,或者int rank = 0;正确初始化。

rank的未确定值几乎肯定是您的工作中止的原因,因为实例将随机发送或接收。

答案 1 :(得分:3)

这段代码毫无意义。 MPI_Bcast是一个集体通信电话,这意味着,为了使操作成功完成,所提供的通信器中的所有排名(在您的情况下为MPI_COMM_WORLD必须来调用它。 MPI_Bcast也是一个 rooted 操作,这意味着有一个指定的信息源,这是具有指定排名的进程。因此,除了要求所有排名必须调用MPI_Bcast之外,所有必须还为 root 提供相同的排名。

只有当MPI_Bcast的{​​{1}}参数为num时,您的程序才会调用func,这只会在排名0中发生。在所有其他等级中0不会调用func,他们只是完成库并退出。这导致MPI_Bcast最终失败,因为它试图将消息发送到不再可用的进程,最终导致错误(“最终”,因为标准允许早期本地完成,在某些情况下,尤其是小消息,如在你的情况下,发送缓冲)。默认情况下,MPI通过中止作业而不是返回错误代码来处理错误。

没有任何东西可以阻止你从条件中调用任何MPI集合函数,但是你必须小心并确保所有级别最终都进行集体调用,无论他们采取什么代码路径来执行此操作。

MPI_Bcast的正确版本为:

func

使用“来自条件内的电话”可能是:

int func(int num) {
    if (num == 0) {
        num = 5;
    }
    MPI_Bcast(&num, 1, MPI_INT, 0, MPI_COMM_WORLD);
    return num;
}

(但这显然是不必要的)