【发布时间】:2016-04-04 20:14:27
【问题描述】:
主要问题
有人有针对 x64 的快速sin() 实现吗?
它不需要是纯帕斯卡。
说明
我有一个 VCL 应用程序,当它为 x64 编译时,在某些情况下运行速度会慢很多。
它进行了大量的浮点 3d 计算,我发现这是因为当输入值变大时,System.Sin() 和 System.Cos() 在 x64 上会慢很多。
我通过创建一个简单的测试应用程序来计时,该应用程序测量计算 sin(x) 所需的时间,x 值不同,差异很大:
call: x64: x86:
Sin(1) 16 ms 20 ms
Sin(10) 30 ms 20 ms
Sin(100) 32 ms 20 ms
Sin(1000) 34 ms 21 ms
Sin(10000) 30 ms 21 ms
Sin(100000) 30 ms 16 ms
Sin(1000000) 35 ms 20 ms
Sin(10000000) 581 ms 20 ms
Sin(100000000) 1026 ms 21 ms
Sin(1000000000) 1187 ms 22 ms
Sin(10000000000) 1320 ms 21 ms
Sin(100000000000) 1456 ms 20 ms
Sin(1000000000000) 1581 ms 17 ms
Sin(10000000000000) 1717 ms 22 ms
Sin(100000000000000) 1846 ms 23 ms
Sin(1E15) 1981 ms 21 ms
Sin(1E16) 2100 ms 21 ms
Sin(1E17) 2240 ms 22 ms
Sin(1E18) 2372 ms 18 ms
etc etc etc
您在这里看到的是 sin(1E5) 的运行速度大约是 sin(1E8) 的 300 倍。
如果您有兴趣,我已经创建了上面的表格,如下所示:
{$APPTYPE CONSOLE}
program SinTest;
uses Diagnostics, Math, SysUtils;
var
i : Integer;
x : double;
sw: TStopwatch;
begin
x := 1;
while X < 1E18 do
begin
sw := TStopwatch.StartNew;
for i := 1 to 500000 do
System.Sin(x);
// WriteLn(System.sin(x), #9,System.Sin(fmod(x,2*pi)));
sw.Stop;
WriteLn(' ', ('Sin(' + round(x).ToString + ')'):20, ' ', sw.ElapsedMilliseconds,' ms');
x := x * 10;
end;
WriteLn('Press any key to continue');
readln;
end.
注意事项:
在 StackOverflow 上有一些关于更快的正弦函数的问题,但它们都没有可用于移植到 Delphi 的源代码,例如:Fastest implementation of sine, cosine and square root in C++ (doesn't need to be much accurate)
x64 的其余部分比 32 位对应的运行速度更快
通过执行以下操作,我发现了一些糟糕的解决方法:
Sin(FMod(x,2*pi))。它提供了正确的结果,并且对于较大的数字运行得很快。当然,对于较小的数字,它会慢一些。
【问题讨论】:
-
大概您不关心准确性,或者您不会调用具有如此大值的三角函数。您肯定明白舍入意味着三角函数对于此类输入值毫无意义吗?还是准确性对您来说并不重要?
-
那么,看看你能不能猜出这个程序的输出:
{$APPTYPE CONSOLE} var s1, s2: Single; begin s1 := 10000000.5; s2 := 10000000.0; Writeln(s1=s2); end.这里有一个线索。输出不是FALSE。 -
似乎 MSVC 可以更快地做到这一点,我很想知道如何做到这一点,因为我敢打赌它对于合理的输入值也能更快地做到这一点。但是对于您的大输入值,您甚至调用这些三角函数都是在浪费时间,正如我之前的评论所展示的那样。
-
IMO,将
sin(fmod(x, 2 * pi))的代码包装到一个小函数中可能是 about 尽可能好(事实上,这是他们应该开始做的 - - 从时间上看,他们可能通过重复减法实现了fmod,如果它接近正确的范围,这很好,但如果它大大超出范围,则速度很慢并且可能不准确)。 -
不,您使用的是单精度。它在问题中。还是这个问题不是您要问的?
标签: performance delphi 64-bit x86-64 trigonometry