【发布时间】:2017-10-22 15:49:02
【问题描述】:
我正在一个 fortran 程序中测试 FFTW,因为我需要使用它。由于我正在处理巨大的矩阵,我的第一个解决方案是使用 OpenMP。当我的矩阵有维度500 x 500 x 500时,会发生以下错误:
Operating system error:
Program aborted. Backtrace:
Cannot allocate memory
Allocation would exceed memory limit
我使用以下代码编译了代码:gfortran -o test teste_fftw_openmp.f90 -I/usr/local/include -L/usr/lib/x86_64-linux-gnu -lfftw3_omp -lfftw3 -lm -fopenmp
PROGRAM test_fftw
USE omp_lib
USE, intrinsic:: iso_c_binding
IMPLICIT NONE
INCLUDE 'fftw3.f'
INTEGER::i, DD=500
DOUBLE COMPLEX:: OUTPUT_FFTW(3,3,3)
DOUBLE COMPLEX, ALLOCATABLE:: A3D(:,:,:), FINAL_OUTPUT(:,:,:)
integer*8:: plan
integer::iret, nthreads
INTEGER:: indiceX, indiceY, indiceZ, window=2
!! TESTING 3D FFTW with OPENMP
ALLOCATE(A3D(DD,DD,DD))
ALLOCATE(FINAL_OUTPUT(DD-2,DD-2,DD-2))
write(*,*) '---------------'
write(*,*) '------------TEST 3D FFTW WITH OPENMP----------'
A3D = reshape((/(i, i=1,DD*DD*DD)/),shape(A3D))
CALL dfftw_init_threads(iret)
CALL dfftw_plan_with_nthreads(nthreads)
CALL dfftw_plan_dft_3d(plan, 3,3,3, OUTPUT_FFTW, OUTPUT_FFTW, FFTW_FORWARD, FFTW_ESTIMATE)
FINAL_OUTPUT=0.
!$OMP PARALLEL DO DEFAULT(SHARED) SHARED(A3D,plan,window) &
!$OMP PRIVATE(indiceX, indiceY, indiceZ, OUTPUT_FFTW, FINAL_OUTPUT)
DO indiceZ=1,10!500-window
write(*,*) 'INDICE Z=', indiceZ
DO indiceY=1,10!500-window
DO indiceX=1,10!500-window
CALL dfftw_execute_dft(plan, A3D(indiceX:indiceX+window,indiceY:indiceY+window, indiceZ:indiceZ+window), OUTPUT_FFTW)
FINAL_OUTPUT(indiceX,indiceY,indiceZ)=SUM(ABS(OUTPUT_FFTW))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
call dfftw_destroy_plan(plan)
CALL dfftw_cleanup_threads()
DEALLOCATE(A3D,FINAL_OUTPUT)
END PROGRAM test_fftw
请注意,当我只使用一个巨大的矩阵(A3D)而不在该矩阵的所有值中运行循环时会发生此错误(对于在所有值中运行,我应该将三个(嵌套)循环的限制为500-window。
我试图在编译中用-mcmodel=medium 解决这个问题(提示here 和here),但没有成功。
我用gfortran -o test teste_fftw_openmp.f90 -I/usr/local/include -L/usr/lib/x86_64-linux-gnu -lfftw3_omp -lfftw3 -lm -fopenmp -fmax-stack-var-size=65536编译时成功了
所以,我不明白:
1)如果巨大的矩阵是共享变量,为什么会有内存分配问题?
2)如果我有更多巨大的矩阵变量,我找到的解决方案会起作用吗?比如多3个矩阵500 x 500 x 500来存储计算结果。
3)在我发现的提示中,人们说使用可分配数组/矩阵可以解决,但我使用没有任何区别。我还需要为此做些什么吗?
【问题讨论】:
-
您使用 64 位编译器和操作系统吗?你有多少内存?大约需要 4 GB 的内存。加上
reshape的另一个可能的临时地址,所以另一个可能的 2 GB。 -
使用
ulimit -a检查进程资源限制。也许数据段大小或虚拟地址空间大小是有限的。 -
我在有限的 PC 上进行了测试,具有 4GB 的 RAM。我将尽快使用 12 GB 进行测试(完成后在此处更新)。关于
ulimit -a,stack size是8192 kb。抱歉@hristo-iliev,但这个 8 Mb 的限制到底是什么? -
@victortxa Hristo 不是在谈论
stack size,而是在谈论“数据段大小或虚拟地址空间大小”,这是非常不同的东西。对于堆栈,请参阅 stackoverflow.com/questions/13264274/… 和 stackoverflow.com/questions/20256523/… 中的解释,但我认为这不是你的问题。您只需要在计算机中增加更多 RAM。 -
@vladimir-f 现在我知道了!根据
ulimit -a输出,您阐明的这些功能都是无限的。
标签: memory-management fortran openmp gfortran