MPI_Finalize()不会结束任何进程

问题描述 投票:2回答:4

我正在搞乱openMP,我有一个奇怪的错误。

看来,即使在MPI_Finalize()之后,每个线程都会继续运行。我已经按照简单的Hello World程序的指南,它看起来像这样:

#include <mpi.h>;

int main(int argc, char** argv) {

// Initialize the MPI environment
    MPI_Init(NULL, NULL);

// Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

// Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

// Get the name of the processor
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(processor_name, &name_len);

// Print off a hello world message
       printf("Hello world from processor %s, rank %d"
       " out of %d processors\n",
       processor_name, world_rank, world_size);

// Finalize the MPI environment.
    MPI_Finalize();

    printf("This is after finalize");
}

注意最后一个printf()...这应该只打印一次,因为并行部分已经完成,对吧?!

但是,如果我使用6个处理器运行它,那么该程序的输出是:

mpirun -np 6 ./hello_world

Hello world from processor ubuntu, rank 2 out of 6 processors
Hello world from processor ubuntu, rank 1 out of 6 processors
Hello world from processor ubuntu, rank 3 out of 6 processors
Hello world from processor ubuntu, rank 0 out of 6 processors
Hello world from processor ubuntu, rank 4 out of 6 processors
Hello world from processor ubuntu, rank 5 out of 6 processors
This is after finalize...
This is after finalize...
This is after finalize...
This is after finalize...
This is after finalize...
This is after finalize...

我误解了MPI是如何工作的吗?是否应该通过finalize停止每个线程/进程?

c parallel-processing mpi openmpi
4个回答
4
投票

这只是未定义的行为。

调用此例程后运行的进程数未定义;在调用MPI_Finalize之后,最好不要执行比返回rc更多的操作。

http://www.mpich.org/static/docs/v3.1/www3/MPI_Finalize.html


2
投票

MPI标准仅要求等级0从MPI_FINALIZE返回。我不会在这里复制整个文本,因为它相当冗长,但您可以在第8章第8.7节(启动)第359 - 361页的标准版本3.0(最近几天)中找到它。这是最相关的部分:

虽然并不要求所有进程都从MPI_FINALIZE返回,但要求至少MPI_COMM_WORLD中的进程0返回,以便用户可以知道计算的MPI部分已经结束。此外,在POSIX环境中,用户可能希望为从MPI_FINALIZE返回的每个进程提供退出代码。

甚至有一个例子正试图完全按照你的说法去做:

例8.10以下说明了要求至少一个进程返回并且已知进程0是返回的进程之一的用法。无论有多少进程返回,都希望代码如下所示。

...  
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
...
MPI_Finalize();
if (myrank == 0) {
    resultfile = fopen("outfile","w");
    dump_results(resultfile);
    fclose(resultfile);
} exit(0);

在调用MPI_FINALIZE之后,MPI标准没有说明应用程序的行为。所有这些功能都需要清理内部MPI状态,完成通信操作等。虽然在调用MPI_FINALIZE之后MPI肯定可以(并允许)杀死应用程序的其他级别,但实际上,这几乎是从来没有这样做。可能有一个反例,但我不知道。


2
投票

当我启动MPI时,我遇到了与MPI_Init和MPI_Finalize方法相同的问题。我认为这些函数之间的并行工作和外部工作串行。最后我看到了这个答案,我想出了它的功能。

J Teller的回答:https://stackoverflow.com/a/2290951/893863

int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);  
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);  
    MPI_Comm_rank(MPI_COMM_WORLD,&myid);

    if (myid == 0) { // Do the serial part on a single MPI thread
        printf("Performing serial computation on cpu %d\n", myid);
        PreParallelWork();
    }

    ParallelWork();  // Every MPI thread will run the parallel work

    if (myid == 0) { // Do the final serial part on a single MPI thread
        printf("Performing the final serial computation on cpu %d\n", myid);
        PostParallelWork();
    }

    MPI_Finalize();  
    return 0;  
}  

-1
投票

实际上,MPI_Finalize()不是并行部分的结尾,它只是所有MPI程序的结束。此外,MPI_Init()不是调用所有进程的函数调用,但是你的mpirun确实如此。 MPI只是一个在多个进程之间传递消息的库。

为了测试这一点,我们甚至可以在没有任何MPI函数调用的情况下编写程序:

#include <iostream>

int main(int argc, char *argv[]){

    int rank = 0, size = 0;

    std::cout << "Hello world from process " << rank << " of " << size << std::endl;

    return 0;

}

编译并运行:

mpicxx MPIHello.cxx -o MPIHello
mpirun -np 4 MPIHello

结果:

Hello world from process 0 of 0
Hello world from process 0 of 0
Hello world from process 0 of 0
Hello world from process 0 of 0
热门问题
推荐问题
最新问题