如何在MPI中为除root之外的所有节点执行MPI_Scatter?

时间:2017-03-30 03:25:37

标签: mpi distributed-computing hpc

在MPI中,如果我在MPI_COMM_WORLD上执行MPI_Scatter,则所有节点都会收到一些数据(包括发送根)。

如何从根节点到所有其他节点执行MPI_Scatter,确保根节点不接收任何数据

创建一个包含所有节点的新MPI_Comm,但根是可行的方法吗?

1 个答案:

答案 0 :(得分:1)

让我们想象您的代码如下:

int rank, size;    // rank of the process and size of the communicator
int root = 0;      // root process of our scatter
int recvCount = 4; // or whatever
double *sendBuf = rank == root ? new double[recvCount * size] : NULL;
double *recvBuf = new double[recvCount];

MPI_Scatter( sendBuf, recvCount, MPI_DOUBLE,
             recvBuf, recvCount, MPI_DOUBLE,
             root, MPI_COMM_WORLD );

所以在这里,确实,root进程会将数据发送给自己,尽管可以避免这种情况。 以下是实现这一目标的两种明显方法。

使用MPI_IN_PLACE
MPI_Scatter()的呼吁不会改变。代码中唯一的变化是接收缓冲区的定义,这将是这样的:

double *recvBuf = rank == root ?
                  static_cast<double*>( MPI_IN_PLACE ) :
                  new double[recvCount];

使用MPI_Scatterv()
有了这个,你必须定义一个描述各个接收大小的整数数组,一个描述起始索引的位移数组,并在调用MPI_Scatterv()时使用它们来取代你对{{1}的调用像这样:

MPI_Scatter()

当然,在这两种情况下,流程int sendCounts[size] = {recvCount}; // everybody receives recvCount data sendCounts[root] = 0; // but the root process int displs[size]; for ( int i = 0; i < size; i++ ) { displs[i] = i * recvCount; } MPI_Scatterv( sendBuf, sendCounts, displs, MPI_DOUBLE, recvBuf, recvCount, MPI_DOUBLE, root, MPI_COMM_WORLD ); 的接收缓冲区都没有数据,而且必须在代码中考虑这一点。

我个人更喜欢第一个选项,但两者都有效。