具有大数据和很少 MPI 进程的 FFTW 问题示例代码

问题描述

问题

我使用 FFTW 来计算 MPI 并行化就地 3D FFT,特别是使用 fftw_mpi_plan_dft_r2c_3d(),它通常有效。最近,我对将大数据量与少量 cpu 内核/MPI 进程混合起来很感兴趣。使用 2 个进程,全局大小 gridsize*gridsize*gridsize 的 3D FFT 失败并出现错误

[s81n11:31843] *** MPI_Sendrecv 发生错误

[s81n11:31843] *** 进程报告 [1582235649,0]

[s81n11:31843] *** 在通信器上 MPI COMMUNICATOR 6 DUP FROM 5

[s81n11:31843] *** MPI_ERR_COUNT:无效的计数参数

[s81n11:31843] *** MPI_ERRORS_ARE_FATAL(此通信器中的进程现在将中止,

[s81n11:31843] *** 可能还有你的 MPI 工作)

如果我使用 gridsize >= 2048。请注意,使用例如它可以正常工作1 或 3 个进程。

我怀疑这归结为 MPI_Sendrecv() 中的 MPI 消息大小有限。对于 2 个进程,每个局部网格的物理大小为 size = (gridsize/2)*gridsize*(2*(gridsize/2 + 1)),其中全局网格分布在第一个维度上,最后一个维度接收少量的 padding。对于 gridsize = 2048size = 1.001*2³²。我对 gridsize = 2047 没有问题,对于 size = 0.999*2³²

  1. 问题究竟出在哪里?最好指出确切的 unsigned int(或其他)罪魁祸首。

  2. 如果我直接负责 MPI 调用,我可以使用多个调用分块执行通信。但是,由于 FFTW 在内部调用 MPI,我该如何解决这个问题?如果不是太复杂,我想我什至愿意破解 FFTW/MPI 源。

虽然其他人之前一定遇到过这个问题,但我在网上找不到任何关于 FFTW 限制的信息。感谢有关该主题的任何参考。

我在 64 位 Linux 上使用 FFTW 3.3.9 和 MPICH 3.3.2 和 OpenMPI 4.0.3 时发现了问题。

示例代码

下面是一个示例 C 代码,将其命名为 fft.c

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <fftw3-mpi.h>

int main(int argc,char* argv[]) {
  /* Set grid size */
  ptrdiff_t gridsize = 32;
  if (argc > 1)
    gridsize = atoi(argv[1]);
  ptrdiff_t gridsize_padding = 2*(gridsize/2 + 1);

  /* Initialize MPI */
  MPI_Init(NULL,NULL);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  fftw_mpi_init();

  /* Allocate grid */
  ptrdiff_t gridsize_local;
  ptrdiff_t gridsize_local_i,gridstart_local_i;
  ptrdiff_t gridsize_local_j,gridstart_local_j;
  double* grid = fftw_alloc_real(fftw_mpi_local_size_3d_transposed(
    gridsize,gridsize,gridsize_padding,MPI_COMM_WORLD,&gridsize_local_i,&gridstart_local_i,&gridsize_local_j,&gridstart_local_j
  ));
  assert(gridsize_local_i == gridsize_local_j);
  gridsize_local = gridsize_local_i;
  if (rank == 0)
    printf("gridsize %td\n",gridsize);
  printf("rank %d got gridsize_local = %td\n",rank,gridsize_local);

  /* Nullify grid */
  ptrdiff_t i,j,k;
  for (i = 0; i < gridsize_local; i++) {
    for (j = 0; j < gridsize; j++) {
      for (k = 0; k < gridsize_padding; k++) {
        grid[(i*gridsize + j)*gridsize_padding + k] = 0.0;
      }
    }
  }

  /* Carry out FFT */
  fftw_plan plan = fftw_mpi_plan_dft_r2c_3d(
      gridsize,grid,(fftw_complex*) grid,FFTW_ESTIMATE | FFTW_MPI_TRANSPOSED_OUT
  );
  fftw_mpi_gather_wisdom(MPI_COMM_WORLD);
  fftw_mpi_broadcast_wisdom(MPI_COMM_WORLD);
  fftw_execute(plan);

  /* Clean up */
  fftw_free(grid);
  fftw_destroy_plan(plan);
  fftw_mpi_cleanup();
  MPI_Finalize();
  return 0;
}

假设您已经安装了 MPI 和 FFTW 并且环境配置适当,您可以使用

编译上面的 fft.c
mpicc -I/path/to/fftw/include -I/path/to/mpi/include -c -o fft.o fft.c
mpicc fft.o -o fft -L/path/to/fftw/lib -Wl,-rpath=/path/to/fftw/lib -lfftw3_mpi -lfftw3 -L/path/to/mpi/lib -Wl,-rpath=/path/to/mpi/lib -lmpi

使用 2 个进程执行 3D FFT,例如gridsize 为 64,现在做

mpiexec -n 2 ./fft 64

不会发生任何事情,因为不会检查或打印任何结果。以 2048 的 gridsize 运行会在大约一分钟后产生崩溃。 警告:以 2048 的 gridsize 运行将占用 64 GB 内存 (!),因此您可能无法对此进行测试。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)