fortran - MPI_Win_create 的基本 RMA 问题,当大小非零时,参数 NULL 基指针中的空指针无效

标签 fortran window mpi

我正在 Fortran 90 中使用最新稳定版本的 MPICH (3.3)

我想让 MPI_Window 在根进程上公开一个数组,并且通信器中的所有其他进程调用 MPI_Get 将数组复制到它们自己的“本地”副本中。

不幸的是,在 MPI_Win_create 的非根进程中提供 MPI_BOTTOM 作为“基本”参数(base, ...) 导致错误

MPI_Win_create(192): MPI_Win_create(base=(nil), size=0, disp_unit=1275069467, MPI_INFO_NULL, MPI_COMM_WORLD, win=0x7ffcb343d9fc) failed

MPI_Win_create(156): Null pointer in parameter NULL base pointer is invalid when size is nonzero

我一直在研究一个教科书的例子,第 10 页。 61 图 3.2,使用高级 MPI,消息传递接口(interface)的现代功能,Gropp、Hoefler、Thakur、Lusk。

除了MPI_BOTTOM之外,我应该使用什么替代kind(MPI_ADDRESS_KIND)?这是在进程上初始化 MPI_Window 的正确方法吗?该进程实际上并未公开其内部内存,只是访问另一个进程的内存?

显然,将 base 的参数更改为已分配的(非空)数组是可行的,但这会更改后面的 GET 的行为,因此它不起作用(创建无效的内存访问)。

我不知道为什么运行时错误明确指出空基指针对于非零大小无效,因为我在调用 mpi_win_create(MPI_BOTTOM, 0, MPI_INTEGER, ...).

这是我自己用于此示例的所有代码。它设置缓冲区并尝试为每个进程创建窗口。在对 MPI_Fence 的两次调用之间有一个注释掉的部分,这是所有非根进程尝试 GET 的部分。

program main
  use mpi

  implicit none
  integer :: ierr, procno, nprocs, comm

  integer, allocatable :: root_data(:), local_data(:)
  integer, parameter :: root = 0, NUM_ELEMENTS = 10

  integer :: win

  integer :: i

  !======================================

  call mpi_init(ierr)
  comm = mpi_comm_world
  call mpi_comm_rank(comm, procno, ierr)
  call mpi_comm_size(comm, nprocs, ierr)

  !======================================
  if (procno .eq. root) then
    allocate(root_data(1:NUM_ELEMENTS))
    do i=1,NUM_ELEMENTS
      root_data(i) = i
    enddo

    call mpi_win_create(root_data, NUM_ELEMENTS, MPI_INTEGER, &
                        MPI_INFO_NULL, comm, win, ierr)
  else
    allocate(local_data(1:NUM_ELEMENTS))
    local_data = 0
    call mpi_win_create(MPI_BOTTOM, 0, MPI_INTEGER, &
                        MPI_INFO_NULL, comm, win, ierr)
  endif

  !======================================
  call mpi_win_fence(0, win, ierr)
 
  !if (procno .ne. root) then 
  !  call mpi_get(local_data, NUM_ELEMENTS, MPI_INTEGER, &
  !               root, 0, NUM_ELEMENTS, MPI_INTEGER, &
  !               win, ierr)
  !endif

  call mpi_win_fence(0, win, ierr)
  !======================================

  if (procno .ne. root) then
    print *, "proc", procno
    print *, local_data
  endif

  !======================================
  call MPI_Win_free(win, ierr)

  call mpi_finalize(ierr)
end program main

预期结果是每个进程打印其 local_data 版本。在本例中,由于 MPI_Get 被注释掉,因此应该是十个 0。

我遇到了运行时错误。

最佳答案

MPI_Win_create()size 参数的类型为 INTEGER(KIND=MPI_ADDRESS_KIND)

然后我能够使用 MPICH 3.3 和最新的 Open MPI 成功运行修改后的版本

program main
  use mpi

  implicit none
  integer :: ierr, procno, nprocs, comm

  integer, allocatable :: root_data(:), local_data(:)
  integer, parameter :: root = 0
  integer (KIND=MPI_ADDRESS_KIND) :: NUM_ELEMENTS = 10, zero = 0

  integer :: win

  integer :: i

  !======================================

  call mpi_init(ierr)
  comm = mpi_comm_world
  call mpi_comm_rank(comm, procno, ierr)
  call mpi_comm_size(comm, nprocs, ierr)

  !======================================
  if (procno .eq. root) then
    allocate(root_data(1:NUM_ELEMENTS))
    do i=1,NUM_ELEMENTS
      root_data(i) = i
    enddo

    call mpi_win_create(root_data, NUM_ELEMENTS, MPI_INTEGER, MPI_INFO_NULL, comm, win, ierr)
  else
    allocate(local_data(1:NUM_ELEMENTS))
    local_data = 0
    call mpi_win_create(MPI_BOTTOM, zero, MPI_INTEGER, MPI_INFO_NULL, comm, win, ierr)
  endif

  !======================================
  call mpi_win_fence(0, win, ierr)

  !if (procno .ne. root) then 
  !  call mpi_get(local_data, NUM_ELEMENTS, MPI_INTEGER, &
  !               root, 0, NUM_ELEMENTS, MPI_INTEGER, &
  !               win, ierr)
  !endif

  call mpi_win_fence(0, win, ierr)
  !======================================

  if (procno .ne. root) then
    print *, "proc", procno
    print *, local_data
  endif

  !======================================
  call MPI_Win_free(win, ierr)

  call mpi_finalize(ierr)
end program main

关于fortran - MPI_Win_create 的基本 RMA 问题,当大小非零时,参数 NULL 基指针中的空指针无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57503910/

相关文章:

linux - 增加虚拟内存而不增加VmSize

c++ - 从 C++ 调用带有可选参数的 Fortran 子例程

html - 如果窗口不是全屏,则水平 css 菜单 <li> 元素会在其自身下重新定位

c++ - 用于在 C 或 C++ 中解析 XML 的跨 Linux 和 Windows 的通用 XML 库是什么?

xna - 拖动游戏窗口时防止执行暂停

algorithm - 以分布式或顺序方式工作的算法的术语

types - 使用 gfortran 强制显式变量声明

python - f2py - 函数参数的顺序困惑

fortran - Fortran 90 中的中点规则

cuda - 多 GPU 分析(多个 CPU,MPI/CUDA 混合)