atan2和sqrt哪个更高效?

9
有些情况下,有多种方法可以计算相同的值。
我正在设计一个“扩展”2D凸多边形的算法。为了做到这一点,我想找出每个顶点向哪个方向偏移。为了产生一个在四周都有相同厚度“皮肤”的扩展多边形,向该方向偏移的量也取决于该顶点的角度。但现在我只关心方向。
一种方法是使用atan2:让B是我的顶点,A是前一个顶点,C是下一个顶点。我的方向是angle(B-A)angle(B-C)的“角平均数”。
另一种方法涉及sqrt:unit(B-A)+unit(B-C)其中unit(X)X/length(X)得到一个具有我的方向的向量。
我倾向于第二种方法,因为平均角度值需要一些工作。但我基本上是在两个调用atan2和两个调用sqrt之间做选择。哪个通常更快?如果我在着色器程序中执行此操作呢?
我并不试图对我的程序进行优化,我想知道这些函数一般是如何实现的(例如在标准c库中),以便我能够知道什么是更好的选择。
据我所知,sqrt和三角函数需要迭代方法才能得出答案。这就是为什么我们尽可能避免它们的原因。人们已经提出了“近似”函数,使用查找表和插值等方法尝试产生更快的结果。当然,除非我发现我的代码由于仅使用这些例程或重度涉及它们的例程而导致瓶颈,否则我永远不会费心去处理它们,但sqrt、三角函数和反三角函数之间的差异可能与讨论相关。

2
最好的答案是让你自己尝试并进行比较。 - madth3
如果您所说的“扩展”是指“缩放”,那么只需将每个向量乘以一个常数即可。 - BlueRaja - Danny Pflughoeft
那将是很方便的,如果表示允许这样做,例如如果我知道多边形的质心。由于计算质心只涉及叉积,你可能在这方面有所发现! - Steven Lu
不幸的是,简单的缩放并不能实现您所期望的皮肤厚度均匀增加。考虑一个高度为1单位、长度为100单位的矩形:仅仅将顶点按+10%缩放会导致上下边缘厚度为0.1单位的皮肤,但左右边缘却有10单位的厚度。 - ryanm
3个回答

27

在常见的现代硬件上,使用一般的库来计算平方根(sqrt)比计算反正切(atan2)更快。虽然存在atan2更快的情况,但这种情况很少。

最近的x86实现实际上具有相当高效的sqrt指令,在这种硬件上,差异可能非常明显。英特尔优化手册引用单精度平方根为Sandybridge的14个周期,双精度平方根为22个周期。通过良好的数学库,atan2的计时通常在100个周期左右或更多。


2
这就是我正在寻找的信息!谢谢。 - Steven Lu

2

听起来你已经拥有了所有的信息,可以进行分析并自行找出答案。

如果你不需要精确的结果,并且不介意增加额外的逻辑来使其工作,你可以使用专门的操作,例如RSQRTSSRSQRTPS,它们可以计算1/sqrt,从而将这两个昂贵的操作结合在一起。


你知道最近版本的 gcc 是否可以将代码优化为使用这些指令吗? - Steven Lu
@StevenLu:是的,可以看一下 -mrecip 选项。 - janneb
1
而且,作为一个警告,倒数近似指令并不是用来直接使用的,而是作为牛顿-拉普森迭代的第一步。 - janneb
@StevenLu:是的,我应该询问更多关于你正在做什么的细节,我会更新答案以反映这一点。 - Guvante

0

实际上,sqrt比atan2更好,1 / sqrt比sqrt更好。

对于非内置解决方案,您可能会对 CORDIC逼近感兴趣。

但在您的情况下,在得出任何结论之前,您应该开发完整的公式并全局优化它们,因为超越函数只是计算的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接