замена «-01» на «-02» опцией компилятора Intel приводит к тому, что FPE сбрасывается при малых значениях цикла - PullRequest
0 голосов
/ 04 октября 2018

Вот код:

#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

в обоих циклах, все работает на любом 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 = большая».Но «-O3» не работает.Я работаю на 8-ядерном процессоре Intel Core i7-3770 и использую компилятор Intel icpc версии 17.0.1.

1 Ответ

0 голосов
/ 04 октября 2018

Общий ответ такой же, как и Добавление флага компилятора Intel "-march = native" в строку компиляции приводит к исключению с плавающей запятой в KNL .ICC без -fp-model except позволяет компилятору создавать asm, который вызывает исключения FP, которых не будет у источника, так что такого рода вещи следует ожидать с feenableexcept.

Вы не показали достаточно asm длядать конкретный ответ относительно того, какой именно прием оптимизации привел к этому в данном конкретном случае.


В моем полном коде мне настоятельно необходимо использовать уровень оптимизации "-O2" или "-O3"вариант.Я не понимаю, какие противоречивые вещи.

Итак, прочитайте документацию Intel, на которую я ссылался в моем предыдущем ответе, в которой это четко объясняется.

Есть 3 "группы"параметры (точный / быстрый / строгий), (ширина) и (except или нет).По умолчанию fast=1 для этой группы.

Руководство пользователя и справочное руководство для компилятора Intel® C ++ 15.0 fp-модель, fp

Так как fast является значением по умолчанию, вы не должны указывать except без ключевого слова группы A или группы B.

Вы можете безопасно использовать любое из этих:

  • -O3 -fp-model precise -fp-model except с feenableexcept()
  • -O3 -fp-model fast=2 с вашей полностью оптимизированной версией выпуска / производства, в которой не используется feenableexcept().

Вы должны использовать -fp-model except, если хотите использовать feenableexcept().В противном случае компилятор будет считать, что создание исключения FP не является видимым побочным эффектом вашей программы.

...