启用浮点异常陷阱后Fortran程序无法在Slurm中运行的问题
解决Slurm环境下Fortran启用FPE陷阱时libxml2触发异常的问题
问题背景
在Fortran代码中启用浮点异常(FPE)陷阱(遵循编译器手册建议)后,生成的二进制文件无法在Slurm队列中运行。直接执行或通过mpirun运行均正常,但通过Slurm批处理脚本或srun执行时,会在调用MPI_Init阶段触发浮点异常,回溯显示异常来自libxml2的xmlCheckVersion函数。
该问题源于libxml2 2.9.11及后续版本的除零错误,当前主流LTS发行版(如Ubuntu 22.04)多使用2.9系列版本;libxml2 2.10版本已修复此问题,但需等待发行商跟进更新。
平台信息:Ubuntu 22.04 LTS, x86_64, gcc 12.2.0, OpenMPI 4.1.4, libxml2 2.9.13
解决方案:延迟启用FPE陷阱
核心思路是避开外部库初始化阶段的异常,先完成MPI_Init调用(此时会触发libxml2的问题代码),再为自身业务代码启用FPE陷阱。
针对gfortran
使用Fortran标准的ieee_exceptions模块手动控制FPE陷阱的开启时机,编译时不再使用-ffpe-trap选项:
修改后的示例代码:
program mwe use mpi_f08 use ieee_exceptions integer :: ierror ! 先完成MPI初始化,绕过libxml2的异常代码 call MPI_Init(ierror) print*, "MPI_Init returned", ierror ! 为后续业务代码启用指定FPE陷阱 call ieee_set_halting_mode(ieee_invalid, .true.) call ieee_set_halting_mode(ieee_divide_by_zero, .true.) call ieee_set_halting_mode(ieee_overflow, .true.) ! 此处编写业务代码 end program
编译命令:
mpif90 mwe.F90
针对ifort
使用Intel编译器提供的fpe_set函数控制FPE陷阱,编译时不再使用-fpe0选项:
修改后的示例代码:
program mwe use mpi_f08 integer :: ierror external :: fpe_set ! 声明Intel的FPE控制函数 ! 先完成MPI初始化 call MPI_Init(ierror) print*, "MPI_Init returned", ierror ! 启用FPE陷阱(对应原-fpe0的行为:捕获无效操作、除零、溢出) call fpe_set(0) ! 此处编写业务代码 end program
编译命令:
mpifort mwe.F90
替代方案(可选)
若系统环境允许,可手动编译安装libxml2 2.10+版本,替换系统默认的2.9.x版本,从根源解决该除零错误。但需注意,替换系统库可能影响其他依赖libxml2的应用,需谨慎操作。
内容的提问来源于stack exchange,提问作者H. Weirauch
相关产品推荐
相关产品推荐

