将“ -01”替换为“ -02”英特尔编译器选项会导致FPE的循环次数减少

时间:2018-10-04 10:22:26

标签: c++ intel compiler-optimization

代码如下:

#include <math.h>
#include <iostream>
#include <omp.h>
#include <fenv.h>
#include <signal.h>

void handler(int sig)
{
  printf("Floating Point Exception\n");
  exit(0);
}
const float alpha=1.5;
const unsigned int N=2;
struct Particle
{
  float x, y, z;
  float m;
};
Particle p[N] __attribute__((aligned(64)));
void interaction()
{
  double P=0.0;
#pragma omp parallel for reduction(+:P)
  for(int i=0; i<N; ++i)
  {
    float PP=0.0;
  #pragma simd reduction(+:PP)
  //#pragma novector
    for(int j=0; j<N; ++j) if(i!=j)
    {
      float rdist1=sqrtf((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/rdist1;
    }
    P+=PP;
  }
  std::cout<<"P="<<P<<std::endl;
}
void randomizeBodies()
{
  double pot_en=0.;
  const double pi=3.1415926536;   
  float RADIUS=pow(10.0*N,1.0/3.0);
#pragma omp single
#pragma novector
  for(int i=0; i<N; ++i)
  {
    float DISTANCE=0.0f;
    if(i>0)
    {
      while(DISTANCE<=1.0f)
      {
        float theta=pi*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
        float phi=2*pi*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
        float rr=RADIUS*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
        p[i].x =rr*sin(theta)*cos(phi);
        p[i].y =rr*sin(theta)*sin(phi);
        p[i].z =rr*cos(theta);
        DISTANCE=10000.0f;
      #pragma simd reduction(min:DISTANCE)      
        for(int j=0; j<i; ++j)
        {
          float dij=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));
          if(dij<DISTANCE) DISTANCE=dij;
        }
      }
    }
    else
    {
      float theta=pi*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
      float phi=2*pi*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
      float rr=RADIUS*static_cast <float> (rand())/(static_cast <float> (RAND_MAX));
      p[i].x =rr*sin(theta)*cos(phi);
      p[i].y =rr*sin(theta)*sin(phi);
      p[i].z =rr*cos(theta);
    }  
  }
#pragma omp parallel for reduction(+:pot_en)
  for(int i=0; i<N; ++i)
  {
    float pp=0.0;
  #pragma simd reduction(+:pp)
  //#pragma novector
    for(int j=0; j<N;  ++j) if(i!=j)
    {
      float rd=sqrtf((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;
    }
    pot_en+=pp;
  }
  pot_en/=2;
  std::cout<<"P="<<pot_en<<std::endl;
}
int main(int argc, char **argv)
{
  feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW);
  signal(SIGFPE, handler);
  randomizeBodies();
  interaction();
}

我使用以下命令对其进行编译

-DCMAKE_CXX_COMPILER=icpc -DCMAKE_CXX_FLAGS="-O2"

并带有“ -g”,它给出以下输出

Program received signal SIGFPE, Arithmetic exception.
0x00000000004024ab in randomizeBodies ()
at /home/70-gaa/source/GPU/ERROR24/error.cpp:90
90            pp+=alpha/rd;
(gdb) 

N = 2,4 。但是在 N> = 8 时可以使用。 如果要发表评论

 #pragma simd reduction

取消注释

 #pragma novector

在两个for循环中,所有内容都可以在任何N处工作。如果使用“ -01”,则所有内容也可以在任何N处工作。 如果要使用向量化和“ -O2”或“ -O3”,程序将在 N = 2,4 处但在 N> = 8 处引发浮点异常。作品。 为什么?原则上,我需要使用以下编译行:     -DCMAKE_CXX_FLAGS =“-march = native -mtune = native     -ipo16 -fp-model fast = 2 -O3 -qopt-report = 5 -mcmodel = large”。 但是“ -O3”无效。 我使用Intel Core i7-3770 8核CPU,并使用Intel编译器icpc版本17.0.1。

1 个答案:

答案 0 :(得分:0)

一般答案与adding "-march=native" intel compiler flag to the compilation line leads to a floating point exception on KNL相同。不带-fp-model except的ICC允许编译器生成导致源程序不会导致FP异常的asm,因此使用feenableexcept应该具有这种效果。

您还没有显示足够的asm来给出具体答案,以了解在这种特定情况下究竟是什么优化技巧导致了这一问题。


  

在我的完整代码中,我强烈需要使用“ -O2”或“ -O3”优化级别选项。我不明白发生了什么冲突。

因此,请阅读我在上一个答案中链接的英特尔文档,其中对此进行了清晰的解释。

有3个“组”选项(精确/快速/严格),(宽度)和(是否为except)。该组的默认值为fast=1

  

英特尔®C ++编译器15.0 fp-model, fp

用户和参考指南      

由于默认为fast,因此,如果没有A组或B组关键字,则不能指定except

您可以安全地使用以下任意一个:

  • -O3 -fp-model precise -fp-model exceptfeenableexcept()
  • -O3 -fp-model fast=2以及不使用feenableexcept()的完全优化的发行/生产版本。

如果您想使用-fp-model except,则必须使用feenableexcept()。否则,编译器将假定导致FP异常不是程序的可见副作用。