C++11+fortran+OpenACC移植程序从核报错
-
求大神指点~~
程序概况
我目前移植的应用是c++11编写的, 规模在数十万行,数值计算密集部分使用fortran编写,该程序在x86机器上使用valgrind检测没有内存泄漏。现在程序在主核上c++11使用gcc530, fortran用swafort -host编译然后链接,可以正常运行。
编译配置:
C++11部分采用
module load sw
提供的mpiswg++
编译器, 开启-std=gnu++11
和-mhybrid
选项。
fortran部分采用系统默认的swafort
编译器, 开启-fpe3
。链接选项:
"\ -L/usr/sw-mpp/mpi2/mpiswgcc/lib -L/usr/sw-mpp/lib \ -lmpifort -lgfortran -lgfortran_slave -lslave -lathread -lmaster -lc_slave -lglibc_slave \ -L/usr/sw-mpp/swacc/swacc-2.0.0-1458-fix-1473/lib/sw5 \ -Wl,-zmuldefs -static -lswacc_host -lswacc_slave -lm_slave \ -L/usr/sw-mpp/swcc/swgcc530-tools/usr_sw5/lib -lslave \ -L/usr/sw-mpp/swcc/lib/gcc-lib/sw_64-swcc-linux/5.421-sw-500/lib \ -lfortran_slave -lfortran -lffio -lffio_slave "
错误信息
在fortran中加入OpenACC指导语句之后, 程序会报各种问题, 比如在一个完美嵌套循环上加一个OpenACC, 程序就会报段错误, 循环代码和报错信息如附录所示。
示例代码:c$acc parallel loop copyout(dux) DO K=ifirst1,ilast1 DO J=ifirst0,ilast0 DO L=1,4 DUX(J,K,L)= 0.0 ENDDO ENDDO ENDDO c$acc end parallel loop
其中一种错误:
CATCHSIG: Myid = 0(CPU 8,CG 0), si_signo = 11(Segmentation Fault: PC = 0x4ff04642f8) [vn000008:mpi_rank_0][MPIDI_CH3_Abort] application called MPI_Abort(MPI_COMM_WORLD, 1000) - process 0: Invalid argument (22)
目前的尝试
我做过一些尝试:
-
在主核的c++代码上添加一些打印语句也会影响报错类型,目前发现的报错包括:
- SPDE Error
- Fload Point Exception
- Segmentation Fault
- DMA descriptor examination
-
有时在完美嵌套循环上加collapse可以使原本报spde error的程序正常运行, 但有些代码段不加collapse可以正常运行但加了collapse反而会报错。
-
尝试使用swacc生成中间代码, 然后用gcc530编译主从核代码, 问题依然存在, 与用swacc编译产生的结果一致。
-
在已经出错(比如FPE)的acc加速区内, 添加打印语句, 从核没有打印输出, 但程序可以正常运行了。
-
尝试将fortran的数值内核单独摘出来,使用简单的c++11代码(约70行)调用数值内核,使用与主程序相同的链接脚本和编译器套件, acc加速部分工作正常且有加速, 从核可以正常打印, 添加的各种copyin、local、collapse等均可以正常工作。
2020/07/24更新:
* 使用athread重新改写从核代码, 从核直接访问主存程序可以运行,直接访问主存可以正确赋值, 但在调试过程中发现, 添加打印语句write(*,*) my_id
会报SDLB错。报错信息如下:+------------------------------------------------------------------------------+ | CPE Exception Encountered | +------------------------------------------------------------------------------+ SDLB Exception Happended +------------------------------------------------------------------------------+ | Decoding CPE spots | +------------------------------------------------------------------------------+ Last function spawned 4ff04109c0 +------------------------------------------------------------------------------+ | Decode of CPE PCs | +------------------------------------------------------------------------------+ 0: 4ff0444bf0 1: 4ff0436758 2: 4ff0436758 3: 4ff0436758 4: 4ff0436758 5: 4ff0436758 6: 4ff0436758 7: 4ff0436758 8: 4ff0436760 9: 4ff0436760 10: 4ff0436760 11: 4ff0436758 12: 4ff0436758 13: 4ff0436758 14: 4ff0436760 15: 4ff0436760 16: 4ff0436758 17: 4ff0436760 18: 4ff0436758 19: 4ff0436760 20: 4ff0436758 21: 4ff0436760 22: 4ff0436758 23: 4ff0436760 24: 4ff0436760 25: 4ff0436758 26: 4ff0436760 27: 4ff0436758 28: 4ff0436758 29: 4ff0436758 30: 4ff0436760 31: 4ff0436758 32: 4ff0436758 33: 4ff0436758 34: 4ff0436760 35: 4ff0436758 36: 4ff0436760 37: 4ff0436760 38: 4ff0436758 39: 4ff0436758 40: 4ff0436758 41: 4ff0436760 42: 4ff0436760 43: 4ff0436758 44: 4ff0436760 45: 4ff0436758 46: 4ff0436760 47: 4ff0436760 48: 4ff0436760 49: 4ff0436758 50: 4ff0436758 51: 4ff0436758 52: 4ff0436760 53: 4ff0436760 54: 4ff0436760 55: 4ff0436758 56: 4ff0436758 57: 4ff0436760 58: 4ff0436758 59: 4ff0436758 60: 4ff0436758 61: 4ff0436760 62: 4ff0436758 63: 4ff0436758 +------------------------------------------------------------------------------+ | Decode of SDLB error spot | +------------------------------------------------------------------------------+ TC_SDLB_ERR_SPOT: 2c0200700001c920 REQ_TYPE: read TC_SDLB_REQ_ADDR: 700001c920 SRC_PE: 0 GRAIN: 1 SRC_TYPE: cpe OUT_OF_RANGE: yes OUT_OF_PERM: no
2020/07/25更新:
- 在程序中只对一个fortran的赋值循环添加openacc指导语句并不添加任何copy操作(没有DMA?)程序可以运行, 但赋的值与主核运行时的赋值不一致: 下文中的循环是将
tracergt0
和tracelft0
赋值为1.0, 主核使用swafort -host
编译打印得到的结果均是1.0, 但打开openacc之后, 用swafort
编译, 得到两个数组在赋值之后得到的数组内有大量其他不正常数字, 如8.33833108929440958E-2等。
c$acc parallel loop do ic2=ifirst2-FACEG,ilast2+FACEG do ic1=ifirst1-FACEG,ilast1+FACEG ie0=ifirst0-FACEG tracergt0(ie0,ic1,ic2)=1.0 tracelft0(ie0,ic1,ic2)=1.0 do ie0=ifirst0+1-FACEG,ilast0+FACEG tracelft0(ie0,ic1,ic2)=1.0 tracergt0(ie0,ic1,ic2)=1.0 enddo ie0=ilast0+FACEG+1 tracelft0(ie0,ic1,ic2)=1.0 tracergt0(ie0,ic1,ic2)=1.0 enddo enddo c$acc end parallel loop
-
-
代码好长,我有阅读Fortran恐惧症,建议是你首先在逻辑上研究一下有没有并行写,就是最外层循环的两个下标有对数组同一个位置的更新。
另外你刚开始那个代码我觉得珠海要是循环顺序的问题。考虑试一下:DO L=1,4 c$acc parallel loop DO K=ifirst1,ilast1 c$acc data copyout(dux(:, k, l)) DO J=ifirst0,ilast0 DUX(J,K,L)= 0.0 ENDDO c$acc end data ENDDO c$acc end parallel loop ENDDO
-
loop不能和copy配合