OpenTK
库以及它们MonoTouch和MonoDroid包含方法LengthFast
,它应该计算向量长度的近似值而不使用Math.Sqrt
(这似乎是被称为慢)。 LengthFast
使用MathHelper.InverseSqrtFast
,这是一种非常有趣的方法,可以快速逼近平方根(参见http://www.opentk.com/files/doc/_math_helper_8cs_source.html的第172和196行)。
我创建了一个小型基准测试,调用两次计算100'000'000
次,矢量长度介于1到100之间。
在Windows 7 / Intel i7-2600 3.40 GHz上,我得到了:
Length
:2947 ms
LengthFast
:4754 ms
在配备MonoTouch的iPad 3上,我得到了:
Length
:51575 ms
LengthFast
:41252 ms
所以,LengthFast
在英特尔CPU上慢得多,在iPad的ARM上稍快一点。
对此有何解释?这是英特尔CPU能够“原生”计算平方根的结果(不使用软件近似值)吗? LengthFast
不应该总是更快,至少是一点点吗?
答案 0 :(得分:3)
所有Math
成员都非常快。不要试图加速.NET数学代码。在ARM处理器上它可能更快,因为ARM处理器上的相同实现需要一些缺少的X86 / X86_64命令,因此代码是不同的。
答案 1 :(得分:1)
如果你看一下LengthFast
的来源,它与Quake 3中的那个基本相同。
该算法针对x86指令进行了优化,而不是针对ARM指令。据记载,这种算法在ARM上实际上要慢得多:
http://omcfadde.blogspot.com/2011/02/math-function-micro-optimization.html
显然可以看出,这种微优化对x86和x86_64来说非常出色。不要在ARM上试试;它比仅仅采用1.0 / sqrt(x)
的命中要慢得多
修改强>
原来我把它向后看了......可能是JIT弄乱了你的时间。在进入定时循环之前尝试调用Length
和LengthFast
一次,以确保两个方法和MathHelper
类都被初始化和JITted。它不应该产生那么大的差异,但它是一个起点。 MonoTouch没有JIT,所以它仍然是一个因素。