Einzelnen Beitrag anzeigen

Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.012 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#15

AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64

  Alt 20. Jun 2023, 15:12
Zur Eingangsfrage und den um mehr als Faktor 10 unterscheidenden Ergebnissen kann ich nur sagen: da ist ziemlich sicher irgendwo ein Messfehler oder eine nicht vergleichbare Compilerkonfiguration.
Das hat ja Matthias schon beantwortet.
Hat er?
Ja. Vor allem auf M1 Max getestet. Wo hast du getestet?
Auf einem i7-12700 - wenn du auf ner ARM CPU x86(-64) Kompilate testest, dann möchte ich behaupten, dass das durch irgendeine Emulationsschicht läuft und da könnte es durchaus sein, dass die 32bit Executable einen hohen Overhead verursacht.

PlattformLaufzeit: Inc(sum)Laufzeit: sum := sum + 1
32 Bit1.82s (1822103 us)1.69s (1693918 us)
64 Bit294.65ms (294654 us)294.85ms (294857 us)

Verwende ich sum in der Ausgabe (ShowMessage) nicht, sehen die Ergebnisse für 32-Bit so aus:
PlattformLaufzeit: Inc(sum)Laufzeit: sum := sum + 1
32 Bit294.92ms (294925 us)1.68s (1688951 us)
Die Werte für 64-Bit ändern sich nicht.

Alle Messwerte in mehreren Durchläufen verifiziert.
Inc für Int64 ist scheinbar leider etwas unglücklich implementiert unter 32bit und sorgt nicht für denselben Code.

Mit + bekomm ich diese Ergebnisse:

Win32: ca 290ms
Win64: ca 220ms

Außerdem ist es immer gefährlich den Zeitmessungscode und die Ausgabe, welche fast immer strings beinhaltet mit in dieselbe Routine zu packen, wie den Code, den man messen möchte. Das kann u.U. katastrophale (im Sinne der gemessenen Zeit) haben, da der Compiler für strings und andere gemanagte Typen ein implizites try/finally erzeugt und dieses besonders unter 32bit dafür sorgt, dass der Compiler jegliche werte immer über den Stack bezieht anstatt sie in Registern zu behalten.

Zurück zum Inc auf 32bit:

Erzeugt diesen code:

Code:
add dword ptr [ebp-$18],$01
adc dword ptr [ebp-$14],$00
sum := sum + 1; erzeugt diesen:

Code:
mov eax,[ebp-$18]
mov edx,[ebp-$14]
add eax,$01
adc edx,$00
mov [ebp-$18],eax
mov [ebp-$14],edx
"Aber Stevie, das ist doch mehr Code, warum läuft der langsamer?"
Dafür müssen wir uns mal anschauen, wie die Timings dieser Befehle sind und dazu kann man dieses Dokument zurate ziehen.

Genauer gesagt, schauen wir uns add und adc mit den Operanden m,r/i an (das, was Inc erzeugt) - ich nehme dafür die Timings von Icelake auf Seite 349. Wenn wir in die Spalte Latency gehen, sehen wir dort eine für die Performance vernichtende 7. Der Code, welcher für die Addition genutzt wird nutzt add und adc mit den Operanden r,r/i, die eine Latenz von 1 haben. Die zusätzlichen mov Befehle werden hier vermutlich durch die sogenannte "mov elimination" von der CPU entfernt, da sie erkennt, dass man immer nur denselben Wert schreibt und liest (das ist aber unbestätigt und nur eine Vermutung meinerseits, dafür müsste ich den Code genauer profilen).
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (20. Jun 2023 um 16:02 Uhr)
  Mit Zitat antworten Zitat