所以我正在尝试并行化我使用MPI的Fortran 2003程序。我在具有64Gb共享内存的16个处理器内核的节点上运行它。我的MPI通信器中的16个等级必须将一些算法应用于相当大的阵列的一部分(大约6000乘8000个元素,双精度)。
现在,我使用MPI_BCAST
将此数组的副本从根级别发送到其他15个级别,这需要花费大量时间。大数组是只读的,因此我认为使用MPI_win_allocate_shared
使所有排名都可以读取并快速传递win对象会更快。由于它是共享内存节点,因此应该可以正常工作。 (所有这些都基于我在本主题的答案中找到的解释:MPI Fortran code: how to share data on node via openMP?)
但是,当我尝试编译程序时,收到以下错误消息:
Undefined symbols for architecture x86_64:
"_mpi_win_allocate_shared_", referenced from:
___lakefinder_parallel_mpi_nam_module3_MOD_fill_sea_master in lakefinder_parallel_mpi_nam_module3.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
不知道为什么,因为程序使用了其他几个MPI命令(MPI_INIT,MPI_SEND,MPI_BCAST等),并且它可以正常工作。
有什么想法吗?
这是我的基本代码(只有相关部分,它是大型气候模型的一部分,我不打扰你):
PROGRAM Main_program
USE mpi
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_PTR, C_F_POINTER
USE configuration_main_module, only: dp ! 8-byte float
IMPLICIT NONE
REAL(dp), DIMENSION(6000,8000) :: data_array
INTEGER :: ierr, rank, size, win, disp_unit
INTEGER(KIND=MPI_ADDRESS_KIND) :: windowsize
TYPE(C_PTR) :: baseptr
! Split program into ranks
CALL MPI_INIT(ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
! Open up a lot of space for the root rank and nothing for the others
IF (rank==0) THEN
windowsize = 6000*8000*8_MPI_ADDRESS_KIND
ELSE
windowsize = 0
END IF
disp_unit = 1
CALL MPI_Win_allocate_shared(windowsize, disp_unit, MPI_INFO_NULL, MPI_COMM_WORLD, baseptr, win, ierr)
CALL MPI_FINALIZE(ierr)
END PROGRAM Main_program
答案 0 :(得分:0)
以下代码使用英特尔Fortran 16.0.2和MPICH 3.2编译并运行且没有错误。请注意,我在退出之前触摸已分配的缓冲区并释放窗口。我还选择了一个不会占用大量内存的数组维度。
您可以尝试使用较小的数组维度进行测试并向上扩展直至失败,以查看问题是否与不充分的共享内存资源相关联,这在Sys5共享内存API中很常见,但不是POSIX共享内存API
如果不是资源问题,则可能是Open-MPI中的错误。请将错误报告给Open-MPI并切换到MPICH。对于它的价值,我还没有看到任何与MPI-3共享内存问题的Open-MPI,但我没有像其他人一样对它进行测试,而且我从不使用Fortran的RMA。
PROGRAM Main_program
USE mpi
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_PTR, C_F_POINTER
use iso_fortran_env
IMPLICIT NONE
REAL(kind=REAL64), DIMENSION(60,80) :: data_array
INTEGER :: ierr, rank, size, win, disp_unit
INTEGER(KIND=MPI_ADDRESS_KIND) :: windowsize
TYPE(C_PTR) :: baseptr
! Split program into ranks
CALL MPI_INIT(ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
! Open up a lot of space for the root rank and nothing for the others
IF (rank==0) THEN
windowsize = 60*80*8_MPI_ADDRESS_KIND
ELSE
windowsize = 0
END IF
disp_unit = 1
CALL MPI_Win_allocate_shared(windowsize, disp_unit, MPI_INFO_NULL, MPI_COMM_WORLD, baseptr, win, ierr)
if (ierr .ne. 0) call MPI_Abort(MPI_COMM_WORLD, ierr, -1)
CALL MPI_Win_lock_all(0, win, ierr)
if (rank .eq. 0 ) data_array = 0
CALL MPI_Win_unlock_all(win, ierr)
CALL MPI_Win_free(win, ierr)
CALL MPI_FINALIZE(ierr)
END PROGRAM Main_program