英特尔主流的更快但不太准确的fsin?

use*_*710 11 c c++ assembly trigonometry intel

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

我习惯用C++编写代码并做一些asm优化,所以任何适合从C++开始,到C语言到asm的管道都适合我.

谢谢.


我现在处于Linux 64位以下,gcc并且clang(甚至强硬的铿锵并没有提供任何与FPU相关的优化AFAIK).

编辑

  • 我已经实现了一个sin功能,它通常是2倍于std::sin甚至sse上.
  • 我的功能永远不会慢fsin,即使很难fsin通常更准确,但考虑到fsin从未超越我的sin实现,我将保留我sin的现在,也是我sin完全可移植的fsin只有x86.
  • 我需要这个用于实时计算,所以我将精确换算速度,我认为我会很好,精度为4-5位小数.
  • 没有基于表的方法,我没有使用它,它搞砸了缓存,使一切变慢,没有基于内存访问或查找表的算法请.

Pas*_*uoq 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));
Run Code Online (Sandbox Code Playgroud)

并且可能根据目标架构的特性进行优化.此外,在链接的博客文章中没有注明,如果您在汇编中实现此功能,请使用该FMADD说明.如果使用C或C++实现,如果使用fmaf()C99标准函数,请确保FMADD生成.模拟版本比乘法和加法要昂贵得多,因为fmaf()它不是完全等同于乘法后加法(所以如此实现它是不正确的).

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

graphpipi

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

如果您只需要[-1 ... 1]定义间隔,则可以通过忽略其余部分使该多项式在该间隔上更准确.再次为此定义间隔运行优化算法会产生:

X*(1 + X*X*(-1.666659904470566774477504230733785739156e-1 + X*X*(8.329797530524482484880881032235130379746e-3 + X*X*( - 1.928379009208489415662312713847811393721e-4)))

绝对错误图:

graph11

如果这对您来说太准确,则可以针对相同的目标优化较低程度的多项式.那么绝对误差会更大,但你会保存乘法或两次.

  • @ user2485710嗯,你的问题是关于罪,所以我回答了罪.无论如何,使用的方法是Remez算法,它提供的内容在我的答案已经提供的链接中非常清楚地解释:http://lolengine.net/blog/2011/12/21/better-function-approximations.如何理解使用它(我没有). (3认同)
  • @ user2485710需要理解的是多项式逼近的原理(否则,您最终会尝试使用形式为aX ^ 2 + bX的多项式来逼近正弦,而您必须在各处调用`abs()`,这是荒谬可笑,例如Xavier Holt回答的“尼克版”。您还需要有关浮点的基本事实,以便将X的系数固定为1是有益的。我使用了LolRemez(可从我已经提供的链接中获得),但是由于上述所有原因,正确使用它很复杂。 (2认同)
  • @ user2485710 1)http://en.wikipedia.org/wiki/Approximation_theory。有关于这本书。我不会给你写书。2)如果您不喜欢它,请不要使用它。Maple等工具中有可用的实现,但是我无权使用这些工具,也没有任何迹象表明它们的实现更干净。您了解此代码未包装在最终产品中,对吗?3)我为您提供了我所使用的所有内容的链接,但是如果您拒绝我曾经对您来说太过“恐怖”的工具,那么我无能为力。 (2认同)
  • “从您的答案中,我无法为此提取任何名称,参考或算法” ** Remez算法**。我给了你名字和一个开源实现的链接。“您正在从其他来源复制和粘贴代码”实际上,我正在为您运行该算法,因为它使用起来很复杂,并且您的问题是关于“更快但精度更低的fsin”。别客气。LolRemez附带了一个教程,http://lolengine.net/wiki/doc/maths/remez,但是您已经将该实现视为“可怕”,并且我不知道有任何其他免费实现或教程。 (2认同)

Xav*_*olt 5

如果你没有接近(我假设你是,如果你想要击败硬件),你应该看看Nick sin在DevMaster上的实现:

http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine

他有两个版本:"快速和草率"方法和"慢速和准确"方法.一对夫妇回复某人估计相对误差分别为12%和0.2%.我自己完成了一个实现,并在我的机器上找到了1/14和1/8硬件时间的运行时间.

希望有所帮助!

PS: 如果你自己这样做,你可以重构缓慢/准确的方法,以避免乘法,并略微改善尼克的版本,但我不记得究竟如何...

  • @ user2485710标题为"快速准确的正弦/余弦".它没有说"近似".可以假设任何返回IEEE 754号码的函数的精度受该格式的限制.当函数产生的结果在实际结果的1 ULP内时,可以认为函数是准确的.这篇文章再次描述的是一个不准确和快速的正弦函数(来自一个从未听过霍纳的计划的人). (2认同)