C MPI_Finalize()不结束任何进程

C MPI_Finalize()不结束任何进程,c,parallel-processing,mpi,openmpi,C,Parallel Processing,Mpi,Openmpi,我在玩openMPI,我有一个wierd bug 看起来,即使在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 i

我在玩openMPI,我有一个wierd bug

看起来,即使在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");
}

我是否误解了MPI的工作原理?finalize是否应该停止每个线程/进程

这只是未定义的行为

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


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

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

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

示例8.10以下说明了要求至少有一个进程返回的用法,并且已知进程0是返回的进程之一。无论有多少进程返回,都希望下面这样的代码能够正常工作


在调用
MPI\u FINALIZE
后,MPI标准没有对应用程序的行为做任何说明。所有这些功能都需要清理内部MPI状态、完成通信操作等。虽然MPI在调用
MPI\u FINALIZE
后肯定有可能(并且允许)杀死应用程序的其他列组,但实际上,这几乎从来都不是这样做的。可能有一个反例,但我没有意识到。

当我启动MPI时,我对MPI_Init和MPI_Finalize方法也有同样的问题。我认为这些函数之间是并行工作的,外部是串行工作的。最后,我看到了这个答案,并了解了它的功能

J Teller的回答:


实际上,
MPI\u 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;

}
结果:

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

是的,你误解了MPI的工作原理
mpi\u finalize
本质上是一种声明,表示此后将不再发出
mpi
指令。它不是关闭进程的指令。未指定基础系统的功能,您报告的行为是典型的。为了获得更多乐趣,请尝试将该
printf
语句复制到
mpi_init
之前。谢谢。。(你是第一个,所以请回答我可以接受:))那么我真正应该做的是把我想做的任何逻辑只放在if(world_rank==0){}中一次,以确保它只做一次?还是有更好的最佳实践?@HighPerformanceMark“一种声明,表示此后将不再发布mpi指令”这是错误的!进程必须在结束后退出。除了返回,它不应该做任何事情。请看我的答案。抱歉@addy2012,但HighPerformanceMark实际上是正确的。MPI标准中有一些语言规定了这一点(手册页不是福音)。
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;  
}  
#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