1

我一直在对慢速代码区域进行一些 eprofile 测试。这适用于 Visual Studio 2008 和 .NET 2(已完全修补)。Haversine 公式使用了大约 32% 的计算。这需要两个正弦、两个余弦、一个平方根和一个反正弦 - 所有这些都使用标准的 .NET 数学库(即 Math.Sin、Math.Asin、Math.Sqrt)。我已经能够轻松地缓存余弦 - 导致 Haversine 函数的加速大约 25-30%。

在配置文件中,我看到 __CIasin_pentium4 和 __CIasin 除了人们发布的堆栈转储之类的内容外,它们在 Google 上都找不到太多内容。pentium4 变体抓取的样本数量大约是原来的两倍(包括和不包括在内)。我假设这是一个反正弦,但它真的比正弦贵得多吗?即使将计算两倍的数量,轮廓中也没有正弦的迹象。

这两个函数都是反正弦,还是一个是正弦?如果不是,它们代表什么?

是的,我在 Internet 和此处看到了有关快速正弦波的各种文章和帖子。我确实需要计算正弦的准确性,而不是查找表或截断的泰勒级数。我正在使用 Haversine 来计算和/或比较地球表面的距离。10m 精度(我的应用程序的最小恕我直言)相当于大约 1/640000 弧度。

一种关于速度的想法是多重化三角恒等式。虽然这会导致更多的三角函数,但它们将变得仅依赖于单个端点,因此变得可缓存。另一个是展开反正弦和平方根以进行比较。我认为后者有很大的改进空间,但是目前我正在尝试了解处理时间的原因以及 __CIasin 函数所代表的确切含义。

4

2 回答 2

1

看起来 Pentium FPU 有正弦和余弦(fsin 和 fcos)的本机指令,但没有反正弦指令。因此,我看到的 __CIasin 函数可能是反正弦的 .NET 实现,我理解它使用泰勒级数。这解释了速度上的巨大差异,因此 asin 出现了,而 sin 没有出现。(或者 cos 或 sqrt ——这些也是本机函数)。

我很久以前就直接对 x86 FPU 进行了编码。很久以前,我认为它一定是 8087 - 无论如何,当时唯一存在的三角是部分切线!

因此,优化的下一个工作是尽可能从半正弦中解开反正弦和平方根。结果用于简单的大于/小于比较(排序等);并与“固定”值进行比较。在这两种情况下,都应该可以打开它们。例如。固定值变为平方(sin(fixed)),并与 sqrt 内部的值进行比较。

我仍然认为 trig 标识可能是一个有用的优化,但它肯定会使代码复杂化并引入错误的可能性。

于 2010-10-21T18:35:22.720 回答
0

是的,绝对解开 sqrt 和反正弦。反三角函数几乎总是比它们的正向函数慢,因为正向三角函数通常在 FPU 中实现。

于 2010-11-08T20:27:08.640 回答