MPI - Bsend使用

时间:2017-03-05 09:04:18

标签: c++ mpi

当我想在异步发送后完全释放资源时MPI_Bsend是否正常? 请问:

MPI_Bsend(&array[0],...)
delete[] array;

阻止我删除我要发送的内存(问题是,当适当的recv打开时,数组可能已被删除)?

UPD:

void RectMPIAngleFiller::setglobalFillerbounds1() {

    int_t SIZE = getSolver()->getNumInterpolators() * procnums;
    int_t gridnums = getSolver()->getNumGrids();
    if (layer == 1) {
      if (local_rank == 0) {
    MPI_Isend(&rank_size, 1, MPI_INT, 0, gridnum, MPI_COMM_WORLD);
      }
    } else if (layer == 0) {
      int_t fillernumber = getSolver()->getNumInterpolators();
      int_t local_fillernum = fillernum % fillernumber;
      if (local_rank == 0 && local_fillernum == 0) {
    int_t * incomeSizes = new incomeSizes[gridnums];
    incomeSizes[gridnum] = getSolver()->getNumInterpolators();

    for ( int_t i = 0; i < gridnums; i++) {
      if (i != gridnum)
        MPI_Irecv(&incomeSizes[i], 1, MPI_INT, MPI_ANY_SOURCE, i, MPI_COMM_WORLD, &request);
    }

      }
   }    
}

我现在有一个这样的功能(现在可能不正确),它从许多进程收集大小,这些进程可能相同但在不同的类实例上运行,这就是为什么一切都是Send。

此函数在每个实例的外循环中运行,我希望在整个循环之后完成它。

现在它只接收大小,我不想要这个并希望删除一些内部数组,并根据相同功能中的接收大小调整它们的大小。如果我有非常大的数组,Isend中的内部缓冲区太小而无法存储所有信息。

2 个答案:

答案 0 :(得分:4)

缓冲和非阻塞发送之间的区别在MPI中有点微妙。在实践中,它们都可以用于避免死锁,因为两个例程在消息传递之前将控制权返回给用户(或者更确切地说,它们将总是返回给用户,但是在那时不能保证消息已经被传递)。在实践中,这意味着既不需要等待匹配的接收被发布,这有助于避免死锁。

但是,MPI_Bsend 保证数据已复制到缓冲区。用户可以通过MPI_Buffer_attach确保为缓冲的所有未完成消息提供足够的内存。这是一条消息还是更多消息取决于程序的逻辑。

MPI_Isend 不保证消息已被复制到缓冲区。心理模型是发送已推迟到以后 - 您已经要求MPI在将来的某个时间发送消息时方便。您必须等待相关的请求以确保MPI_Send已完成。

  • 当MPI_Bsend返回时,可以安全地释放发送缓冲区 保证已被复制到用户提供的缓冲区。
  • 当MPI_Isend返回时,取消分配发送缓冲区是不安全的。

  • 当MPI_Wait(&amp; request,&amp; status)返回时,可以安全地取消分配 发送缓冲区。这是因为 数据已被复制到 缓冲区(系统缓冲区,不是您通过Buffer_attach提供的缓冲区) 因为它已安全地传送到匹配的MPI_Recv。

MPI可以自由选择是否缓冲MPI_Send。实际上,小消息是缓冲的,但大的消息不是。

虽然MPI_Ibsend存在完整性,但我无法想到一个真实的用例。原则上,它可以在将消息复制到用户提供的缓冲区之前返回,这样您就可以在等待之后释放发送缓冲区。那么您可以将用户代码与副本重叠?在实践中似乎有点无意义。

答案 1 :(得分:3)

使用MPI_Isend文档中禁止对输入缓冲区进行任何修改(或释放):https://www.open-mpi.org/doc/v2.0/man3/MPI_Isend.3.php

  

非阻塞发送调用表示系统可能开始从发送缓冲区中复制数据。 在调用非阻塞发送操作之后,发送方不应修改发送缓冲区的任何部分,直到发送完成。可以通过调用MPI_Wait,MPI_Waitany,MPI_Test或MPI_Testany来确定发送请求是否已完成

Bsend的文档没有这样的禁止(但MPI_Buffer_attach之前应该调用足够大的文件):https://www.open-mpi.org/doc/v2.0/man3/MPI_Bsend.3.php

  

MPI_Bsend执行缓冲模式,阻止发送。 ...缓冲区空间不可供后续MPI_Bsends重用,除非您确定已收到该消息(不仅仅是应该已收到该消息)。

如果您想要将缓冲和异步相结合,请尝试使用MPI_Ibsend https://www.open-mpi.org/doc/v2.0/man3/MPI_Ibsend.3.php,但它具有与Isend相同的禁令:

  

MPI_Ibsend - 启动非阻塞缓冲发送。 ...非阻塞发送调用表示系统可能开始从发送缓冲区中复制数据。在调用非阻塞发送操作之后,发送方不应修改发送缓冲区的任何部分,直到发送完成。

发送模式的完整列表例如在http://www.mcs.anl.gov/research/projects/mpi/sendmode.html中;没有R *变体的列表是:

  
      
  • MPI_Send - 直到您可以使用发送缓冲区,MPI_Send才会返回。它可能阻止也可能不阻塞(允许缓冲,或者打开   发送方或接收方,或等待匹配接收)。
  •   
  • MPI_Bsend - 可缓冲;立即返回,您可以使用发送缓冲区。 MPI规范的后期附加组件。应该只使用   当绝对必要时。
  •   
  • MPI_Ssend - 在匹配收到发布
  • 之前不会返回   
  • MPI_Isend - 非阻止发送。但不一定是异步的。在成功,等待/测试或之前,您不能重复使用发送缓冲区   你知道收到了消息(参见MPI_Request_free)。   还要注意,虽然我指的是立即,但没有   MPI_Isend的性能要求。立即发送必须返回   用户无需在目的地进行匹配接收。一个   实现可以自由地将数据发送到目的地之前   返回,只要发送调用不阻塞等待   匹配接收。何时发送数据报价的策略不同   不同的性能优势和劣势将取决于   申请。
  •   
  • MPI_Ibsend - 缓冲无阻塞
  •   
  • MPI_Issend - 同步非阻塞。请注意,只有在发布匹配的接收时,才会完成等待/测试。
  •