代码如下:
#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。
答案 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 except
与feenableexcept()
-O3 -fp-model fast=2
以及不使用feenableexcept()
的完全优化的发行/生产版本。如果您想使用-fp-model except
,则必须使用feenableexcept()
。否则,编译器将假定导致FP异常不是程序的可见副作用。