real x / 1.0 /, y / 0.0 / print *, x/y end character string*5, out*20 double precision value external exception_handler i = ieee_handler(’set’, ’all’, exception_handler) string = ’1e310’ print *, ’Input string ’, string, ’ becomes: ’, value print *, ’Value of 1e300 * 1e10 is:’, 1e300 * 1e10 i = ieee_flags(’clear’, ’exception’, ’all’, out) end integer function exception_handler(sig, code, sigcontext) integer sig, code, sigcontext(5) print *, ’*** IEEE exception raised!’ return end |
运行时输出:
调试已并行化的程序需要做一些额外工作。下列方案提出了处理该任务的方法。
有一些步骤可以直接进行尝试以确定错误原因。
关闭并行化。
可以采取下列某一步骤:
关闭并行化选项-用 -O3 或 -O4 选项进行编译但不使用任何并行化选项来验证程序是否正确工作。
将线程数设置为 1,然后打开并行化选项进行编译-将环境变量 PARALLEL 设置为 1 来运行程序。
如果问题消失,则可以假定问题是由于使用多线程而引起的。
另外,通过用 -C 进行编译,检查数组引用是否越界。
使用带 —autopar 选项的自动并行化问题可能会指示编译器正在并行化它本来不应并行化的应用程序。
关闭 -reduction。
如果正在使用 —reduction 选项,可能会进行求和约简,并得出稍微不同的答案。尝试不用该选项运行。
使用 fsplit。
如果程序中有许多子例程,可用 fsplit(1) 将它们拆成单独的文件。然后使用或不使用—autopar 编译一些文件。
执行二进制文件并验证结果。
重复该过程直到将问题范围缩小至一个子例程为止。
使用 -loopinfo。
检查哪些循环正在进行并行化、哪些循环未进行并行化。
使用伪子例程。
创建一个不执行任何操作的伪子例程或函数。将该子例程的调用置于几个正在进行并行化的循环内。重新编译并执行。使用 -loopinfo 查看哪些循环正在进行并行化。
继续该过程直到开始获得正确的结果。
逐次反向运行循环。
将 DO I=1,N 替换为 DO I=N,1,-1。如果结果不同,则表明存在数据依赖性。
避免使用循环索引。
替换:
DO I=1,N ... CALL SNUBBER(I) ... ENDDO |
使用:
DO I1=1,N I=I1 ... CALL SNUBBER(I) ... ENDDO |