"...optimierter Code" ?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
7x7
Beiträge: 591
Registriert: 14.08.2007 15:41
Computerausstattung: ganz toll
Wohnort: Lelbach

"...optimierter Code" ?

Beitrag von 7x7 »

Ich arbeite gerade an einem sehr rechenintensiven Programm (eigentlich sind meine Programme IMMER sehr rechenintensiv :mrgreen: )
Dabei kommt es mir wirklich auf jede microsekunde an. Jetzt habe ich mich mal mit dem Assembler-Output des PB-Kompilats beschäftigt.

Ich bin wahrlich kein Assembler-Profi; aber über das, was ich da teilweise so gesehen habe, kann ich nur den Kopf schütteln!

z.B:

Code: Alles auswählen

K4(a1,a2,a3,a4)-1
erzeugt folgenden Assembler-Code:

Code: Alles auswählen

  MOV    edx,dword [a_K4+4]
  IMUL   edx,dword [v_a1]
  MOV    ebp,edx
  MOV    edx,dword [a_K4+8]
  IMUL   edx,dword [v_a2]
  ADD    ebp,edx
  MOV    edx,dword [a_K4+12]
  IMUL   edx,dword [v_a3]
  ADD    ebp,edx
  PUSH   ebp
  MOV    eax,dword [v_a4]
  POP    ebp
  ADD    ebp,eax
  SAL    ebp,2
  ADD    ebp,dword [a_K4]
  MOV    ebx,dword [ebp]
  DEC    ebx
  PUSH   ebx
  MOV    edx,dword [a_K4+4]
  IMUL   edx,dword [v_a1]
  MOV    ebp,edx
  MOV    edx,dword [a_K4+8]
  IMUL   edx,dword [v_a2]
  ADD    ebp,edx
  MOV    edx,dword [a_K4+12]
  IMUL   edx,dword [v_a3]
  ADD    ebp,edx
  PUSH   ebp
  MOV    eax,dword [v_a4]
  POP    ebp
  ADD    ebp,eax
  SAL    ebp,2
  ADD    ebp,dword [a_K4]
  POP    dword [ebp]
Nanu? Wird hier etwa zweimal aufwendig die speicheradresse des Arrays berechnet, obwohl doch schon von vornherein klar ist, wo das Ergebnis hinkommt?

Das könnte ich ja (gerade noch) verstehen, wenn der PB-Code lauten würde:

Code: Alles auswählen

K4(a1,a2,a3,a4) = K4(a1,a2,a3,a4) -1
Deswegen schreibe ich ja in der Kurzform! Aber nein, die Kurzform spart nur Schreibarbeit...optimiert wird dabei nichts!

Der optimale Code würde so aussehen:

Code: Alles auswählen

  MOV    edx,dword [a_K4+4]
  IMUL   edx,dword [v_a1]
  MOV    ebp,edx
  MOV    edx,dword [a_K4+8]
  IMUL   edx,dword [v_a2]
  ADD    ebp,edx
  MOV    edx,dword [a_K4+12]
  IMUL   edx,dword [v_a3]
  ADD    ebp,edx
  PUSH   ebp
  MOV    eax,dword [v_a4]
  POP    ebp
  ADD    ebp,eax
  SAL    ebp,2
  ADD    ebp,dword [a_K4]
  MOV    ebx,dword [ebp]
  DEC    ebx
  PUSH   ebx
  POP    dword [ebp]
Läuft im Ergebnis doppelt so schnell und ist kompakter!

Dann sind mir noch andere Sachen aufgefallen, die nicht so schön gelöst sind (z.B. Jump, der auf einen Jump springt, der auf einen Jump springt, der auf einen Jump springt...furchtbar). Und wer PEEK/Poke benutzt im Glauben, damit Geschwindigkeit zu gewinnen...für den wäre ein Blick in den Assembler-Output sehr abschreckend!
Referenz-Handbuch hat geschrieben:"...der generierte Code produziert ein optimiertes Executable."
So, so....
- alles was ich hier im Forum sage/schreibe ist lediglich meine Meinung und keine Tatsachenbehauptung
- unkommentierter Quellcode = unqualifizierter Müll
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: "...optimierter Code" ?

Beitrag von STARGÅTE »

Wo ist jetzt deine Frage?

A + 1 ist schon immer nur eine schreibliche abkürzung für A = A + 1 gewesen!
Es wird also immer A = A + 1 kompiliert.

Wenn man mit Arrays arbeitet ist es meiner Meinung eigentlich selbst verständlich, dass man selbst das ArrayFeld speichert, wenn man es danach oft benutzt:

Code: Alles auswählen

*Field.Integer = @K4(a1,a2,a3,a4) ; Wenn K4() vom Type Integer ist.
*Field\i + 1
; ...
Zumindest hab ich das schon immer so gemacht, wenn es wirklich auf Zeit ankommt.

Das Peek und Poke nicht so schnell sind wie du denkst ist doch klar, weil sie eine Typenumwandlung enthalten.
Das *Buffer\i = 1 schneller ist als PokeI(*Buffer, 1) wurde schon mehrfach im Forum beschrieben.

Ich meine, sicher kann hier und da optimiert werden, aber auch ein Compiler ist kein Hellseher.
Wer optimierten Code haben will, muss selbst ASM-en

Aber zurück zum Thema: Wie lautet deine Frage?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: "...optimierter Code" ?

Beitrag von NicTheQuick »

STARGÅTE hat geschrieben:Wenn man mit Arrays arbeitet ist es meiner Meinung eigentlich selbst verständlich, dass man selbst das ArrayFeld speichert, wenn man es danach oft benutzt:

Code: Alles auswählen

*Field.Integer = @K4(a1,a2,a3,a4) ; Wenn K4() vom Type Integer ist.
*Field\i + 1
; ...
Zumindest hab ich das schon immer so gemacht, wenn es wirklich auf Zeit ankommt.
Für sowas ist aber ein Kompiler gedacht. Der sollte selbst merken, dass er das optimieren kann.
Mit Pointern kann man immer rumtricksen. Aber in diesem Fall hätte ich schon von PB erwartet, dass es diese Optimierung von selbst erledigt.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Re: "...optimierter Code" ?

Beitrag von Thorium »

PB ist kein optimierender Compiler. Alleine schon weils ein Single Pass Compiler ist, sind viele Optimierungen nicht möglich.

Peek und Poke sind eigentlich nurnoch aus Kompatiblitäsgründen vorhanden und wurden durch Pointer abgelöst.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten