C++ 针对英特尔asm的更快但更不准确的fsin?

C++ 针对英特尔asm的更快但更不准确的fsin?,c++,c,assembly,intel,trigonometry,C++,C,Assembly,Intel,Trigonometry,由于x86下用于计算sin(x)函数的函数fsin可以追溯到奔腾时代,而且显然它甚至没有使用SSE寄存器,我想知道是否有更新更好的指令集用于计算三角函数 我习惯于用C++编写代码,做一些 ASM优化,所以适合于从C++开始到C到ASM的任何一个流水线都适合我。 谢谢 我现在使用的是64位Linux,使用的是gcc和clang(即使是强硬的clang也不能真正提供任何与FPU相关的优化AFAIK) 编辑 我已经实现了一个sin函数,它通常比std::sin快2倍,即使启用了sse 我的函数从来

由于x86下用于计算sin(x)函数的函数
fsin
可以追溯到奔腾时代,而且显然它甚至没有使用SSE寄存器,我想知道是否有更新更好的指令集用于计算三角函数

<>我习惯于用C++编写代码,做一些<代码> ASM<代码>优化,所以适合于从C++开始到C到ASM的任何一个流水线都适合我。 谢谢


我现在使用的是64位Linux,使用的是
gcc
clang
(即使是强硬的clang也不能真正提供任何与FPU相关的优化AFAIK)

编辑

  • 我已经实现了一个
    sin
    函数,它通常比
    std::sin
    快2倍,即使启用了
    sse
  • 我的函数从来没有比
    fsin
    慢过,即使是艰难的
    fsin
    通常也更准确,但是考虑到
    fsin
    从来没有超过我的
    sin
    实现,我现在将保留我的
    sin
    ,而且我的
    sin
    是完全可移植的,因为
    fsin
    仅适用于x86
  • 我需要这个来进行实时计算,所以我会用精度来换取速度,我想我的精度可以达到4-5个小数点
  • 不,对于基于表的方法,我没有使用它,它会破坏缓存,使一切变慢,请不要使用基于内存访问或查找表的算法

如果您对近似值满意(我假设您满意,如果您试图击败硬件),您应该看看Nick在DevMaster的
sin
实现:

他有两个版本:一个是“快而草率”的方法,另一个是“慢而准确”的方法。一对夫妇回答说,有人估计相对误差分别为12%和0.2%。我自己做了一个实现,在我的机器上发现运行时间是硬件时间的1/14和1/8

希望有帮助


PS:如果您自己这样做,您可以重构慢速/精确的方法,以避免乘法,并比Nick的版本稍有改进,但我不记得具体如何…

如果您需要一个正弦近似值,该近似值优化为绝对精度超过-π…π,请使用:

x*(1+x*x*(-0.1661251158026961831813227851437514375977220432+x*x*(8.039435607297774818782474328923524338E-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));
在链接的博客帖子中没有注意到,如果你在汇编中实现这个,使用<代码> fMADAD< /Cuff>指令。如果在C或C++中实现,如果你使用,例如,<代码> fMAF-()C99标准函数,请确保生成了
FMADD
。仿真版本比乘法和加法昂贵得多,因为
fmaf()
所做的并不完全等同于先乘法后加法(因此仅实现它是不正确的)

sin(x)和上述多项式在-π图和π图之间的差异如下:

多项式被优化以减少它与sin(x)之间的差异,sin(x)介于-π和π之间,而不仅仅是有人认为是个好主意

如果您只需要[-1…1]定义区间,则可以通过忽略其余区间使多项式在该区间上更精确。再次运行此定义区间将产生:

x*(1+x*x*(-1.6666599044705667744775042307337785739156E-1+x*x*(8.3297975305244824880881032235130379746E-3+x*x*(-1.928379009208489415662312713847811393721e-4)))

绝对误差图:


如果这对你来说太准确了,那么绝对误差可能会更大,但你可以保存一两次乘法。

这可能会被证明是有用的:你能更具体地说明为什么你认为SSE2对你的情况没有帮助吗?那么你的情况是什么?你能在你的问题中详细说明吗?根据我在那篇论文中的理解:他们表达了余弦作为基本算术运算的函数,因此可以使用SSE对其进行矢量化,从而允许您同时计算4个余弦。@user2485710您需要在问题中说明这些目标:希望以更高的精度获得更快的速度,否则没有人能帮到您…@OliCharlesworth我喜欢您的PRNG方法,但我不喜欢我认为它会精确到要求的4-5位小数。好吧,这是一个很长的阅读,我正在阅读它,但现在我认为我需要一些时间来处理它和相关的选项。但看起来这些人或多或少是游戏开发者,他们对此非常满意。“你可以重构慢/准确的方法,以避免乘法,并比Nick的版本稍有改进”当Horner form是对多项式求值方案的改进时,你应该避免对所谓的“快速和准确”实现提出大胆的主张。这篇博文的标题应该是“快速和不准确的正弦”,因为这两个版本都是如此。@user2485710标题是“快速准确的正弦/余弦”,而不是“近似值”。任何返回IEEE 754数字的函数都可以假定其精度受到该格式的限制。当函数生成的结果与实际结果相差1 ULP以内时,可以认为该函数是准确的。文章再次描述的是一个不准确且快速的正弦函数(来自从未听过f Horner方案的人)@user2485710用你需要的定义间隔来补充你的问题,我将向你展示一个绝对准确度可能比你已经编写的函数更好的函数(我假设你对绝对准确度感兴趣。你也应该说得更清楚)@user2485710-Pascal说帖子应该有这个词标题中的“近似值”,因为该方法在典型浮点意义下不准确。