将 OpenMP 与 Fortran 一起使用时出现内存错误,运行 FFTW
Posted
技术标签:
【中文标题】将 OpenMP 与 Fortran 一起使用时出现内存错误,运行 FFTW【英文标题】:Memory error when using OpenMP with Fortran, running FFTW 【发布时间】: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
,而是在谈论“数据段大小或虚拟地址空间大小”,这是非常不同的东西。对于堆栈,请参阅 ***.com/questions/13264274/… 和 ***.com/questions/20256523/… 中的解释,但我认为这不是你的问题。您只需要在计算机中增加更多 RAM。
@vladimir-f 现在我知道了!根据ulimit -a
输出,您阐明的这些功能都是无限的。
【参考方案1】:
两个具有 500 x 500 x 500 元素的双复数数组需要 4 GB 的内存。您的计算机中的可用内存量可能不足。
如果您只使用小窗口,您可能会考虑不使用整个数组,而只使用其中的一部分。或者使用 MPI 将计算分布在多台计算机上。
或者只是使用内存更大的计算机。
【讨论】:
也许我错过了什么,但500 x 500 x 500 x 2(complex) x 8(double) x 2(num arrays) = 4 e9
不是 4GB 还是 3.73GB? (取决于您选择使用 1000 还是 1024 进行计算)
实际上,需要超过 3.73 GiB,因为 A3D
的非连续切片被传递给没有显式接口的函数,并且编译器正在为每次调用 @987654323 创建一个临时连续副本@.
好的,window
是 2,所以临时数组没什么大不了的。
@vladimir-f 它在具有 12 GB RAM 的 PC 中运行良好(编译中没有 -fmax-stack-var-size=65536
标志)。现在我的问题是另一个与 OpenMP 计算有关的问题,我将在另一个问题中发布。以上是关于将 OpenMP 与 Fortran 一起使用时出现内存错误,运行 FFTW的主要内容,如果未能解决你的问题,请参考以下文章
请看看则个fortran结合openmp并行程序,为啥老出错?
开始尝试在 Win7 下使用 OpenMP 编写 fortran 并行程序