Xeon-Phi騎士登陸核心有一個快速exp2
指令vexp2pd
(內部_mm512_exp2a23_pd
)。英特爾C++編譯器可以使用編譯器附帶的短矢量數學庫(SVML)矢量化exp
函數。具體而言,它稱爲功能__svml_exp8
。從SVML覆蓋函數調用
然而,當我通過調試步驟我沒有看到__svml_exp8
使用vexp2pd
指令。這是許多FMA操作的複雜功能。據我所知,vexp2pd
比exp
不太準確,但如果我用-fp-model fast=1
(默認值)或fp-model fast=2
我期望編譯器使用該指令,但事實並非如此。
我有兩個問題。
- 有沒有辦法讓編譯器使用
vexp2pd
? - 我如何安全地重寫調用
__svml_exp8
?
至於第二個問題,這是我迄今所做的。
//exp(x) = exp2(log2(e)*x)
extern "C" __m512d __svml_exp8(__m512d x) {
return _mm512_exp2a23_pd(_mm512_mul_pd(_mm512_set1_pd(M_LOG2E), x));
}
這是安全嗎?有沒有更好的解決方案一個內聯函數?在下面的測試代碼中,這比不覆蓋時大約快3倍。
//https://godbolt.org/g/adI11c
//icpc -O3 -xMIC-AVX512 foo.cpp
#include <math.h>
#include <stdio.h>
#include <x86intrin.h>
extern "C" __m512d __svml_exp8(__m512d x) {
//exp(x) = exp2(log2(e)*x)
return _mm512_exp2a23_pd(_mm512_mul_pd(_mm512_set1_pd(M_LOG2E), x));
}
void foo(double * __restrict x, double * __restrict y) {
__assume_aligned(x, 64);
__assume_aligned(y, 64);
for(int i=0; i<1024; i++) y[i] = exp(x[i]);
}
int main(void) {
double x[1024], y[1024];
for(int i=0; i<1024; i++) x[i] = 1.0*i;
for(int r=0; r<1000000; r++) foo(x,y);
double sum=0;
//for(int i=0; i<1024; i++) sum+=y[i];
for(int i=0; i<8; i++) printf("%f ", y[i]); puts("");
//printf("%lf",sum);
}
你問的編譯器使用'vexp2pd'扔的精度有30位。即使快速數學也不會這樣做。 – Mysticial
@Mysticial我很確定我注意到編譯器使用'vrcp28pd'(實際上你可以在這裏看到它(https://godbolt.org/g/Wya9Ic))。所以如果它使用快速互惠爲什麼不是一個快速的'exp'?看看這個代碼的倒數,它看起來可能是在做一次牛頓迭代或其他事情(否則,所有FMA都會出現這種情況)。這可以解釋爲什麼它使用快速倒數而不是快速的'exp'。 –
我從來沒有聽說過'vfixupimmpd'。奇怪的指示。內在指導說它需要AVXVL,但是共享者爲沒有AVXVL的KNL生成它。 –