【MPI】 创建新组并使用组通信

0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
0(0,1,2,3) 1(0,1,2,3) 2(0,1,2,3) 3(0,1,2,3)
4(4,5,6,7) 5(4,5,6,7) 6 7
8 9 10 11
12(12,13,14,15) 13 14 15

假设有一个4*4的矩阵,并且使用16个节点,目的是想让每四个节点存放矩阵的一行,如上面的第二个表格所示,目的是想模拟简单按块矩阵乘的分配。

#include"mpi.h"

#include<stdio.h>

#include<malloc.h> 

int main( int argc, char *argv[] )

{

     int rank, size;

     int X_rank, X_size,Y_rank,Y_size;

     int *data, buf,d[4][4],dd[4],ddd; 

     MPI_Comm X_comm,Y_comm,col_comm;
     MPI_Group group_world,new_group;

     MPI_Status status;

     MPI_Request request; 

     MPI_Init(&argc, &argv);

     MPI_Comm_rank( MPI_COMM_WORLD, &rank );

     MPI_Comm_size(MPI_COMM_WORLD, &size); 
     if(rank == 0)
	     for(int i=0;i<4;i++)
		     for(int j=0;j<4;j++)
			     d[i][j] = i*4+j;


     MPI_Comm_split(MPI_COMM_WORLD, rank%4, 0, &Y_comm);
     MPI_Comm_split(MPI_COMM_WORLD, rank/4, 0, &X_comm);

     //得到新的rank和size

     MPI_Comm_rank(X_comm, &X_rank);

     MPI_Comm_size(X_comm, &X_size);     
     MPI_Comm_rank(Y_comm, &Y_rank);

     MPI_Comm_size(Y_comm, &Y_size);     
//     printf("rank: [%d],X_rank: %d, X_size:%d,Y_rank: %d, Y_size:%d\n",rank, X_rank,X_size,Y_rank,Y_size);


     MPI_Comm_group(MPI_COMM_WORLD,&group_world);
     int members[4] = {0,4,8,12};
     MPI_Group_incl(group_world,4,members,&new_group);
     MPI_Comm_create(MPI_COMM_WORLD,new_group,&col_comm);
//     MPI_Comm_create_group(MPI_COMM_WORLD,new_group,0,&col_comm);
     if(MPI_COMM_NULL != col_comm)
	     MPI_Scatter(&d[0][0], 4, MPI_INT, dd, 4,MPI_INT,0, col_comm);
     MPI_Bcast(dd,4,MPI_INT,0,X_comm);
     MPI_Barrier(X_comm);

     printf("[%d]号进程数据:%d,%d,%d,%d\n",rank, dd[0],dd[1],dd[2],dd[3]);


     MPI_Group_free(&group_world);
     MPI_Group_free(&new_group);
     if(MPI_COMM_NULL != col_comm)
             MPI_Comm_free(&col_comm);
     MPI_Comm_free(&X_comm);
     MPI_Comm_free(&Y_comm);



     MPI_Finalize(); 

    return 0;

}

在实现过程中使用到了MPI_Comm_split函数和MPI_Comm_create函数,在使用的过程中,对这两个函数的用法有了更深刻的认识。

1,MPI_Comm_split这个函数是对原通信空间按color值重新分配为新的通信组,color值相同的为一个新组。这样在一个通信空间里就会产生多个组(正常一个通信空间只包含一个组,因此当包含多个组的通信空间用法让我迷惑了好久)。因此在使用组通信如MPI_Bcast时会对这多个组分别进行通信,将某个进程的数据广播到本组内的各个线程。同时该通信空间内的其他组也按此方法进行广播。

2,MPI_Comm_create在使用的时候如果新创建的通信子所包含的通信空间不是整个进程组时(如本例程创建的col_comm通信子只包含0,4,8,12进程,不包含其他进程),在使用MPI_Scatter等组通信以及释放该通信子时需要加上判断 if(MPI_COMM_NULL != col_comm),不然会出现错误,错误信息可能是组通信或者通信子使用不正确。

eg:[ncic10195:27835] *** An error occurred in MPI_Comm_free
[ncic10195:27835] *** reported by process [2896756737,1]
[ncic10195:27835] *** on communicator MPI_COMM_WORLD
[ncic10195:27835] *** MPI_ERR_COMM: invalid communicator
[ncic10195:27835] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
[ncic10195:27835] ***    and potentially your MPI job)

[ncic10195:27200] *** An error occurred in MPI_Scatter
[ncic10195:27200] *** reported by process [2852126721,15]
[ncic10195:27200] *** on communicator MPI_COMM_WORLD
[ncic10195:27200] *** MPI_ERR_COMM: invalid communicator
[ncic10195:27200] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
[ncic10195:27200] ***    and potentially your MPI job)
 

最终结果如下:

[0]号进程数据:0,1,2,3
[1]号进程数据:0,1,2,3
[2]号进程数据:0,1,2,3
[3]号进程数据:0,1,2,3
[4]号进程数据:4,5,6,7
[5]号进程数据:4,5,6,7
[6]号进程数据:4,5,6,7
[7]号进程数据:4,5,6,7
[8]号进程数据:8,9,10,11
[9]号进程数据:8,9,10,11
[10]号进程数据:8,9,10,11
[11]号进程数据:8,9,10,11
[12]号进程数据:12,13,14,15
[13]号进程数据:12,13,14,15
[14]号进程数据:12,13,14,15
[15]号进程数据:12,13,14,15

参考内容:

https://mpitutorial.com/tutorials/introduction-to-groups-and-communicators/

发布了46 篇原创文章 · 获赞 14 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/xll_bit/article/details/103091764
mpi
今日推荐