我有一个2D处理器网格(3 * 3):
P00,P01,P02在R0,P10,P11,P12中,在R1中,P20,P21,P22在R2中。 P * 0在同一台计算机上。所以与P * 1和P * 2相同。
现在我想让R0,R1,R2同时调用MPI_Bcast从P * 0广播到p * 1和P * 2.
我发现当我使用MPI_Bcast时,只需要在一行中播放三倍的时间。
例如,如果我只在R0中调用MPI_Bcast,则需要1.00秒。 但如果我在所有R [0,1,2]中调用三个MPI_Bcast,则总共需要3.00秒。 这意味着MPI_Bcast无法并行工作。
是否有任何方法可以同时播放MPI_Bcast广播? (一个节点同时播放三个频道。)
感谢。
答案 0 :(得分:5)
如果我理解你的问题,你希望同时进行逐行广播:
P00 -> P01 & P02
P10 -> P11 & P12
P20 -> P21 & P22
这可以使用子通信器完成,例如一个只有第0行的进程,另一个只有第1行的进程,依此类推。然后,您可以通过使用适当的通信器参数调用MPI_Bcast
来在每个子通信器中发出同步广播。
如果您首先使用笛卡尔通信器,那么创建行式子通信器非常容易。 MPI为此提供MPI_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);
现在comm_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
来将进程分组到新的子通信器中 - 具有相同color
的进程最终位于同一个子通信器中。在您的情况下,color
应该等于调用进程所在行的编号。拆分操作也需要key
,用于对新子通信器中的进程进行排序。它应该等于调用进程所在的列数,例如:
// 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
将再次包含一个子通信器的句柄,该子通信器只跨越与调用进程相同的行。
答案 1 :(得分:1)
MPI-3.0草案包含一个非阻塞MPI_Ibcast
集体。虽然非阻塞集体尚未正式成为标准的一部分,但它们已经在MPICH2和(我认为)OpenMPI中可用。
或者,您可以从单独的线程开始阻止MPI_Bcast
调用(我假设R0,R1和R2是不同的传播者)。
第三种可能性(可能或可能不可能)是重组数据,以便只需要一次广播。