2 回答

TA貢獻1852條經(jīng)驗 獲得超7個贊
導致此行為的最可能原因是您的堆棧大小限制太?。o論出于何種原因)。由于e_in
每個OpenMP線程都是私有的,因此每個線程在線程堆棧上分配一個副本(即使您已指定-heap-arrays
!)。取1616 kB(或1579 KiB)的202000
元素REAL(KIND=8)
。
堆棧大小限制可以通過以下幾種機制控制:
在標準的Unix系統(tǒng)shell上,堆棧大小的數(shù)量由
ulimit -s <stacksize in KiB>
。這也是主OpenMP線程的堆棧大小限制。pthreads
在創(chuàng)建新線程時,POSIX threads()庫也將此限制的值用作默認線程堆棧大小。OpenMP支持通過環(huán)境變量控制所有其他線程的堆棧大小限制
OMP_STACKSIZE
。它的值是一個帶有可選后綴k
/K
用于KiB,m
/M
f為MiB或g
/G
用于GiB的數(shù)字。此值不會影響主線程的堆棧大小。GNU OpenMP運行時(
libgomp
)識別非標準環(huán)境變量GOMP_STACKSIZE
。如果設(shè)置它會覆蓋值OMP_STACKSIZE
。英特爾OpenMP運行時可識別非標準環(huán)境變量
KMP_STACKSIZE
。如果設(shè)置它會覆蓋值的值,OMP_STACKSIZE
并且還會覆蓋使用GOMP_STACKSIZE
兼容性O(shè)penMP運行時的值(這是默認值,因為當前唯一可用的英特爾OpenMP運行時庫是compat
一個)。如果
*_STACKSIZE
未設(shè)置任何變量,則英特爾OpenMP運行時的默認值為2m
32位體系結(jié)構(gòu)和4m
64 位體系結(jié)構(gòu)。在Windows上,主線程的堆棧大小是PE頭的一部分,并由鏈接器嵌入到那里。如果使用Microsoft
LINK
進行鏈接,則使用/STACK:reserve[,commit]
。該reserve
參數(shù)指定以字節(jié)為單位的最大堆棧大小而可選commit
參數(shù)指定初始提交大小。兩者都可以使用0x
前綴指定為十六進制值。如果不能重新鏈接可執(zhí)行文件,則可以通過編輯PE頭來修改堆棧大小EDITBIN
。它采用與鏈接器相同的堆棧相關(guān)參數(shù)。使用MSVC的整個程序優(yōu)化enabled(/GL
)編譯的程序無法編輯。Win32目標的GNU鏈接器支持通過
--stack
參數(shù)設(shè)置堆棧大小。要直接從GCC傳遞選項,-Wl,--stack,<size in bytes>
可以使用。
請注意,線程堆棧實際上是使用由(或默認值)設(shè)置的大小分配的*_STACKSIZE
,與主線程的堆棧不同,主線程從較小的堆棧開始,然后根據(jù)需求增長到設(shè)置的限制。因此,不要設(shè)置*_STACKSIZE
為任意大的值,否則可能會達到進程虛擬內(nèi)存大小限制。
這里有些例子:
$ ifort -openmp my_module.f90 main.f90
將主堆棧大小限制設(shè)置為1 MiB(額外的OpenMP線程將默認獲得4 MiB):
$ ulimit -s 1024$ ./a.outzsh: segmentation fault (core dumped) ./a.out
將主堆棧大小限制設(shè)置為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)
將主堆棧大小限制設(shè)置為2 MiB,將附加線程的堆棧大小設(shè)置為1 MiB:
$ ulimit -s 2048$ KMP_STACKSIZE=1m ./a.outzsh: segmentation fault (core dumped) KMP_STACKSIZE=1m ./a.out
在大多數(shù)Unix系統(tǒng)上,主線程的堆棧大小限制由PAM或其他登錄機制設(shè)置(請參閱參考資料/etc/security/limits.conf
)。Scientific Linux 6.3的默認值為10 MiB。
另一種可能導致錯誤的可能情況是虛擬地址空間限制設(shè)置得太低。例如,如果虛擬地址空間限制為1 GiB且線程堆棧大小限制設(shè)置為512 MiB,則OpenMP運行時將嘗試為每個其他線程分配512 MiB。使用兩個線程,只有堆棧的1 GiB,當代碼,共享庫,堆等的空間相加時,虛擬內(nèi)存大小將超過1 GiB,并且會發(fā)生錯誤:
將虛擬地址空間限制設(shè)置為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運行時庫將無法創(chuàng)建新線程,并在中止程序終止之前通知您。

TA貢獻1836條經(jīng)驗 獲得超3個贊
分段錯誤是由于使用OpenMP時的堆棧內(nèi)存限制。使用上一個答案中的解決方案并沒有解決我在Windows操作系統(tǒng)上的問題。使用內(nèi)存分配到堆而不是堆棧內(nèi)存似乎工作:
integer, parameter :: nmax = 202000 real(dp), dimension(:), allocatable :: e_ininteger iallocate(e_in(nmax))e_in = 0! rest of codedeallocate(e_in)
此外,這不涉及更改任何默認環(huán)境參數(shù)。
在此確認并參考ohm314的解決方案:使用堆內(nèi)存分配的大型陣列
添加回答
舉報