【问题标题】:How to do an MPI_Scatter in MPI to all nodes except the root?如何在 MPI 中对除根以外的所有节点执行 MPI_Scatter?
【发布时间】:2017-08-23 19:03:39
【问题描述】:

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

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

创建一个包含除根以外的所有节点的新 MPI_Comm 是否可行?

【问题讨论】:

  • 不创建另一个通信器不是一个可行的选择。但是,使用MPI_IN_PLACE 是。
  • 您也可以使用MPI_Scatterv 并将根秩的块长度设置为零。

标签: mpi distributed-computing hpc


【解决方案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() 的调用中使用它们,这将取代您对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 );

当然,在这两种情况下,进程root 的接收缓冲区中都没有数据,这必须在您的代码中加以说明。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多