【问题标题】:MPI_ERR_BUFFER from MPI_Bsend after removing following print statement?删除以下打印语句后来自 MPI_Bsend 的 MPI_ERR_BUFFER?
【发布时间】:2017-10-20 14:29:51
【问题描述】:

我有以下有效的代码:

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {

  int world_rank, world_size;
  MPI_Init(NULL, NULL);
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);

  int n = 10000;
  int ni, i;

  double t[n];
  int x[n];

  int buf[n];
  int buf_size = n*sizeof(int);
  MPI_Buffer_attach(buf, buf_size);

  if (world_rank == 0) {
    for (ni = 0; ni < n; ++ni) {
      int msg_size = ni;
      int msg[msg_size];
      for (i = 0; i < msg_size; ++i) {
        msg[i] = rand();
      }

      double time0 = MPI_Wtime();
      MPI_Bsend(&msg, msg_size, MPI_INT, 1, 0, MPI_COMM_WORLD);
      t[ni] = MPI_Wtime() - time0;
      x[ni] = msg_size;
      MPI_Barrier(MPI_COMM_WORLD);
      printf("P0 sent msg with size %d\n", msg_size);
    }
  }

  else if (world_rank == 1) {
    for (ni = 0; ni < n; ++ni) {
      int msg_size = ni;
      int msg[msg_size];
      MPI_Request request;
      MPI_Barrier(MPI_COMM_WORLD);
      MPI_Irecv(&msg, msg_size, MPI_INT, 0, 0, MPI_COMM_WORLD, &request);
      MPI_Wait(&request, MPI_STATUS_IGNORE);
      printf("P1 received msg with size %d\n", msg_size);
    }
  }
  MPI_Buffer_detach(&buf, &buf_size);
  MPI_Finalize();
}

一旦我删除打印语句,程序就会崩溃,告诉我有一个MPI_ERR_BUFFER: invalid buffer pointer。如果我只删除一个打印语句,其他打印语句仍会执行,所以我相信它会在程序结束时崩溃。我不明白为什么它会崩溃,而且当我使用打印语句时它不会崩溃超出了我的逻辑......

有人知道这里发生了什么吗?

【问题讨论】:

    标签: c mpi


    【解决方案1】:

    您根本没有为 MPI 提供足够的缓冲区空间。在缓冲模式下,所有正在进行的消息都存储在用作环形缓冲区的缓冲区空间中。在您的代码中,可能有多个消息需要缓冲,而不管printf。请注意,即使2*n*sizeof(int) 也没有足够的缓冲区空间 - 即使相应的接收完成,屏障也不能保证缓冲区在本地释放。您必须提供(n*(n-1)/2)*sizeof(int) 内存才能确定,或者介于两者之间并希望。

    底线:不要使用缓冲模式。

    通常,使用标准阻塞发送调用并编写应用程序以使其不会死锁。调整 MPI 实现,以便无论接收者如何都可以发送小消息 - 以避免延迟接收者的等待时间。

    如果您想重叠通信和计算,请使用非阻塞消息 - 为每次通信提供适当的内存。

    【讨论】:

    • 缓冲模式只缓冲不立即发送的消息,即同步阻塞标准发送的消息。
    • @zulan 感谢您的回答。我不知道必须同时为 all 消息提供空间。在上面的代码中,我尝试强制缓冲,因为我想测量准备发送和缓冲发送之间的性能差异(不确定这是否是一个合理的做法 - 但布丁就是吃东西的证据:P)。
    • @Hristo - 我想我已经从 MPI 文档中了解到,在标准模式下,MPI 决定它是缓冲还是发送,缓冲和就绪模式允许我指定行为,我是不是弄错了?
    • @HristoIliev 我什至没有在标准中找到那个承诺(只有“如果执行发送并且没有发布匹配的接收,那么 MPI 必须缓冲传出消息,以便允许发送呼叫以完成。”)。尽管如此,我认为在大多数情况下很难推断出缓冲区的实际上限。你不同意我的建议吗?
    • 我要说的是缓冲模式不需要缓冲每条消息。这实际上是一些 MPI 实现所做的。当使用tcp BTL(其急切限制为 64 KiB)与 Open MPI 一起运行时,即使根本没有附加缓冲区(MPI 将其视为缓冲区大小为零),OP 的程序也能正常运行。同时,它会立即与英特尔 MPI 一起崩溃。但我同意这是一种知之甚少的模式,一般应避免使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2016-05-12
    相关资源
    最近更新 更多