由于用于计算x86下fsin
函数的函数sin(x)
可以追溯到Pentium时代,显然它甚至没有使用SSE寄存器,我想知道是否有更新的更好的计算三角函数的指令集。
我习惯用C ++编写代码并进行一些asm
优化,所以任何适合从C ++开始,到C语言到asm的管道都适合我。
感谢。
我目前使用的是64位,gcc
和clang
(即使是强硬的clang也没有提供任何与FPU相关的优化AFAIK)。
修改
sin
功能,即使std::sin
开启,它通常比sse
快2倍。fsin
,即使很难fsin
通常更准确,但考虑到fsin
永远不会超过sin
实施,我会保留我的sin
目前,我的sin
也完全可移植,而fsin
仅适用于x86。答案 0 :(得分:11)
如果需要近似正弦优化绝对精度超过-π...π,请使用:
x *(1 + x * x *( - 0.1661251158026961831813227851437597220432 + x * x *(8.03943560729777481878247432892823524338e-3 + x * x * -1.4941402004593877749503989396238510717e-4))
可以通过以下方式实现:
float xx = x * x;
float s = x + (x * xx) * (-0.16612511580269618f + xx * (8.0394356072977748e-3f + xx * -1.49414020045938777495e-4f));
也许optimized depending on the characteristics of your target architecture。此外,在链接的博客文章中没有注明,如果您在汇编中实现此功能,请使用FMADD
指令。如果使用C或C ++实现,如果使用fmaf()
C99标准函数,请确保生成FMADD
。模拟版本比乘法和加法要昂贵得多,因为fmaf()
所做的并不完全等同于乘法后跟加法(因此实现它就不正确)。
sin(x)与-π和π之间的上述多项式之间的差异如此:
多项式是优化的,以减少它与-π和π之间的sin(x)之间的差异,而不仅仅是某人认为是个好主意的东西。
如果您只需要[-1 ... 1]定义间隔,那么可以通过忽略其余部分使该多项式在该间隔上更准确。再次为此定义间隔运行the optimization algorithm会产生:
x *(1 + x * x *( - 1.666659904470566774477504230733785739156e-1 + x * x *(8.329797530524482484880881032235130379746e-3 + x * x *( - 1.928379009208489415662312713847811393721e-4)))
绝对错误图:
如果这对你来说太准确了,可以optimize a polynomial of lower degree for the same objective。那么绝对误差会更大,但你会保存乘法或两次。
答案 1 :(得分:5)
如果你没有接近(我假设你是,如果你想要击败硬件),你应该看看Nick在DevMaster上的sin
实现:
http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine
他有两个版本:“快速和邋”“方法”和“慢速和准确”方法。一对夫妇回复某人估计相对误差分别为12%和0.2%。我自己完成了一个实现,并在我的机器上找到了1/14和1/8硬件时间的运行时间。
希望有所帮助!
PS:如果你自己这样做,你可以重构缓慢/准确的方法,以避免乘法,并略微改善尼克的版本,但我不记得究竟如何...