主要问题 有人对x64有快速的sin()实现吗? 它不需要是纯粹的pascal. 说明 我有一个VCL应用程序,在某些情况下,当它为x64编译时运行速度慢很多. 它进行了大量的浮点3d计算,并且我已经跟踪
有人对x64有快速的sin()实现吗?
它不需要是纯粹的pascal.
说明
我有一个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
你在这里看到的是罪(1E5)的速度是罪的1倍(1E8).
如果您有兴趣,我已经创建了上面这样的表格:
{$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(闪存模块(X,2 * PI)).它提供了正确的结果,并且对于更大的数字它可以快速运行.对于较小的数字,它当然有点慢.
function SinX87(x:double):double; var d : double; asm movsd qword ptr [rbp+8], xmm0 fld qword ptr [rbp+8] fsin fstp qword ptr [rbp+8] movsd xmm0, qword ptr [rbp+8] end;
这会增加一些开销,因为您必须将SSE寄存器中的值弹出到堆栈中,将其加载到x87单元中,执行计算,将值弹回到堆栈,然后将其加载回XMM0以获取功能结果.然而,罪恶计算相当沉重,所以这是一个相对较小的开销.如果你需要保留x87的xxx实现,我真的会这样做.
存在其他库,在x64代码中比Delphi的purepascal例程更有效地计算sin.我压倒性的偏好是将一组好的C例程导出到DLL中.此外,正如大卫所说,无论如何,使用具有可笑大量参数的trig函数并不是一件明智的事情.