2 回答
TA贡献1852条经验 获得超7个赞
导致此行为的最可能原因是您的堆栈大小限制太小(无论出于何种原因)。由于e_in
每个OpenMP线程都是私有的,因此每个线程在线程堆栈上分配一个副本(即使您已指定-heap-arrays
!)。取1616 kB(或1579 KiB)的202000
元素REAL(KIND=8)
。
堆栈大小限制可以通过以下几种机制控制:
在标准的Unix系统shell上,堆栈大小的数量由
ulimit -s <stacksize in KiB>
。这也是主OpenMP线程的堆栈大小限制。pthreads
在创建新线程时,POSIX threads()库也将此限制的值用作默认线程堆栈大小。OpenMP支持通过环境变量控制所有其他线程的堆栈大小限制
OMP_STACKSIZE
。它的值是一个带有可选后缀k
/K
用于KiB,m
/M
f为MiB或g
/G
用于GiB的数字。此值不会影响主线程的堆栈大小。GNU OpenMP运行时(
libgomp
)识别非标准环境变量GOMP_STACKSIZE
。如果设置它会覆盖值OMP_STACKSIZE
。英特尔OpenMP运行时可识别非标准环境变量
KMP_STACKSIZE
。如果设置它会覆盖值的值,OMP_STACKSIZE
并且还会覆盖使用GOMP_STACKSIZE
兼容性OpenMP运行时的值(这是默认值,因为当前唯一可用的英特尔OpenMP运行时库是compat
一个)。如果
*_STACKSIZE
未设置任何变量,则英特尔OpenMP运行时的默认值为2m
32位体系结构和4m
64 位体系结构。在Windows上,主线程的堆栈大小是PE头的一部分,并由链接器嵌入到那里。如果使用Microsoft
LINK
进行链接,则使用/STACK:reserve[,commit]
。该reserve
参数指定以字节为单位的最大堆栈大小而可选commit
参数指定初始提交大小。两者都可以使用0x
前缀指定为十六进制值。如果不能重新链接可执行文件,则可以通过编辑PE头来修改堆栈大小EDITBIN
。它采用与链接器相同的堆栈相关参数。使用MSVC的整个程序优化enabled(/GL
)编译的程序无法编辑。Win32目标的GNU链接器支持通过
--stack
参数设置堆栈大小。要直接从GCC传递选项,-Wl,--stack,<size in bytes>
可以使用。
请注意,线程堆栈实际上是使用由(或默认值)设置的大小分配的*_STACKSIZE
,与主线程的堆栈不同,主线程从较小的堆栈开始,然后根据需求增长到设置的限制。因此,不要设置*_STACKSIZE
为任意大的值,否则可能会达到进程虚拟内存大小限制。
这里有些例子:
$ ifort -openmp my_module.f90 main.f90
将主堆栈大小限制设置为1 MiB(额外的OpenMP线程将默认获得4 MiB):
$ ulimit -s 1024$ ./a.outzsh: segmentation fault (core dumped) ./a.out
将主堆栈大小限制设置为1700 KiB:
$ ulimit -s 1700$ ./a.out 0.000000000000000E+000 (0.000000000000000E+000,0.000000000000000E+000) 0.000000000000000E+000 (0.000000000000000E+000,0.000000000000000E+000)
将主堆栈大小限制设置为2 MiB,将附加线程的堆栈大小设置为1 MiB:
$ ulimit -s 2048$ KMP_STACKSIZE=1m ./a.outzsh: segmentation fault (core dumped) KMP_STACKSIZE=1m ./a.out
在大多数Unix系统上,主线程的堆栈大小限制由PAM或其他登录机制设置(请参阅参考资料/etc/security/limits.conf
)。Scientific Linux 6.3的默认值为10 MiB。
另一种可能导致错误的可能情况是虚拟地址空间限制设置得太低。例如,如果虚拟地址空间限制为1 GiB且线程堆栈大小限制设置为512 MiB,则OpenMP运行时将尝试为每个其他线程分配512 MiB。使用两个线程,只有堆栈的1 GiB,当代码,共享库,堆等的空间相加时,虚拟内存大小将超过1 GiB,并且会发生错误:
将虚拟地址空间限制设置为1 GiB,并使用另外两个具有512 MiB堆栈的线程运行(我已将注释注释掉omp_set_num_threads()
):
$ ulimit -v 1048576$ KMP_STACKSIZE=512m OMP_NUM_THREADS=3 ./a.outOMP: Error #34: System unable to allocate necessary resources for OMP thread:OMP: System error #11: Resource temporarily unavailableOMP: Hint: Try decreasing the value of OMP_NUM_THREADS.forrtl: error (76): Abort trap signal... trace omitted ...zsh: abort (core dumped) OMP_NUM_THREADS=3 KMP_STACKSIZE=512m ./a.out
在这种情况下,OpenMP运行时库将无法创建新线程,并在中止程序终止之前通知您。
TA贡献1836条经验 获得超3个赞
分段错误是由于使用OpenMP时的堆栈内存限制。使用上一个答案中的解决方案并没有解决我在Windows操作系统上的问题。使用内存分配到堆而不是堆栈内存似乎工作:
integer, parameter :: nmax = 202000 real(dp), dimension(:), allocatable :: e_ininteger iallocate(e_in(nmax))e_in = 0! rest of codedeallocate(e_in)
此外,这不涉及更改任何默认环境参数。
在此确认并参考ohm314的解决方案:使用堆内存分配的大型阵列
添加回答
举报