Fortran程序在Cray环境下使用外部输入整数分配动态数组报错
问题描述
如下Fortran代码在Intel、GNU编译器下可正常编译运行:
program simplarray implicit none real, allocatable, dimension(:,:,:) :: a character(len=32) :: cmdarg integer :: n = 0 call get_command_argument(1, cmdarg) read(cmdarg,'(i)') n print '("n=",i5)', n call flush(6) allocate(a(n,n,2)) print '("a is dimensioned ", 3i5)', shape(a) deallocate(a) end program
正常运行输出:
> ./a.out 50 n= 50 a is dimensioned 50 50 2
但在Cray环境下运行报错:
> ./a.out 10 n= 10 Illegal instruction (core dumped)
如果将n改为硬编码赋值,运行正常:
integer :: n = 10 ! call get_command_argument(1, cmdarg) ! read(cmdarg,'(i)') n
硬编码后的运行输出:
./a.out n= 10 a is dimensioned 10 10 2
尝试从文本文件读取n的值,故障现象完全一致:
integer :: n open(unit=11, file='size.txt') read(11,*) n close(11)
补充信息:
- 同版本12.0.3的Cray编译器在另一台Cray平台运行该程序完全正常
- 编译指令仅为在Intel Broadwell架构的登录节点执行:
ftn simplarray.F90
解答
问题根因
这是Cray编译环境典型的编译节点与运行节点CPU架构不兼容问题,和代码本身逻辑无关:
- Cray的
ftn编译器默认会针对当前编译所在节点的CPU架构生成最高优化等级的指令,你在Intel Broadwell架构的登录节点编译,生成的程序会用到Broadwell专属的AVX2、BMI2等扩展指令集。 - 如果你提交运行的计算节点CPU架构比Broadwell旧(比如Haswell、Sandy Bridge等),这些专属指令无法被识别,就会抛出
Illegal instruction错误。
为什么硬编码n时可以正常运行
当n是硬编码的常量时,编译器在编译阶段就能完成常量传播、数组大小计算,甚至可以把数组优化为静态分配,不会触发动态分配场景下的优化指令逻辑。只有当n是运行时动态获取的变量时,编译器会插入针对编译节点架构优化的动态内存对齐、数组维度计算的SIMD指令,这部分指令在旧架构节点无法执行。
你可以直接在编译用的登录节点运行该程序验证,大概率可以正常执行,只有提交到计算节点时才会报错。
为什么同版本编译器的另一台Cray平台无故障
那台平台的登录节点和计算节点CPU架构完全一致,编译生成的指令在运行节点可以正常支持。
解决方案
- 编译时指定目标运行节点的CPU架构参数,示例:
- 运行节点为Intel Haswell:
ftn -xCORE-AVX2 simplarray.F90 - 运行节点为Intel Sandy/Ivy Bridge:
ftn -xAVX simplarray.F90 - 需要兼容多代Intel架构:
ftn -axCORE-AVX2,AVX,SSE4.2 simplarray.F90
- 运行节点为Intel Haswell:
- 直接在目标计算节点上编译程序,编译器会自动适配当前节点架构生成兼容指令。
内容的提问来源于stack exchange,提问作者bob.sacamento
相关产品推荐
相关产品推荐

