![]() |
Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
das ist bestimmt eine Anfänger Frage und eventuell den meisten Leuten klar weshalb folgendes, das ich gleich beschreibe so ist wie es ist.
Ich habe gestern ein kleines Tutorial Video von DelphiLernen auf Youtube angeschaut. Und das kleine Programm nachgebaut.
Code:
Nichts großartiges.
procedure TForm1.Button1Click(Sender: TObject);
var i: integer; sum: Int64; StartTime, EndTime, ElapsedTime: Int64; begin StartTime := MilliSecondOfTheDay(Now); sum := 0; for i := 1 to 1000000000 do sum := sum + 1; EndTime := MilliSecondOfTheDay(Now); ElapsedTime := EndTime - StartTime; ShowMessage('Summe: ' + IntToStr(sum) + ' / Zeit: ' + IntToStr(ElapsedTime) + ' ms'); end; Ich habe es für alle mir verfügbaren Plattformen kompiliert. Win32 = 6063ms Win64 = 390ms macOS ARM 64 Bit = 1296 ms macos 64 Bit ( mit rosetta) = 316 ms in C für Arm mit gcc -O3 2 ms Swift 41 ms Sekunden C# 362 ms Lazarus fpc für intel 421ms fpc für arm 1624 ms Was mich etwas wundert das dies in Windows bei 64 und 32 so ein großer unterschied ist, und das bei macOS die Rosetta Variante auch sehr viel schneller ist als die (Native Arm) Version. Selbe Bild beim FPC. Gut C ist halt einfach schnell, dachte allerdings aus Erzählungen das Delphi nicht arg weit dahinter ist. Was mir stark gewundert hat das Swift die Schleife so schnell durchläuft und auch das C# das Schneller durchläuft unter Macos als die Delphi variante. Den Hacken Optimierungen habe ich angekreuzt in Delphi. Eventuell gibt es da noch etwas das man machen könnte. Mich interessiert einfach woher diese unterschiede kommen. Vielleicht kann mich da jemand kurz aufklären. Danke :) |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
* wie optimal erzeugt der Compiler den Code
* wie schnell sind die einzelnen verwendeten CPU-Befehle * was bietet die jeweilige Platform eigentlich für Befehle * wie gut läuft der Speicherzugriff * und wie gut die Abarbeitung dieses Codes Win32 muß langsamer sein, denn bei 64 Bit rechnet die CPU, mit einem "Assembler"-Befehl, während es unter 32 Bit eine Funktion macht, also viele Assembler-Befehle. [edit] Nee, beim ADD wird es direkt gemacht, aber auch mit mehreren Befehlen, denn die 32 Bit-CPU kann ja nur mit 32 Bit rechnen. MUL, DIV, MOD waren aber Funktionen. (z.B. siehe __llmul in der System.pas)
Delphi-Quellcode:
Und wenn man jetzt noch die Überlauf- und Bereichsprüfung wieder deaktiviert, welche nun seit Kurzem standardmäßig aktiv sind. :wall:
// Win32
mov eax,[ebp-$10] mov edx,[ebp-$0c] add eax,$7b adc edx,$00 jno $006663d9 call $00498228 mov [ebp-$10],eax mov [ebp-$0c],edx // Win64 add qword ptr [rbp+$28],$7b jno TForm4.FormCreate + $20 call @IntOver
Delphi-Quellcode:
mov eax,[ebp-$10]
mov edx,[ebp-$0c] add eax,$7b adc edx,$00 mov [ebp-$10],eax mov [ebp-$0c],edx versus add qword ptr [rbp+$08],$7b PS, bezüglich der Optimierung. Bei gewissen Rechenoperationen kann es "anders" einfacher gehn. z.B. aus einem
Delphi-Quellcode:
kann oft einfach ein
i * 2
Delphi-Quellcode:
werden.
i shl 1
Und ein "einfacher" Bit-Shift geht auch mit weniger CPU-Takten, als ein "aufwendiges" mathematisches Rechnen. |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Danke für die schöne Erklärung!
6 zu 1 mehr Arbeit in der 32 Bit Version, hätte ich nicht gedacht. :) |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Das hängt aber auch sehr vom konkreten System ab. Bei mir (i5-8600k) braucht Win32 ca. 1400 Millisekunden und Win64 ca. 1600 bzw. im Release 1300 vs. 400. Da ist der Unterschied geringer. Generell ist die Optimierung beim 64-Bit Compiler oft besser.
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Code:
jetzt nur noch ca. 50 ms für win32
var
counter: integer; startTime, endTime: TDateTime; timeTaken: Double; begin counter := 1; startTime := Now; // Startzeit aufzeichnen asm mov ecx, counter @loop_start: inc ecx cmp ecx, 100000000 jle @loop_start mov counter, ecx end; endTime := Now; timeTaken := MilliSecondSpan(startTime, endTime); ShowMessage(FloatToStr(timeTaken) + ' ms'); end;
Code:
Ich habe jetzt mal den inc versucht. ist egal ob auf mac oder win immer bei ca. 30-60 ms. procedure TForm1.Button1Click(Sender: TObject); var counter:integer; startTime, endTime: TDateTime; timeTaken: Double; begin counter := 0; startTime := Now; // Startzeit aufzeichnen while counter <= 100000000 do inc(counter); endTime := Now; // Endzeit aufzeichnen timeTaken := MilliSecondSpan(startTime, endTime); // Berechnung der benötigten Zeit in Millisekunden ShowMessage(FloatToStr(timeTaken) + ' ms'); // Zeigt die benötigte Zeit in Millisekunden an end; d.h. für mich falls ich etwas Inkrementieren muss sollte ich "inc" verwenden anstelle "x := x+1;" ich find das echt Interresant :) Dachte für mich immer... das ist doch das gleiche... |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Deine neuen Quelltexte machen aber auch etwas anderes. Anfangs hattest du eine Schleife mit der Änderung der Schleifenvariable und zusätzlich das Inkrementieren eines Wertes. Jetzt hast du nur noch die Schleife. Dass das schneller ist, ist klar.
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
int64 ist auf Win32 ist "teuer"
Das ursprüngliche
Code:
auf
var
i: int64;
Code:
bringt für Win32 schon etliches (6044 -> 736ms)
var
i: integer; |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
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. |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Der Overhead von Int64 unter 32bit ist messbar aber keineswegs auch nur annäherend in Bereich x10 Zitat:
Der Messwert bei swift sieht auch aus, als ob da etwas ähnliches passiert. |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Delphi 11.3 Alexandria, Build Release (Standardeinstellungen), Prozessor Intel(R) Core(TM) i5 3.20GHz
Delphi-Quellcode:
uses
mormot.core.base, mormot.core.perf; const RUN_COUNT = 1000000000; var timer: TPrecisionTimer; begin timer.Start; var sum: Int64 := 0; for var i: Integer := 1 to RUN_COUNT do // sum := sum + 1; Inc(sum); ShowMessage(Format('Laufzeit: %s (%d us), Summe: %d', [timer.Stop, timer.StopInMicroSec, sum]));
Verwende ich sum in der Ausgabe (ShowMessage) nicht, sehen die Ergebnisse für 32-Bit so aus:
Alle Messwerte in mehreren Durchläufen verifiziert. Bis bald... Thomas |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Zitat:
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
Delphi-Quellcode:
erzeugt diesen:
sum := sum + 1;
Code:
"Aber Stevie, das ist doch mehr Code, warum läuft der langsamer?"
mov eax,[ebp-$18]
mov edx,[ebp-$14] add eax,$01 adc edx,$00 mov [ebp-$18],eax mov [ebp-$14],edx Dafür müssen wir uns mal anschauen, wie die Timings dieser Befehle sind und dazu kann man ![]() 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). |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Ja. Sicherlich.
Aber darum geht/ging es doch (siehe Betreff) |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Wäre es denkbar dass solche krassen Unterschiede x10 auch durch Intel vs.AMD kommen könnten?
Hier wird wohl Intel favorisiert, aber ich vermute AMD liegt da gleichauf. Oder ist das eine falsche Annahme ? |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Sicher das der Compiler das
Delphi-Quellcode:
nicht einfach wegoptimiert?
Inc(Sum)
Ein schlauer Compiler könnte sogar die Schleife wegoptimieren
Delphi-Quellcode:
.
Inc(Sum, RUN_COUNT)
Wichtig ist sicher, ob der erzeugte Code für die Schleife vollständig in die Befehlswarteschlange des Prozessorkerns passt und die Sprungvorhersage richtig liegt. |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Solang nicht detailiertere Information vorliegen vermute ich entweder die Virtualisierungs-/Emulationssschicht oder das Benutzen von Inc anstatt +1 als Ursache. In dem zuvor verlinkten Dokument stehen auch die Instructiontimings von AMD einschließlich Zen 4. Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
![]() |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
Windows 11/ARM in Parallels VM auf M1 Max (original Code, Post#1) Win32/Release Int64: 5987 ms Integer: 712 ms -> Faktor 8 Windows 11 auf Intel NUC Intel i7-1360p (original Code, Post#1) Win32/Release Int64: 270 ms Integer: 205 ms -> Faktor 1,3 Also Int64 in einer Windows11-VM auf ARM -> "Langsam" |
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Zitat:
|
AW: Geschwindigkeitsunterschiede Apple Sillicon / Intel Win32 / Win64
Apple hat für seinen ARM etwas eingebaut (Name vergessen),
was eine x86 CPU (vermutlich x64) emuliert. Könnte man entfernt mit Wine (Windows-Anwendung im Linux), bzw. eher mit 16 und 32 Bit in einer mit 64 Bit-CPU, sowie 16 Bit in einer mit 32 Bit-CPU. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:13 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz