MPI_Win_create 的基本 RMA 问题,当大小为非零时,参数 NULL 基指针中的空指针无效
Basic RMA issue with MPI_Win_create, Null pointer in parameter NULL base pointer is invalid when size is nonzero
我正在使用最新稳定版 MPICH (3.3) 的 Fortran 90
我想要 MPI_Window 在根进程上公开一个数组,通信器中的所有其他进程调用 MPI_Get 将该数组复制到它们自己的“本地”副本中。
不幸的是,在 MPI_Win_create(base, ...) 的非根进程中提供 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
我一直在研究教科书示例,pg。 61 图 3.2,使用高级 MPI,消息传递接口的现代特性,Gropp、Hoefler、Thakur、Lusk。
除了 MPI_BOTTOM
之外,我还应该使用什么 kind(MPI_ADDRESS_KIND)
?这是在一个进程上初始化 MPI_Window 的正确方法,该进程实际上并没有公开它的内部内存,只是访问另一个进程的内存吗?
显然,将 base 的参数更改为已分配的(非空)数组是可行的,但这会改变后面 GET 的行为,因此它不起作用(创建无效的内存访问)。
我不知道为什么运行时错误特别指出空基指针对于非零大小无效,因为我在 mpi_win_create(MPI_BOTTOM, 0, MPI_INTEGER, ...)
.[=19 的调用中明确将大小指定为 0 =]
这是我自己为这个例子准备的所有代码。它设置缓冲区并尝试为每个进程创建 windows。在对 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
版本,在这种情况下应该是十个 0,因为 MPI_Get 被注释掉了。
我遇到了运行时错误。
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
我正在使用最新稳定版 MPICH (3.3) 的 Fortran 90
我想要 MPI_Window 在根进程上公开一个数组,通信器中的所有其他进程调用 MPI_Get 将该数组复制到它们自己的“本地”副本中。
不幸的是,在 MPI_Win_create(base, ...) 的非根进程中提供 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
我一直在研究教科书示例,pg。 61 图 3.2,使用高级 MPI,消息传递接口的现代特性,Gropp、Hoefler、Thakur、Lusk。
除了 MPI_BOTTOM
之外,我还应该使用什么 kind(MPI_ADDRESS_KIND)
?这是在一个进程上初始化 MPI_Window 的正确方法,该进程实际上并没有公开它的内部内存,只是访问另一个进程的内存吗?
显然,将 base 的参数更改为已分配的(非空)数组是可行的,但这会改变后面 GET 的行为,因此它不起作用(创建无效的内存访问)。
我不知道为什么运行时错误特别指出空基指针对于非零大小无效,因为我在 mpi_win_create(MPI_BOTTOM, 0, MPI_INTEGER, ...)
.[=19 的调用中明确将大小指定为 0 =]
这是我自己为这个例子准备的所有代码。它设置缓冲区并尝试为每个进程创建 windows。在对 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
版本,在这种情况下应该是十个 0,因为 MPI_Get 被注释掉了。
我遇到了运行时错误。
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