【发布时间】:2022-02-07 01:54:26
【问题描述】:
对于 MPI 中的异步通信,以下哪个更好(在性能、可靠性、可读性等方面):
- MPI_Isend 与缓冲区,然后 MPI_Iprobe & MPI_Recv 一旦接收器准备好,或
- MPI_Irecv 带缓冲区(这样总是有足够的缓冲区发布 MPI_Irecv),然后 MPI_Send 发送者准备好?
通信场景是数据必须异步交换,到达时间无关紧要,两个进程都有工作量。只考虑整体性能(尤其是无阻塞)。
下面是一个最小的工作示例(我没有包括工作量,因此时间可能没有意义)。
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
MPI_Init(NULL, NULL);
int world_size, world_rank;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
if (world_rank == 0 && world_size != 2) {
fprintf(stderr, "This example requires two MPI processes.\n");
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}
/* Non Blocking Send */
int buf[100] = {0};
MPI_Barrier(MPI_COMM_WORLD);
double time = MPI_Wtime();
if (world_rank == 1) {
MPI_Request request;
MPI_Isend(buf, 100, MPI_INT, 0, 0, MPI_COMM_WORLD, &request);
MPI_Wait(&request, MPI_STATUS_IGNORE);
} else {
MPI_Recv(buf, 100, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
time = MPI_Wtime() - time;
printf("rank = %d, time = %f sec\n", world_rank, time);
MPI_Barrier(MPI_COMM_WORLD);
usleep(100);
if (world_rank == 0) {
printf("---\n");
}
/* Non Blocking Receive */
MPI_Barrier(MPI_COMM_WORLD);
time = MPI_Wtime();
if (world_rank == 1) {
MPI_Send(buf, 100, MPI_INT, 0, 0, MPI_COMM_WORLD);
} else {
MPI_Request request;
MPI_Irecv(buf, 100, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
MPI_Wait(&request, MPI_STATUS_IGNORE);
}
time = MPI_Wtime() - time;
printf("rank = %d, time = %f sec\n", world_rank, time);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}
在我的机器上生成:
rank = 0, time = 0.000035 sec
rank = 1, time = 0.000036 sec
---
rank = 0, time = 0.000035 sec
rank = 1, time = 0.000026 sec
已经感谢您的回答,祝您有愉快的一天:)
【问题讨论】:
-
后者避免了意外消息(这可能导致内存使用量增加)。另外,请记住
MPI_Send()可能会阻止如果没有发布匹配的接收。这是选择第二个选项的两个原因。
标签: mpi