如何在 MPI 中对除根以外的所有节点执行 MPI_Scatter?
How to do an MPI_Scatter in MPI to all nodes except the root?
在 MPI 中,如果我在 MPI_COMM_WORLD 上执行 MPI_Scatter,所有节点都会收到一些数据(包括发送根)。
如何执行从根节点到所有其他节点的MPI_Scatter并确保根节点不接收任何数据?
创建一个包含除根以外的所有节点的新 MPI_Comm 是可行的方法吗?
让我们想象一下您的代码如下所示:
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
的接收缓冲区中都不会有数据,这必须在您的代码中说明。
我个人更喜欢第一个选项,但两者都有效。
在 MPI 中,如果我在 MPI_COMM_WORLD 上执行 MPI_Scatter,所有节点都会收到一些数据(包括发送根)。
如何执行从根节点到所有其他节点的MPI_Scatter并确保根节点不接收任何数据?
创建一个包含除根以外的所有节点的新 MPI_Comm 是可行的方法吗?
让我们想象一下您的代码如下所示:
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
的接收缓冲区中都不会有数据,这必须在您的代码中说明。
我个人更喜欢第一个选项,但两者都有效。