调用MPI_ALLREDUCE时触发浮点下溢异常问题咨询
结论
你描述的场景确实会触发本次浮点下溢异常,原因和解决方案如下:
原因说明
- 你通过编译选项
-ffpe-trap=invalid,zero,overflow,underflow开启了浮点下溢捕获,只要任意浮点运算(包括中间临时运算)的结果绝对值小于双精度浮点数的最小正规格化值(约为2.2e-308),就会触发SIGFPE信号,和最终计算结果是否正常无关。 - 从报错栈可以看出你使用的是OpenMPI 4.1.0默认的递归倍增全规约算法
ompi_coll_base_allreduce_intra_recursivedoubling,该算法的求和过程是多进程两两迭代累加,而非直接将所有进程的数值一次性求和:当不同进程的对应phi值为绝对值接近的相反数时,迭代累加的中间步骤会产生极接近0的临时结果,一旦该结果触发下溢条件,就会直接抛出异常,哪怕后续累加的最终结果为0。 - OpenMPI内部的浮点运算会继承主程序的浮点异常开关配置,因此库内部运算产生的下溢事件也会传递到上层业务代码。
验证方案
你可以临时修改编译选项,移除-ffpe-trap中的underflow参数,重新编译运行程序:如果不再抛出浮点异常,即可完全确认是该场景导致的问题。
可行解决方案
- 调试阶段可选择性关闭下溢捕获,仅保留
invalid、zero、overflow三类对结果正确性影响更大的异常检查,大部分科学计算场景下下溢不会导致最终结果严重失真 - 如果必须保留下溢捕获,可在调用
MPI_Allreduce前后通过gfortran内置的ieee_exceptions模块临时关闭下溢异常捕获,调用结束后再恢复原有配置 - 也可以自定义MPI求和操作替换默认的MPI_SUM,避开OpenMPI内部实现的中间下溢问题,该方案会带来少量性能损耗
内容的提问来源于stack exchange,提问作者ATK
相关产品推荐
相关产品推荐

