首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MPI_Isend/MPI_Recv与MPI_Send/MPI_Irecv

MPI_Isend/MPI_Recv与MPI_Send/MPI_Irecv
EN

Stack Overflow用户
提问于 2018-11-08 08:56:43
回答 1查看 2.4K关注 0票数 2

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

  • MPI_Isend与缓冲区,然后MPI_Iprobe & MPI_Recv,一旦接收器准备好,或
  • 当发送方准备就绪时,MPI_Irecv和MPI_Irecv都有足够的缓冲区,而MPI_Send则有缓冲区吗?

通信场景是数据必须异步交换,到达时间无关紧要,两个进程都有工作负载。只考虑整体性能(特别是没有阻塞)。

下面是一个最小的工作示例(我没有包括工作负载,因此时间可能没有意义)。

代码语言:javascript
复制
#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;
}

在我的机器上产生:

代码语言:javascript
复制
rank = 0, time = 0.000035 sec
rank = 1, time = 0.000036 sec
---
rank = 0, time = 0.000035 sec
rank = 1, time = 0.000026 sec

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

EN

回答 1

Stack Overflow用户

发布于 2022-02-06 17:45:56

一般的经验法则是:

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

这样做的另一面并不坏,但是,你可以重叠发送和接收更好。

出于这个原因,我们应该选择您描述的第二个案例场景。另外,如果您不使用非阻塞通信,请小心死锁。有关死锁,请参见MPI Send and receive questions

读者练习:

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

片段1:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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和send。由于Waitall,代码段2有一个死锁。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53204330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档