如果我正确理解您的问题,您希望同时进行逐行广播:
P00 -> P01 & P02
P10 -> P11 & P12
P20 -> P21 & P22
这可以使用子通信器来完成,例如一个只包含第 0 行的进程的子通信器,另一个只包含第 1 行的进程的子通信器,依此类推。MPI_Bcast
然后,您可以通过使用适当的通信器参数在每个子通信器中发出同时广播。
如果您首先使用笛卡尔通信器,则创建逐行子通信器非常容易。MPIMPI_CART_SUB
为此提供了操作。它是这样工作的:
// Create a 3x3 non-periodic Cartesian communicator from MPI_COMM_WORLD
int dims[2] = { 3, 3 };
int periods[2] = { 0, 0 };
MPI_Comm comm_cart;
// We do not want MPI to reorder our processes
// That's why we set reorder = 0
MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 0, &comm_cart);
// Split the Cartesian communicator row-wise
int remaindims[2] = { 0, 1 };
MPI_Comm comm_row;
MPI_Cart_sub(comm_cart, remaindims, &comm_row);
Nowcomm_row
将包含一个新子通信器的句柄,该子通信器将只跨越调用进程所在的同一行。现在只需一次调用MPI_Bcast
即可执行三个同时的逐行广播:
MPI_Bcast(&data, data_count, MPI_DATATYPE, 0, comm_row);
这是有效的,因为在位于不同行的进程中comm_row
,返回的MPI_Cart_sub
结果会有所不同。0
这是子通信器中第一个进程的等级,由于拓扑的构造方式comm_row
,它将对应。P*0
如果您不使用笛卡尔通信器而是对其进行操作MPI_COMM_WORLD
,则可以使用MPI_COMM_SPLIT
将世界通信器拆分为三个逐行子通信器。MPI_COMM_SPLIT
采用color
用于将进程分组为新的子通信器的 a - 具有相同color
最终的进程在同一个子通信器中。在您的情况下color
,应该等于调用进程所在的行数。拆分操作还需要一个key
用于对新子通信器中的进程进行排序的 a。它应该等于调用进程所在的列数,例如:
// Compute grid coordinates based on the rank
int proc_row = rank / 3;
int proc_col = rank % 3;
MPI_Comm comm_row;
MPI_Comm_split(MPI_COMM_WORLD, proc_row, proc_col, &comm_row);
将再次comm_row
包含一个子通信器的句柄,它只跨越与调用进程相同的行。