procedure Array anstelle case

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

procedure Array anstelle case

Beitrag von Mathias »

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 ?
Dateianhänge
procedure_Array.zip
(2.35 KiB) 71-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: procedure Array anstelle case

Beitrag von Jorg3000 »

Hi!
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)
Und sind diese Debug-Einstellungen ausgeschaltet?
- Bereich/Range (Cr)
- Überlauf/Overflow (Co)

chmod222
Beiträge: 14
Registriert: Do 19. Aug 2021, 17:29

Re: procedure Array anstelle case

Beitrag von chmod222 »

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.

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: procedure Array anstelle case

Beitrag von Mathias »

Die meisten Compiler ersetzen (routinemäßig) einen case-block ab einer gewissen Größe durch eine jumptable wie die deinige hier manuell generierte
Das würde einiges erklären.
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. :roll:
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.
Sofern meine Assembler-Künste noch tragbar sind, scheint das hier auch zu passieren (ab -O1), mit einem Array unter dem Label ".Ld1".
Spannende Seite, habe sie gerade in den Favoriten aufgenommen.
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.
Dies habe ich leider auch gesehen, sehr viel Overhead.
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

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: procedure Array anstelle case

Beitrag von Mathias »

Jorg3000 hat geschrieben:
Fr 24. Nov 2023, 17:06
Hi!
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)
Und sind diese Debug-Einstellungen ausgeschaltet?
- Bereich/Range (Cr)
- Überlauf/Overflow (Co)
Habe gerade den Debugger abgestellt, jetzt macht es etwa 2:1 aus.
Und dies trotz der Compilieroptimierung im oberen Post.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten