У меня есть код, который я запускаю на процессоре Intel Xeon Phi Knights Landing (KNL) 7210 (64 ядра) (это ПК в собственном режиме) и использую компилятор Intel c ++ (icpc) версии 17.0.4.Также я запускаю тот же код на процессоре Intel Core 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;
}
...
Particle p[N];
- массив частиц, Particle - это структура чисел с плавающей точкой.N - максимальное количество частиц.
Если убрать флаг -march=native
или заменить его на -march=knl
или -march=core-avx2
, все работает нормально.Этот флаг делает что-то плохое для программы, но что - я не знаю.
Я нашел в интернете (https://software.intel.com/en-us/articles/porting-applications-from-knights-corner-to-knights-landing, https://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
включено в -march=native
флаг для KNL?
Могу ли я заменить флаг -march=native
на -march=knl
при запуске кода на KNL (на i7 все работает)Являются ли они эквивалентными?
Является ли набор флагов записанным оптимальным для достижения максимальной производительности при использовании компилятора Intel?
Как сказал Питер Кордес, я поместил здесь вывод ассемблера, когда программа выдает исключение с плавающей точкой в GDB: 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);
...
}
Я должен подчеркнуть, что я уже использовал feenable, за исключением случаев, когда я получил эту ошибку .Я использовал его с начала отладки программы, потому что у нас были ошибки (исключения с плавающей запятой) в коде, и мы должны были их исправить.