为什么MPI_Init之前的部分仍然是并行执行的

MPI_Init之前和MPI_Finalize之后的环境是串行的吗

背景

今天在进行MPI编程时,偶然发现MPI_Init之前和MPI_Finalize之后的部分实际上也是并行执行的.如下面的代码示例:

#include<stdio.h>
#include<mpi.h>

int main()
{
	int *argc;
	char ***argv;
	int comm_sz,myrank;
	
	printf("hello before init\n");
	
	MPI_Init(argc,argv);
	MPI_Comm_size(MPI_COMM_WORLD,&comm_sz);
	MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
	printf("hello from no.%d\n",myrank);
	MPI_Finalize();
	printf("hello after finalize\n");
	
	return 0;
}

编译之后用8个进程运行,最终的结果是三种hello语句会各输出八条,而非我们直觉上认为的只有 hello from no.%d\n会输出八条,这和我一开始看到的资料上的描述并不相符.

解决方案

在网上查找了一番之后最终找到了一个比较满意的答案:

https://stackoverflow.com/questions/47495108/cmpi-instruction-before-all-process-started

其大意为OpenMP和我们感觉上的流程相似,在并行环境初始化之前是串行的,并行的部分是通过多个线程join进来的方式实现并行,而MPI的机制则不尽相同,MPI的程序在用 mpirun -n 8指定了进程数后,整个程序都会在多个核上进行,但是这样的执行只是一个核的动作的重复,也就是多个核执行同一段代码.而MPI的作用就是调度不同的任务给不同的核,实现并行计算.因此在MPI_Init之前和MPI_Finalize之后并不是串行环境,而是多核只能执行同一段代码的并行环境.

如何串行

那我们如何在一个mpi程序中加入串行的部分呢,在上面链接中的回答中已经有举例,感兴趣的可以自行查阅,其中最简单的方法就是将需要串行执行的代码段也放到MPI_Init之后的环境中,然后用 if(rank == 0)的方式,指定某一个核执行相应的操作,变相地实现了串行.

posted @ 2022-07-22 22:37  yukina~  阅读(661)  评论(0编辑  收藏  举报