1

我有一个 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 吗?(一个节点同时广播三个频道。)

谢谢。

4

2 回答 2

5

如果我正确理解您的问题,您希望同时进行逐行广播:

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包含一个子通信器的句柄,它只跨越与调用进程相同的行。

于 2012-07-07T10:28:06.080 回答
1

MPI-3.0 草案包括一个非阻塞MPI_Ibcast集合。虽然非阻塞集合还没有正式成为标准的一部分,但它们已经在 MPICH2 和(我认为)在 OpenMPI 中可用。

或者,您可以从单独的线程开始阻塞MPI_Bcast调用(我假设 R0、R1 和 R2 是不同的通信器)。

第三种可能性(可能或不可能)是重组数据,以便只需要一次广播。

于 2012-07-07T05:50:17.543 回答