我编写了一段科学代码,像往常一样,这归结为计算代数特征值方程中的系数:计算这些系数需要对多维数组进行积分,这会迅速大幅增加内存使用量。一旦计算出矩阵系数,就可以释放原始的预积分多维数组,并由智能求解器接管,因此内存使用不再是大问题。正如您所看到的,存在瓶颈,在我的 64 位、4 核、8 线程、8GB 内存笔记本电脑上,程序因内存不足而崩溃。
因此,我正在实现一个系统,通过限制 MPI 处理在计算某些特征值矩阵元素时可以承担的任务的大小来控制内存使用情况。完成后,他们将寻找剩余的工作来完成,以便矩阵仍然被填充,但以更顺序和更少并行的方式。
因此,我正在检查可以分配多少内存,这就是混乱开始的地方:我分配了大小为 8 字节的双精度数(使用sizeof(1)
)并查看分配状态。
虽然我有 8 GB 的可用内存来运行仅 1 个进程的测试,但我可以分配一个最大大小的数组(40000,40000)
,大约对应13GB内存!我的第一个问题是:这怎么可能?虚拟内存有这么多吗?
其次,我意识到我也可以对多个进程做同样的事情:最多16流程可以,同时地分配这些巨大的数组!
这不可能吧?
有人明白为什么会发生这种情况吗?我是否做错了什么?
Edit:
这是产生上述奇迹的代码,至少在我的机器上是这样。然而,当我将数组的元素设置为某个值时,它确实会按其应有的方式运行并崩溃——或者至少开始运行very缓慢,我猜这是因为使用了缓慢的虚拟内存?
program test_miracle
use ISO_FORTRAN_ENV
use MPI
implicit none
! global variables
integer, parameter :: dp = REAL64 ! double precision
integer, parameter :: max_str_ln = 120 ! maximum length of filenames
integer :: ierr ! error variable
integer :: n_procs ! MPI nr. of procs
! start MPI
call MPI_init(ierr) ! initialize MPI
call MPI_Comm_size(MPI_Comm_world,n_procs,ierr) ! nr. MPI processes
write(*,*) 'RUNNING MPI WITH', n_procs, 'processes'
! call asking for 6 GB
call test_max_memory(6000._dp)
call MPI_Barrier(MPI_Comm_world,ierr)
! call asking for 13 GB
call test_max_memory(13000._dp)
call MPI_Barrier(MPI_Comm_world,ierr)
! call asking for 14 GB
call test_max_memory(14000._dp)
call MPI_Barrier(MPI_Comm_world,ierr)
! stop MPI
call MPI_finalize(ierr)
contains
! test whether maximum memory feasible
subroutine test_max_memory(max_mem_per_proc)
! input/output
real(dp), intent(in) :: max_mem_per_proc ! maximum memory per process
! local variables
character(len=max_str_ln) :: err_msg ! error message
integer :: n_max ! maximum size of array
real(dp), allocatable :: max_mem_arr(:,:) ! array with maximum size
integer :: ierr ! error variable
write(*,*) ' > Testing whether maximum memory per process of ',&
&max_mem_per_proc/1000, 'GB is possible'
n_max = ceiling(sqrt(max_mem_per_proc/(sizeof(1._dp)*1.E-6)))
write(*,*) ' * Allocating doubles array of size', n_max
allocate(max_mem_arr(n_max,n_max),STAT=ierr)
err_msg = ' * cannot allocate this much memory. Try setting &
&"max_mem_per_proc" lower'
if (ierr.ne.0) then
write(*,*) err_msg
stop
end if
!max_mem_arr = 0._dp ! UNCOMMENT TO MAKE MIRACLE DISSAPEAR
deallocate(max_mem_arr)
write(*,*) ' * Maximum memory allocatable'
end subroutine test_max_memory
end program test_miracle
要保存在test.f90
然后编译并运行
mpif90 test.f90 -o test && mpirun -np 2 ./test