我正在搞乱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停止每个线程/进程?
答案 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