MPI_Init() 之前的初始化变量和 MPI_Finanlize() 之后的 cout
Posted
技术标签:
【中文标题】MPI_Init() 之前的初始化变量和 MPI_Finanlize() 之后的 cout【英文标题】:Initialized variable before MPI_Init() and cout after MPI_Finanlize() 【发布时间】:2014-08-25 04:52:43 【问题描述】:我一直在测试 mpi 如何与以下代码一起工作
#include <iostream>
#include <mpi.h>
using namespace std;
int main(int argc, char *argv[])
r = 3.0;
int id;
int p;
int a[100];
for(int i=0;i<100;++i)a[i]=i+5;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
MPI_Comm_size(MPI_COMM_WORLD, &p);
cout<<id<<" "<<r<<" "<<a[id]<<endl;
MPI_Finalize();
cout<< "Hello world " <<endl;
return 0;
我使用 30 个内核来运行代码。但输出在 2 个方面令人惊讶,
-
这里question 说如果你在 MPI_Init() 之前初始化一个变量,除了 0 之外的其他进程将对初始化值视而不见,但在我的输出文件中,所有不同 id 的进程输出 r=3 和
a[i]
的正确值,这是否意味着我可以在调用 MPI_Init() 之前初始化变量或数组,并且所有进程将共享该变量的相同值?
输出中有很多行“Hello world”,这显然表明每个进程在调用 MPI_Finalize() 后仍在打印“Hello world”,这是为什么呢?
顺便说一下,我正在使用 mpicc 来编译代码。
【问题讨论】:
【参考方案1】:在MPI_Init
之前和MPI_Finalize
之后执行代码是完全有效的。当然,你不能在该代码中使用 MPI,否则它只是普通的 C++。
MPI_Init
和 MPI_Finalize
只是库调用,它们不应该更改控制流或删除在 init 之前分配的值(这怎么可能呢?)。
MPI_Init
不会取消变量的初始化。
您所指的问题只是说进程0中的初始化不会初始化其他进程中的值。在那个问题中,数据是从可能只存在于进程 0 的文件中读取的。
请注意,MPI_Init
不会创建新进程。这不像fork
。所有进程都是在您的程序启动之前创建的(很可能是由mpirun
)。在您的情况下,每个进程都会初始化其数组。
MPI_Finalize
不会终止进程。它只关闭 MPI 库。之后进程仍会继续运行,尽管它们无法再进行交互。
【讨论】:
谢谢。我得到了第一部分。但是如果我只想打印一行“Hello World”怎么办,我脑海中的那个是if(id==0)cout<<"Hello world "<<endl
,除此之外,如何通过终止进程来打印一行?
你提出了一个完美的解决方案:如果你只需要第 0 个进程来做某事,检查它的等级(当然id
中的值在MPI_Finalize
中仍然存在)。我不知道有任何其他区分 MPI 进程的方法。
我认为MPI_Abort
会起作用。但是在尝试之后我发现调用MPI_Abort
之后即使主进程(id=0)也终止了,它根本不打印。
是的,MPI_Abort 终止所有进程。 if (id == 0)
是在“主要”过程中做某事的最简单和最理智的方法。 (顺便说一句,所有进程都是平等的,我认为我们将第 0 个进程称为“main”只是惯例。它没有任何特定的特权,它不是所有其他进程的父进程,它只是其中一个。 )
另外,实际上有可能某些实现根本不允许在MPI_INIT
之前或MPI_FINALIZE
之后执行代码。我相信 FG-MPI 会这样做,因为它实际上确实将 MPI 等级实现为线程,这些线程在 INIT
/FINALIZE
处被 fork
/join
'ed。以上是关于MPI_Init() 之前的初始化变量和 MPI_Finanlize() 之后的 cout的主要内容,如果未能解决你的问题,请参考以下文章