Haupt FrageFaster sin() für x64
Hat jemand eine schnelle Sünde für x64() Implementierung haben? Es muss nicht pures Pascal sein.
Erklärung
ich eine VCL-Anwendung haben, die viel langsamer in einigen Situationen läuft, wenn es für x64 kompiliert.
Es führt viele Gleitkomma-3D-Berechnungen durch, und ich habe dies auf die Tatsache zurückgeführt, dass System.Sin() und System.Cos() auf x64 viel langsamer sind, wenn die Eingabewerte groß werden.
Ich timed es habe durch eine einfache Test-Anwendung erstellen, die messen, wie lange es sin(x)
, mit unterschiedlichen Werten für x zu berechnen nimmt, und die Unterschiede sind riesig:
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
Was Sie hier sehen, ist, dass sin(1E5)
läuft etwa 300 mal so schnell wie sin(1E8)
.
Falls Sie interessiert sind, habe ich die obige Tabelle wie folgt erstellt haben:
{$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.
Hinweise:
Es gibt einige Fragen auf Stackoverflow bezüglich schneller Sinusfunktionen, aber keine von ihnen haben Quellcode, der nützlich ist, um zu Delphi zu portieren, wie dieser: Fastest implementation of sine, cosine and square root in C++ (doesn't need to be much accurate)
Der Rest des x64 läuft schneller als es ist 32bits cou nterpart
Ich habe ein bisschen beschissene Abhilfe gefunden, indem Sie dies tun:
Sin(FMod(x,2*pi))
. Es liefert die korrekten Ergebnisse und es läuft schnell für größere Zahlen. Bei kleineren Nummern ist es natürlich etwas langsamer.
Vermutlich kümmert es Sie nicht um die Genauigkeit, oder Sie würden nicht trig Funktionen mit so großen Werten aufrufen. Sicherlich schätzen Sie, dass eine Abrundung bedeutet, dass trigonale Funktionen für solche Eingabewerte bedeutungslos sind? Oder ist Genauigkeit für Sie nicht wichtig? –
Also, sehen Sie, wenn Sie die Ausgabe dieses Programms erraten können: '{$ APPTYPE CONSOLE} var s1, s2: Single; beginnen s1: = 10000000.5; s2: = 10000000.0; Writeln (s1 = s2); Ende. 'Hier ist ein Hinweis. Die Ausgabe ist nicht "FALSE". –
Es scheint, dass MSVC es schneller machen kann, und ich wäre daran interessiert zu wissen, wie, denn ich wette, es macht es schneller für Eingabewerte, die auch sinnvoll sind. Aber für Ihre großen Eingabewerte verschwenden Sie Ihre Zeit mit dem Aufruf dieser Trigger-Funktionen, wie mein vorheriger Kommentar zeigt. –