MPI_Waitany() 或 MPI_Recv() 与 MPI_ANY_SOURCE?
MPI_Waitany() or MPI_Recv() with MPI_ANY_SOURCE?
上下文:
在我的程序中,主进程正在为从属进程分配工作。从属进程完成工作后,它会向主进程请求更多工作。 Master分配给slave更多的工作,程序继续。
我编写程序的方式是,主进程使用 MPI_Recv 和 MPI_ANY_SOURCE 从从节点接收工作。
/* Allot some work to all the slaves (seed) */
while (istheremorework()) {
/* Master receives slaves work*/
MPI_Status status;
MPI_Recv(recvbuf, width + 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
int slave = status.MPI_SOURCE;
cout << "Master recieved data from slave " << slave << endl;
/* store the data */
/* Master sends new work to the slave */
int* sendbuf;
/* populate sendbuf */
MPI_Send(&sendbuf, 2, MPI_INT, slave, MSG_TAG_DATA, MPI_COMM_WORLD);
/* update remaining work information */;
}
这部分代码也可以改写为
/* Allot some work to all the slaves (seed) */
/* Open a channel with all the slaves to receive their work. */
for (int k = 1; k < i; k++) {
MPI_Irecv(&recbuf[k], BUFFER_LENGTH, MPI_DOUBLE, k, MSG_TAG, MPI_COMM_WORLD, &requests[k - 1]);
/* Each slave sends the results to master */
}
while (istheremorework()) {
/* Master receives slaves work*/
MPI_Waitany(np-1, requests, &index, statuses);
/* Using index to decide which slave sent the result */
cout << "Master received data from slave " << slave << endl;
/* store the data */
/* Master sends new work to the slave */
int* sendbuf;
/* populate sendbuf */
MPI_Send(&sendbuf, 2, MPI_INT, slave, MSG_TAG_DATA, MPI_COMM_WORLD);
/* update remaining work information */;
}
这两种方法在性能上是否等同?您认为使用其中一种比使用另一种有什么显着优势吗?
在 Waitany 版本中,您必须为主进程上的每个工作人员初始化和维护一个 MPI_Request
请求对象,并且 MPI 必须在 MPI_Waitany()
调用中遍历所有这些对象.使用 MPI_Recv(MPI_ANY_SOURCE)
,您只需处理消息队列中的下一条消息。我怀疑 MPI_Recv 版本会更好。
您可以尝试使用性能分析器来确定。对于中小型规模,在这种情况下可能不会有太大的性能差异。然而,在大规模情况下,同时分配那么多请求对象被认为是一个坏主意。
上下文: 在我的程序中,主进程正在为从属进程分配工作。从属进程完成工作后,它会向主进程请求更多工作。 Master分配给slave更多的工作,程序继续。
我编写程序的方式是,主进程使用 MPI_Recv 和 MPI_ANY_SOURCE 从从节点接收工作。
/* Allot some work to all the slaves (seed) */
while (istheremorework()) {
/* Master receives slaves work*/
MPI_Status status;
MPI_Recv(recvbuf, width + 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
int slave = status.MPI_SOURCE;
cout << "Master recieved data from slave " << slave << endl;
/* store the data */
/* Master sends new work to the slave */
int* sendbuf;
/* populate sendbuf */
MPI_Send(&sendbuf, 2, MPI_INT, slave, MSG_TAG_DATA, MPI_COMM_WORLD);
/* update remaining work information */;
}
这部分代码也可以改写为
/* Allot some work to all the slaves (seed) */
/* Open a channel with all the slaves to receive their work. */
for (int k = 1; k < i; k++) {
MPI_Irecv(&recbuf[k], BUFFER_LENGTH, MPI_DOUBLE, k, MSG_TAG, MPI_COMM_WORLD, &requests[k - 1]);
/* Each slave sends the results to master */
}
while (istheremorework()) {
/* Master receives slaves work*/
MPI_Waitany(np-1, requests, &index, statuses);
/* Using index to decide which slave sent the result */
cout << "Master received data from slave " << slave << endl;
/* store the data */
/* Master sends new work to the slave */
int* sendbuf;
/* populate sendbuf */
MPI_Send(&sendbuf, 2, MPI_INT, slave, MSG_TAG_DATA, MPI_COMM_WORLD);
/* update remaining work information */;
}
这两种方法在性能上是否等同?您认为使用其中一种比使用另一种有什么显着优势吗?
在 Waitany 版本中,您必须为主进程上的每个工作人员初始化和维护一个 MPI_Request
请求对象,并且 MPI 必须在 MPI_Waitany()
调用中遍历所有这些对象.使用 MPI_Recv(MPI_ANY_SOURCE)
,您只需处理消息队列中的下一条消息。我怀疑 MPI_Recv 版本会更好。
您可以尝试使用性能分析器来确定。对于中小型规模,在这种情况下可能不会有太大的性能差异。然而,在大规模情况下,同时分配那么多请求对象被认为是一个坏主意。