SVML的覆盖功能调用
overriding function calls from SVML
Xeon-Phi骑士登录核心具有快速的exp2
指令vexp2pd
(内在_mm512_exp2a23_pd
)。Intel C 编译器可以使用编译器随附的短量矢量数学库(SVML)矢量化exp
函数。具体来说,它称为FUCTION __svml_exp8
。
但是,当我踏上调试器时,我看不到__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);
}
ICC将生成vexp2pd,但仅在非常放松的数学要求下,按照目标-fimf*交换机指定。
#include <math.h>
void vfoo(int n, double * a, double * r)
{
int i;
#pragma simd
for ( i = 0; i < n; i++ )
{
r[i] = exp(a[i]);
}
}
例如。用-XMIC-AVX512编译-FIMF-DOMAIN-OXCLUSION = 1 -FIMF-ACCURACY-BITS = 22
..B1.12:
vmovups (%rsi,%rax,8), %zmm0
vmulpd .L_2il0floatpacket.2(%rip){1to8}, %zmm0, %zmm1
vexp2pd %zmm1, %zmm2
vmovupd %zmm2, (%rcx,%rax,8)
addq $8, %rax
cmpq %r8, %rax
jb ..B1.12
请确保理解准确性的含义,因为最终结果不仅仅是22位准确的含义,而且VEXP2PD也将其冲洗至零以零为零化的结果,而不论MXCSR中设置的FTZ/DAZ位。
到第二个问题:"我如何安全地覆盖__svml_exp8的呼叫?" 您的方法通常不安全。SVML例程是Intel编译器的内部,并且依靠自定义呼叫约定,因此具有相同名称的通用例程可能会比图书馆例行程序更多的寄存器,并且您可能最终会遇到难以挑选的ABI不合格。p>提供自己的向量函数的更好方法是利用#pragma op opst oplare simd,例如请参阅https://software.intel.com/en-us/node/524514,以及可能使用intrinsics编码的vector_variant属性,请参见https://software.intel.com/en-us/node/523350。只是不要试图覆盖标准数学名称,否则您会遇到错误。
- "No-Const Pointer to Const "调用功能
- 在地图中存储的类中调用功能
- 如何部分专业化功能以用元组元素作为参数调用功能
- 调用功能并将其设置为等于结构
- 在迭代器上调用功能
- 来自Pascal DLL/SO中的C 加载和调用功能
- 在C 中的另一个类中调用功能
- 如何从另一类调用功能
- C 迭代用于循环并在其中调用功能
- 从矢量数组中调用功能
- C 在运行的JVM中调用功能
- 使用条件模板C 调用功能
- 以特定顺序调用功能
- 在没有资格的命名空间中调用功能
- 如果在同一翻译单元中调用功能,为什么需要搬迁
- Portaudio:通过调用功能播放多个生成的声音
- 如何从其他类调用功能指针
- 如何使用从Swift代码中调用的线程在C 上制作异步调用功能
- 从Python(Anaconda)调用C 功能
- 在ShellCode中调用功能