MPI_Finalize()不会结束任何进程

时间:2015-05-25 13:46:10

标签: c parallel-processing mpi openmpi

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

看来,即使在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停止每个线程/进程?

4 个答案:

答案 0 :(得分:4)

这只是未定义的行为。

  

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

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

答案 1 :(得分:2)

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

  

虽然不要求所有进程都从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标准在调用MPI_FINALIZE后没有说明应用程序的行为。所有这些功能都需要清理内部MPI状态,完成通信操作等。虽然MPI在调用{{1}后杀死应用程序的其他级别肯定是可能的(也是允许的)在实践中,这几乎不是它完成的方式。这可能是一个反例,但我不知道。

答案 2 :(得分: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;  
}  

答案 3 :(得分:-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