天天看点

MPI子通信域Broadcast通信

MPI除了有一个默认的通信域MPI_COMM_WORLD包含所有结点之外,还可以将其分解为多个子通信域进行组内通讯。主要使用MPI_Comm_split(myComm,color,key,splitComm)这个API实现。其主要说明如下:

参数myComm是待分裂的通信域,而splitComm是分裂后的通信域。color是子域的标志,而key是结点在组内的标志。

比如如果有9个结点其rank分别为0-8;

那么用一下规则分组:

color = rank % 3

key = rank / 3

那么结点5(rank=5)就在子通信域的第3个组内(组id为2,从0开始算),在组内的标志为1。

这时如果再次调用广播MPI_Bcast函数,如果其第5个参数是SplitComm通信域的话,每个组都会由指定的root进行一次广播通讯。而这个root不在是总通讯域的id,而是在自己组内的id。如果每个组都有id为root的结点,那么每个组都要在组内进行一次广播。

下面有一段代码可以说明:

/********************************
 *author : ysc
 *email  : [email protected]
 **************************&****/

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

void main(int argc,char *argv[])
{
	MPI_Comm MyWorld, SplitWorld;
	int my_rank,group_size, Color, Key;
	char message[80] = "this is no.x node";
	
	MPI_Init(&argc, &argv);
	MPI_Comm_dup(MPI_COMM_WORLD,&MyWorld);
	MPI_Comm_rank(MyWorld,&my_rank);
	MPI_Comm_size(MyWorld,&group_size);
	
	Color=my_rank%3;
	Key=my_rank/3;

	if(my_rank/3 == 0)
		message[11] = my_rank + '0';
	
	MPI_Comm_split(MyWorld,Color,Key,&SplitWorld);

	MPI_Bcast(message,80,MPI_CHAR,0,SplitWorld);

	printf("node: %d message: %s\n",my_rank,message);

	MPI_Finalize();
}           

只有每个组内id为0的结点对message进行一次赋值,否则都是x。这个id为0的结点在自己的组内进行一次广播,同组的结点都收到了这个信息。运行结果如下:

[email protected]:~$ mpicc 1.c -o 1
[email protected]:~$ mpirun -np 9 ./1
node: 0 message: this is no.0 node
node: 6 message: this is no.0 node
node: 1 message: this is no.1 node
node: 2 message: this is no.2 node
node: 8 message: this is no.2 node
node: 5 message: this is no.2 node
node: 7 message: this is no.1 node
node: 4 message: this is no.1 node
node: 3 message: this is no.0 node
           

可以看到,每个组进行了一次广播,其他的结点都从id为0的结点收到了消息,并且广播的范围只在组内。

继续阅读