对于一个游戏,我的工作-需要的能力,以运行百万的“exp”调用向量。基本上
void vector_exp(const double *x, const double *result, int n)
{
for (int i=0 ; i<n ; i++) result[i] = exp(x[i]) ;
}
对于我的特定情况,输入都是-50..+50。需要双精度,8位小数匹配当前“exp”-以通过测试用例。
我对“日志”也有同样的挑战。输入范围为1 e-7至1 e7。
希望利用AVX 512指令-这应该能够做(理论上)8倍精度的时间。我已经检索到了glibc代码(包括为AVX构建的“C”版本和“.S”版本),但我不确定如何继续前进。
https://github.com/bminor/glibc/tree/master/sysdeps/x86_64/fpu
1条答案
按热度按时间qyyhg6bp1#
我相信其他的答案比我的好-运行一个非常快速和肮脏的多项式近似,我最终得到了这些。
跨独立的
exp2()
或log2()
操作的乱序执行可以使用六阶多项式的霍纳规则来处理FMA依赖链。另请参阅Agner Fog的VCL实现,其目标是高精度,接近
double
的全精度:exp_d
模板,支持2.0
、exp(x-1)
与exp(x)
。(有关正确的模板参数,请参阅exp2
调用程序)。使用13阶泰勒级数,代码中的注解表明它比使用Pade展开的替代版本更快:两个多项式之比。对于吞吐量来说,每多个FMA进行一次除法并不是一个灾难,特别是如果你有很多周围的代码也对每个结果进行一些非除法工作,但是这样做可能会使每个FMA进行太多的除法。
log_d
模板。这确实使用了尾数的5阶多项式的比率。模板参数支持log(x)
与log(x+1)
以避免丢失精度。它只做自然对数(基数为e
),因此您需要将结果缩放1/ln(2)
。