Я написал научный код, и, как обычно, это сводится к вычислению коэффициентов в алгебраическом уравнении на собственные значения: вычисление этих коэффициентов требует интегрирования по многомерным массивам, что резко увеличивает интенсивность использования памяти. После вычисления матричных коэффициентов исходные, предварительно интегрированные многомерные массивы могут быть освобождены, а интеллектуальные решатели возьмут верх, поэтому использование памяти перестает быть большой проблемой. Как вы можете видеть, есть узкое место, а на моем 64-битном, 4-ядерном, 8 потоках, 8 ГБ оперативной памяти, программа вылетает из-за недостаточной памяти.Почему Fortran выделяет такие большие массивы?
Поэтому я внедряю систему, которая контролирует использование памяти, ограничивая размер задач, которые процессы MPI могут принимать при вычислении некоторых элементов матрицы собственных значений. По завершении они будут искать оставшиеся задания, которые будут выполняться, чтобы матрица все еще заполнялась, но была более последовательной и менее параллельной.
Поэтому я проверял, сколько памяти я могу выделить, и вот где начинается путаница: я выделяю парные разряды размером 8 байт (проверяется с помощью sizeof(1)
) и смотрю на статус распределения.
Хотя у меня есть 8 ГБ оперативной памяти, работающей в тесте только с одним процессом, я могу выделить массив размером до (40000,40000)
, что соответствует примерно 13 ГБ памяти! Мой первый вопрос заключается в следующем: как это возможно? Существует ли столько виртуальной памяти?
Во-вторых, я понял, что я тоже могу сделать то же самое для нескольких процессов: до процессов может одновременно выделить эти массивные массивы!
Возможно, это не так?
Кто-нибудь понимает, почему это происходит? И я делаю что-то неправильно?
Edit:
Вот код, который производит вышеупомянутое чудо, по крайней мере, на моей машине. Однако, когда я устанавливаю элементы массивов на какое-то значение, он действительно ведет себя так, как должен, и сбой - или, по крайней мере, начинает вести себя очень медленно, что, я думаю, связано с тем, что используется медленная виртуальная память?
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
Не могли бы вы опубликовать минимальный рабочий код, который воспроизводит это чудо? – francis
Попробуйте установить всю память в ноль - то есть массив = 0.0. Что происходит тогда? Я подозреваю, что это проявление http://stackoverflow.com/questions/864416/are-some-allocators-lazy, которое для HPC в основном является болью в пресловутой ... –
@IanBush Я очень уверен, что это точно проблема. Фактически, я столкнулся с этим вопросом сегодня. OP, если, как только вы выделите память, вы попытаетесь установить ее на 0.0, она, несомненно, сбой. – NoseKnowsAll