Ich habe ein Experiment gemacht, weil ich dachte, mit einem grossen case-Block, werde recht viel Ressourcen verbraucht.
Daher habe ich versucht, die Proceduren welche im Case-Block waren in eine Array auszulagern.
Weil ich dachte ein direkter Zugriff auf eine Adresse sei einiges schneller als wen zig Werte in einem Case-Block abgefragt werden müssen.
Da habe ich mich wohl getäuscht, das Beispiel im Anhang ist nur etwa 1/3 schneller. Und dies auch nur, wen ich die Compiler-Optimierung mit {O-} ausschalte.
Mache ich da einen Überlegungsfehler, das dies nicht mehr beschleunigt wird ?
Oder wird sonst wo viel Leistung verbraten, das dies nicht mehr in Gewicht fällt ?
procedure Array anstelle case
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
procedure Array anstelle case
- Dateianhänge
-
procedure_Array.zip
- (2.35 KiB) 88-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
- Jorg3000
- Lazarusforum e. V.
- Beiträge: 359
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: procedure Array anstelle case
Hi!
Ist es etwas schneller, wenn du das Array mit konstanter Länge definierst ...?
Und sind diese Debug-Einstellungen ausgeschaltet?
- Bereich/Range (Cr)
- Überlauf/Overflow (Co)
Ist es etwas schneller, wenn du das Array mit konstanter Länge definierst ...?
Code: Alles auswählen
RotProc: array[0..47] of procedure(i: integer)
- Bereich/Range (Cr)
- Überlauf/Overflow (Co)
Re: procedure Array anstelle case
Die meisten Compiler ersetzen (routinemäßig) einen case-block ab einer gewissen Größe durch eine jumptable wie die deinige hier manuell generierte, gelegentlich auch approximiert mittels binärsuche wenn eine richtige Jumptable nicht sinnvoll generierbar ist. Die Jumptable des Compilers kassiert aber keine Kosten für Funktionssprünge weil die Blöcke einfach inlined sind und keine calls auf (zur compilezeit) unbekannte Funktionspointer.
Sofern meine Assembler-Künste noch tragbar sind, scheint das hier auch zu passieren (ab -O1), mit einem Array unter dem Label ".Ld1".
Nur bei "-O-" geht er wirklich sequenziell jeden case-test ab, testet jeden Wert einzeln und springt gegebenenfalls, in welchem Fall deine manuelle Jumptable deine Nase vorn hat, aber ab -O1 macht der compiler funktionell das gleiche, aber mit mehr Low-Level Wissen und Kontrolle über den Code und kann deshalb noch mehr Laufzeit einsparen.
Wir können auch sehen dass die ganzen RotX Prozeduren trotz "Nop"-Körper doch vergleichsweise viel assembly code generieren mit dem aufsetzen und clearen des stacks und trotz "inline" marker nicht inlined werden, das dürfte tatsächlich etwas mehr ins Gewicht fallen.
Sofern meine Assembler-Künste noch tragbar sind, scheint das hier auch zu passieren (ab -O1), mit einem Array unter dem Label ".Ld1".
Nur bei "-O-" geht er wirklich sequenziell jeden case-test ab, testet jeden Wert einzeln und springt gegebenenfalls, in welchem Fall deine manuelle Jumptable deine Nase vorn hat, aber ab -O1 macht der compiler funktionell das gleiche, aber mit mehr Low-Level Wissen und Kontrolle über den Code und kann deshalb noch mehr Laufzeit einsparen.
Wir können auch sehen dass die ganzen RotX Prozeduren trotz "Nop"-Körper doch vergleichsweise viel assembly code generieren mit dem aufsetzen und clearen des stacks und trotz "inline" marker nicht inlined werden, das dürfte tatsächlich etwas mehr ins Gewicht fallen.
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: procedure Array anstelle case
Das würde einiges erklären.Die meisten Compiler ersetzen (routinemäßig) einen case-block ab einer gewissen Größe durch eine jumptable wie die deinige hier manuell generierte
Ich habe jetzt versucht meinen meinen Code mit -al zu kompilieren. In diesen Assembler sieht man die Jump-Tabelle auch gut.
Auf diese Idee hätte ich gestern auch kommen können.

Was mich verwundert, das er es mit {$O-} auch macht.
Was ich vermute, wen das case lückenlos eine Integer Reihe abarbeiten kann, kann recht optimiert werden.
Bestehen aber Löcher wie bei 0..3, 10..30, 100..300, kann keine Array mehr gebildet werden.
Spannende Seite, habe sie gerade in den Favoriten aufgenommen.Sofern meine Assembler-Künste noch tragbar sind, scheint das hier auch zu passieren (ab -O1), mit einem Array unter dem Label ".Ld1".
Dies habe ich leider auch gesehen, sehr viel Overhead.Wir können auch sehen dass die ganzen RotX Prozeduren trotz "Nop"-Körper doch vergleichsweise viel assembly code generieren mit dem aufsetzen und clearen des stacks und trotz "inline" marker nicht inlined werden, das dürfte tatsächlich etwas mehr ins Gewicht fallen.
So wie ich generell feststellen konnte, ist "inline" (noch) ein rechtes Sorgenkind von FPC. Siehe Thread bei Bugs.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: procedure Array anstelle case
Habe gerade den Debugger abgestellt, jetzt macht es etwa 2:1 aus.Jorg3000 hat geschrieben: Fr 24. Nov 2023, 17:06 Hi!
Ist es etwas schneller, wenn du das Array mit konstanter Länge definierst ...?
Und sind diese Debug-Einstellungen ausgeschaltet?Code: Alles auswählen
RotProc: array[0..47] of procedure(i: integer)
- Bereich/Range (Cr)
- Überlauf/Overflow (Co)
Und dies trotz der Compilieroptimierung im oberen Post.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot