首页 文章

将“-march = native”intel编译器标志添加到编译行会导致KNL上出现浮点异常

提问于
浏览
2

我有一个代码,我在Intel Xeon Phi Knights Landing(KNL)7210(64核)处理器(它是PC,本机模式)上启动并使用Intel c编译器(icpc)版本17.0.4 . 此外,我在英特尔酷睿i7处理器上启动了相同的代码,其中icpc的版本是17.0.1 . 为了更正确,我在我启动它的机器上编译代码(在i7上编译并在i7上启动,对于KNL也是如此) . 我从不在一台机器上制作二进制文件并将其带到另一台机器上 . 使用OpenMP对循环进行并行化和矢量化 . 为了获得最佳性能,我使用了intel编译器标志:

-DCMAKE_CXX_COMPILER="-march=native -mtune=native -ipo16 -fp-model fast=2 -O3 -qopt-report=5 -mcmodel=large"

在i7上一切正常 . 但是在KNL上,代码可以使用 -march=native ,如果要添加此选项,程序会立即抛出浮点异常 . 如果用唯一的标志"-march=native"编译,情况是一样的 . 如果要使用gdb,它指向该段代码的 pp+=alpha/rd 行:

...

the code above is run in 1 thread

double K1=0.0, P=0.0;

#pragma omp parallel for reduction(+:P_x,P_y,P_z, K1,P)
for(int i=0; i<N; ++i)
{
  P_x+=p[i].vx*p[i].m;
  P_y+=p[i].vy*p[i].m;
  P_z+=p[i].vz*p[i].m;
  K1+=p[i].vx*p[i].vx+p[i].vy*p[i].vy+p[i].vz*p[i].vz;
  float pp=0.0;
#pragma simd reduction(+:pp)
  for(int j=0; j<N; ++j) if(i!=j)
  {
    float rd=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)+(p[i].z-p[j].z)*(p[i].z-p[j].z));
    pp+=alpha/rd;
  }
  P+=pp;
}
...

粒子 p[N]; - 一个粒子阵列,粒子是浮子的结构 . N - 粒子的最大数量 .

如果删除标志 -march=native 或用 -march=knl-march=core-avx2 替换它,一切都很好 . 这个标志对程序做了坏事,但是什么 - 我不知道 .

我发现在Internet(https://software.intel.com/en-us/articles/porting-applications-from-knights-corner-to-knights-landinghttps://math-linux.com/linux/tip-of-the-day/article/intel-compilation-for-mic-architecture-knl-knights-landing)中应该使用标志: -xMIC-AVX512 . 我试图使用这个标志和 -axMIC-AVX512 ,但他们给出了同样的错误 .

所以,我想问的是:

  • 为什么 -march=native-xMIC-AVX512 不起作用 -march=knl 有效;是 -xMIC-AVX512 包含在KNL的 -march=native 标志中?

  • 当我在KNL上启动代码时,我可以用 -march=knl 替换标志 -march=native (在i7上一切正常),它们是否相同?

  • 如果使用英特尔编译器,是否为最佳性能编写了最佳标志集?

正如,Peter Cordes所说,当程序在GDB中抛出浮点异常时,我在这里放置了assembeler输出:1)(gdb)disas的输出:

Program received signal SIGFPE, Arithmetic exception.
0x000000000040e3cc in randomizeBodies() ()
Missing separate debuginfos, use: debuginfo-install libgcc-4.8.5- 
16.el7.x86_64 libstdc++-4.8.5-16.el7.x86_64
(gdb) disas
Dump of assembler code for function _Z15randomizeBodiesv:
0x000000000040da70 <+0>:    push   %rbp
0x000000000040da71 <+1>:    mov    %rsp,%rbp
0x000000000040da74 <+4>:    and    $0xffffffffffffffc0,%rsp
0x000000000040da78 <+8>:    sub    $0x100,%rsp
0x000000000040da7f <+15>:   vpxor  %xmm0,%xmm0,%xmm0
0x000000000040da83 <+19>:   vmovups %xmm0,(%rsp)
0x000000000040da88 <+24>:   vxorpd %xmm5,%xmm5,%xmm5
0x000000000040da8c <+28>:   vmovq  %xmm0,0x10(%rsp)
0x000000000040da92 <+34>:   mov    $0x77359400,%ecx
0x000000000040da97 <+39>:   xor    %eax,%eax
0x000000000040da99 <+41>:   movabs $0x5deece66d,%rdx
0x000000000040daa3 <+51>:   mov    %ecx,%ecx
0x000000000040daa5 <+53>:   imul   %rdx,%rcx
0x000000000040daa9 <+57>:   add    $0xb,%rcx
0x000000000040daad <+61>:   mov    %ecx,0x9a3b00(,%rax,8)
0x000000000040dab4 <+68>:   mov    %ecx,%esi
0x000000000040dab6 <+70>:   imul   %rdx,%rsi
0x000000000040daba <+74>:   add    $0xb,%rsi
0x000000000040dabe <+78>:   mov    %esi,0x9e3d00(,%rax,8)
0x000000000040dac5 <+85>:   mov    %esi,%edi
0x000000000040dac7 <+87>:   imul   %rdx,%rdi
0x000000000040dacb <+91>:   add    $0xb,%rdi
0x000000000040dacf <+95>:   mov    %edi,0xa23f00(,%rax,8)
0x000000000040dad6 <+102>:  mov    %edi,%r8d
0x000000000040dad9 <+105>:  imul   %rdx,%r8
0x000000000040dadd <+109>:  add    $0xb,%r8
0x000000000040dae1 <+113>:  mov    %r8d,0xa64100(,%rax,8)
0x000000000040dae9 <+121>:  mov    %r8d,%r9d
0x000000000040daec <+124>:  imul   %rdx,%r9
0x000000000040daf0 <+128>:  add    $0xb,%r9
0x000000000040daf4 <+132>:  mov    %r9d,0xaa4300(,%rax,8)
0x000000000040dafc <+140>:  mov    %r9d,%r10d
0x000000000040daff <+143>:  imul   %rdx,%r10
0x000000000040db03 <+147>:  add    $0xb,%r10
0x000000000040db07 <+151>:  mov    %r10d,0x9a3b04(,%rax,8)
0x000000000040db0f <+159>:  mov    %r10d,%r11d
0x000000000040db12 <+162>:  imul   %rdx,%r11
0x000000000040db16 <+166>:  add    $0xb,%r11
0x000000000040db1a <+170>:  mov    %r11d,0x9e3d04(,%rax,8)
0x000000000040db22 <+178>:  mov    %r11d,%ecx
0x000000000040db25 <+181>:  imul   %rdx,%rcx
0x000000000040db29 <+185>:  add    $0xb,%rcx
0x000000000040db2d <+189>:  mov    %ecx,0xa23f04(,%rax,8)

2)p $ mxcsr的输出:

(gdb) p $mxcsr
1 = [ ZE PE DAZ DM PM FZ ]

3)p $ ymm0.v8_float的输出:

$2 = {3, 3, 3, 3, 3, 3, 3, 3}

4)p $ zmm0.v16_float的输出:

gdb) p $zmm0.v16_float
$3 = {3 <repeats 16 times>}.

我还提到要检测我使用标准的浮点异常

void handler(int sig)
{
  printf("Floating Point Exception\n");
  exit(0);
}
...
int main(int argc, char **argv)
{
  feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW);
  signal(SIGFPE, handler);
  ...
}

我应该强调 i have already been using feenableexcept when i got this error . 我从程序调试开始就使用它,因为我们在代码中有错误(浮点异常)并且必须纠正它们 .

1 回答

  • 1

    您使用 feenableexcept 来取消屏蔽某些FP异常,因此创建无效临时结果的优化会使程序崩溃 .

    英特尔与 -fp-model fast=2 的编译器,如 gcc -ffast-math ,假设FP异常被屏蔽,因此它可以在某些临时计算中导致某些SIMD元素中的 FE_INVALID ,只要一切都在最后解决(例如,混合以修复recip-sqrt出错的元素) ) . 我'd assume that'这是怎么回事 .

    如果你发布了故障的实际指令的反汇编(而不是在该函数的最开始时的一堆整数乘法),我们可以确切地知道什么是优化导致什么是无效的临时,但一般来说你需要使用不太激进的FP选项在编译打开FP异常的构建时 .


    根据Intel's documentation

    -fp-model fast [= 1 | 2]或/ fp:fast [= 1 | 2]默认情况下禁用浮点异常语义,并且无法启用它们,因为您无法在同一编译中同时指定fast和except . 要启用异常语义,必须显式指定另一个关键字(有关详细信息,请参阅其他关键字说明) .

    You need to use -fp-model except if you want the compiler to respect the fact that FP exceptions are a visible side-effect. 默认情况下不启用 .

    如果您打算调用修改FP环境的函数,ISO C表示您应该使用#pragma STDC FENV_ACCESS ON,如果不这样做,对FP环境的修改不能确定启用异常是否真的很重要 . 可能并不重要,只要您在程序启动时执行一次,否则在启用异常之前或之后计算是否发生都很重要 .


    类似地,对于gcc, -ffast-math 包括 -fno-trapping-math ,它承诺编译器FP指令不会引发SIGFPE,只是在MXCSR中静默设置粘滞状态位并产生NaN(无效),-Infinity(溢出)或 0.0 (下溢) .

相关问题