gpt4 book ai didi

MPI_Isend/MPI_Recv 与 MPI_Send/MPI_Irecv

转载 作者:行者123 更新时间:2023-12-05 06:29:47 30 4
gpt4 key购买 nike

对于MPI中的异步通信,以下哪个更好(在性能、可靠性、可读性等方面):

  • MPI_Isend with buffer 然后 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

谢谢你的回答,祝你有愉快的一天:)

最佳答案

一般的经验法则是:

  1. 在缓冲区中接收数据。此操作很快,但您可能会等待消息到达,
  2. 再次在缓冲区中发送一些数据;这是一个很长的步骤。

反过来做也不错,但是,您可以更好地重叠发送和接收。

因此,应该选择您描述的第二种情况。此外,如果您不使用非阻塞通信,请注意死锁。有关死锁,请参阅 MPI Send and receive questions .

读者练习:

在下面的片段中,假设所有缓冲区都分配了足够的大小。此外,等级和大小分别表示每个进程的等级和 MPI 进程的总数。对于每个片段,请注意它是否死锁并解释原因。报告性能问题。

片段 1:

int ireq = 0;
for (int p=0; p<size; p++)
if (p!=rank)
MPI_Isend(sbuffers[p],buflen,MPI_INT,p,0,comm,&(reqs[ireq++]));
for (int p=0; p<size; p++)
if (p!=rank)
MPI_Recv(rbuffer,buflen,MPI_INT,p,0,comm,MPI_STATUS_IGNORE);
MPI_Waitall(size-1,reqs,MPI_STATUSES_IGNORE);

片段 2:

int ireq = 0;
for (int p=0; p<size; p++)
if (p!=rank)
MPI_Irecv(rbuffers[p],buflen,MPI_INT,p,0,comm,&(reqs[ireq++]));
MPI_Waitall(size-1,reqs,MPI_STATUSES_IGNORE);
for (int p=0; p<size; p++)
if (p!=rank)
MPI_Send(sbuffer,buflen,MPI_INT,p,0,comm);

解决方法:

片段 1 存在性能问题,反转 recv 和发送。

片段 2 由于 Waitall 而出现死锁。

关于MPI_Isend/MPI_Recv 与 MPI_Send/MPI_Irecv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53204330/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com