Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern) (https://www.delphipraxis.net/209310-moeglichkeiten-code-zu-optimieren-z-b-laufzeit-verringern.html)

Truther 20. Nov 2021 17:59


Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Moinsen Leute,

ich habe versucht ein Programm mit Lazarus zu schreiben, welches Bilder auf Ähnlichkeit prüft, nur um dann festzustellen, dass mein Programm extrem langsam ist und selbst nach meinen Optimierungsversuchen es nicht wirklich besser wurde, weshalb ich auf eine vorhandene Bibliothek (OpenCV) versuche, zurzückzugreifen.
Mit der Installation habe ich meine Probleme und warte, bis es auf GetIt veröffentlicht wird. Hier geht es zum entsprechenden Thread: https://www.delphipraxis.net/209296-...y-edition.html

Das nur so nebenbei.

Dann stellte ich mir die Frage: Gibt es generelle Möglichkeiten, die Laufzeit von Code zu verbessern/optimieren, ohne ein Informatikstudium absolviert zu haben? Gibt es Literatur oder Videos dazu, die auch ein Laie versteht?

Ich habe zum Beispiel das hier gefunden: Ein Vortrag von Prof. Dr. Nikolaus Wulff mit dem Thema "Systementwicklung" http://www.lab4inf.fh-muenster.de/la...erung-SS12.pdf

Darin geht es überwiegend um die Potenzierungsfunktion und wie man diese optimieren kann.

Ich bin sehr gespannt auf eure Antworten!

Truther

Delphi.Narium 20. Nov 2021 18:46

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Mal ein Beispiel aus meinem Fraktalgenerator:

Zuerst das Original:
Delphi-Quellcode:
FUNCTION Formel101(a        : Extended;
                   b        : Extended;
                   Faktor   : Extended;
                   Iteration : Longint;
                   Art      : Integer ):LongInt;
VAR x,y,z : Extended;
    Farbe : INTEGER;
BEGIN (* Apfelmann mit Spitze nach links *)
  x    := 0;
  y    := 0;
  Farbe := 0;
  REPEAT
    z    := x * x - y + y + 2 * a; // x² - y² + 2a
    y    := 2 * x * y + 3 * b; // 2 * x * y + 3b
    x    := z;
    Farbe := Farbe + 1;
  UNTIL (Farbe = Iteration) OR (x * x + y * y > Faktor);
  Formel101 := GetFarbe(Farbe,x * x,y * y,x * y,Iteration,art);
END;
und dann die schnellere Methode:
Delphi-Quellcode:
FUNCTION Formel101(a        : Extended;
                   b        : Extended;
                   Faktor   : Extended;
                   Iteration : Longint;
                   Art      : Integer ):LongInt;
VAR x,y,z : Extended;
    aa, bb : Extended;
    xx,yy : Extended;
    xy    : Extended;
    Farbe : INTEGER;
BEGIN (* Apfelmann mit Spitze nach links *)
  x    := 0;
  y    := 0;
  Farbe := 0;
  aa   := a + a;
  bb   := b + b + b;
  xx   := 0;
  yy   := 0;
  REPEAT
    z    := xx - yy + aa; // x² - y² + 2a
    xy   := x * y;
    y    := xy + xy + bb; // 2 * x * y + 3b
    x    := z;
    xx   := x * x;
    yy   := y * y;
    Farbe := Farbe + 1;
  UNTIL (Farbe = Iteration) OR (xx + yy > Faktor);
  Formel101 := GetFarbe(Farbe,xx,yy,xy,Iteration,art);
END;
Wenn's um Rechnerei geht, kann man eigentlich recht pauschal sagen:

Alle Berechnungen, deren Ergebnis mehr als einmal benötigt wird, wird nur einmal berechnet und das Ergebnis in einer Variabel gespeichert. Danach wird statt der Berechnung die Variabel genommen.

Der Geschwindigkeitsvorteil kann dann schonmal (je nach Komplexität) um die 25% (wenn man Glück hat aber auch deutlich mehr) betragen.

Bei Grafikbearbeitung ist es hilfreich, für die Zeit der Berechnung alle Bildschirmaktuallisierungen zu deaktivieren. Ggfls. das Programm zu Beginn der Berechnung minimieren und am Ende der Berechnung wieder auf die normale Größe bringen.

Das langsamste bei der Grafikbearbeitung ist halt die Darstellung auf dem Bildschirm.

Gausi 20. Nov 2021 19:48

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Es gibt da generell zwei Ansätze:

Der erste wäre der, einen Algorithmus zu verwenden, der "prinzipiell schneller" ist. Der erste Schritt dazu ist, die sogenannte Komplexität des vorhandenen Algorithmus abzuschätzen. Das ist ein Teil, den man im Theorie-Teil des Informatik-Studiums lernt. Allerdings könnten die Grundlagen dazu auch schon in der Schule gelehrt werden, imho.

Zur Verdeutlichung ein ganz einfaches Beispiel: Du hast eine sortierte Liste mit Zahlen gegeben, und möchtest wissen, an welcher Stelle dieser Liste eine Zahl X steht.
Möglichkeit 1: du schaust dir jedes einzelne Element der Liste an und vergleichst es mit X. Dabei nutzt du die Sortierung der Liste aber nicht aus.
Möglichkeit 2: Du nutzt die Sortierung der Liste: Dazu schaust du dir zuerst das Element in der Mitte der Liste an. Ist das gesuchte X größer, brauchst du die ganze erste Hälfte der Liste nicht mehr zu checken - dort kann es nicht sein. Im anderen Fall kannst du die zweite Hälfte weglassen. Und dann suchst du mit dem gleichen Verfahren nur in dem interessanten Teil weiter.

Der wesentliche Unterschied zwischen den beiden Verfahren ist, dass die Binärsuche konzeptionell schneller ist: Die suche ist nach grob Log(n)-vielen Schritten abgeschlossen (n ist die Anzahl der Elemente in der Liste), bei dem ersten Verfahren benötigt man grob n viele Schritte.

Mit etwas mehr Mathematik liest sich das dann so: https://de.wikipedia.org/wiki/Landau-Symbole, dort findest du auch einige Beispiele zu "effizienten" und nicht ganz so effizienten Algorithmen für einfache klassische Probleme, z.B. für das Sortieren von Zahlen.

Der zweite Ansatz ist, den Algorithmus generell so zu belassen, aber die Ausführungsgeschwindigkeit dadurch zu verbessern, dass man das Verfahren geschickter implementiert.

Bei der Bildverarbeitung ist z.B. ein Klassiker für sehr, sehr langsamen Code die Verwendung von
Delphi-Quellcode:
Bitmap.Canvas.Pixels[]
, um die RGB-Werte eines Pixels im Bild zu bestimmen. Wenn man so einen Code auf
Delphi-Quellcode:
Scanline
umschreibt, wird der Code um ein vielfaches schneller, auch wenn der zugrundeliegende Algorithmus die gleiche asymptotische Zeitkomplexität hat.

Redeemer 20. Nov 2021 20:51

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1497915)
Delphi-Quellcode:
FUNCTION Formel101(a        : Extended;
                   b        : Extended;
                   Faktor   : Extended;
                   Iteration : Longint;
                   Art      : Integer ):LongInt;
VAR x,y,z : Extended;
    aa, bb : Extended;
    xx,yy : Extended;
    xy    : Extended;
    Farbe : INTEGER;
BEGIN (* Apfelmann mit Spitze nach links *)
  x    := 0;
  y    := 0;
  Farbe := 0;
  aa   := a + a;
  bb   := b + b + b;
  xx   := 0;
  yy   := 0;
  REPEAT
    z    := xx - yy + aa; // x² - y² + 2a
    xy   := x * y;
    y    := xy + xy + bb; // 2 * x * y + 3b
    x    := z;
    xx   := x * x;
    yy   := y * y;
    Farbe := Farbe + 1;
  UNTIL (Farbe = Iteration) OR (xx + yy > Faktor);
  Formel101 := GetFarbe(Farbe,xx,yy,xy,Iteration,art);
END;

Kein gutes Beispiel, denn:
  • Delphi-Quellcode:
    Farbe := Farbe + 1;
    schreibt man nicht, man schreibt
    Delphi-Quellcode:
    Inc(Farbe);
    . Macht auch ein bisschen was aus.
  • Bei a + a würde ich vermuten, dass hier eine Multiplikation besser wäre, da im Prinzip der Exponent inkrementiert wird, wenn Compiler/CPU so intelligent sind. Unter Win32 (allerdings sonst nirgendwo) könnte man eventuell auch ein PWord auf @Extended setzen und PWord^ inkrementieren, aber Endianness macht das kompliziert. Wird aber eh nur einmal ausgefühlt.
  • Wenn ich nicht komplett auf dem Schlauch stehe, hat die Variable z überhaupt keine Funktion und man kann man das noch weiter kürzen:
    Delphi-Quellcode:
      REPEAT
        xy   := x * y;
        y    := xy + xy + bb; // 2 * x * y + 3b
        x    := xx - yy + aa; // x² - y² + 2a
        xx   := x * x;
        yy   := y * y;
        Inc(Farbe);
      UNTIL (Farbe = Iteration) OR (xx + yy > Faktor);

Uwe Raabe 20. Nov 2021 21:21

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Redeemer (Beitrag 1497918)
Delphi-Quellcode:
Farbe := Farbe + 1;
schreibt man nicht, man schreibt
Delphi-Quellcode:
Inc(Farbe);
. Macht auch ein bisschen was aus.

Das ist aber wohl eher ein Mythos. So sieht der mit Delphi 11 Win32 ohne Overflow-Checking erzeugte Code aus:
Delphi-Quellcode:
Project861.dpr.8: Farbe := 0;
0040A104 33C0             xor eax,eax
0040A106 A388F54000       mov [$0040f588],eax
Project861.dpr.9: Farbe := Farbe + 1;
0040A10B FF0588F54000     inc dword ptr [$0040f588]
Project861.dpr.10: Inc(Farbe);
0040A111 FF0588F54000     inc dword ptr [$0040f588]
Project861.dpr.11: end.
0040A117 E8B0BBFFFF      call @Halt0

Redeemer 20. Nov 2021 21:56

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1497920)
Zitat:

Zitat von Redeemer (Beitrag 1497918)
Delphi-Quellcode:
Farbe := Farbe + 1;
schreibt man nicht, man schreibt
Delphi-Quellcode:
Inc(Farbe);
. Macht auch ein bisschen was aus.

Das ist aber wohl eher ein Mythos. So sieht der mit Delphi 11 Win32 ohne Overflow-Checking erzeugte Code aus:
Delphi-Quellcode:
Project861.dpr.8: Farbe := 0;
0040A104 33C0             xor eax,eax
0040A106 A388F54000       mov [$0040f588],eax
Project861.dpr.9: Farbe := Farbe + 1;
0040A10B FF0588F54000     inc dword ptr [$0040f588]
Project861.dpr.10: Inc(Farbe);
0040A111 FF0588F54000     inc dword ptr [$0040f588]
Project861.dpr.11: end.
0040A117 E8B0BBFFFF      call @Halt0

Hatte das aus der Doku geschlossen:
Zitat:

Auf manchen Plattformen erzeugt Inc u. U. hochoptimierten Maschinencode, der sich besonders für enge Schleifen eignet.
Ist dann wohl falsch.

Delphi.Narium 20. Nov 2021 22:01

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
@Redeemer

Schön, dass Du es besser weißt.

Aber diese Methode ist durch ausprobieren entstanden und dabei hat sich gezeigt, das bei vielen tausenden Berechnungen a + a schneller als 2 * a ist und das Farbe := Farbe + 1 schneller als Inc(Farbe) ist, auch wenn immer wieder behauptet wird, Inc sei schneller. (Wobei man hier vermutlich deutlich zwischen dem Inc von Pascal und dem Inc im erzeugten Maschinencode unterscheiden muss, bei 'nem intelligenten Compiler dürfte / sollte da der gleiche Maschinencode rauskommen. - siehe Uwes Beispiel ;-))

Und es ist nicht auszuschließen, dass sich identischer Quelltext unter einem anderen Compiler (in Bezug auf die Ausführungsgeschwindigkeit) vollkommen anders verhält, einfach weil anderer Maschinencode daraus kommt.

Die Routine wurde halt nur von Turbo-Pascal 5 bis Delphi 7 in der Form genutzt. Vielleicht gehen neuere Delphicompiler oder Lazarus und FreePascal damit vollkommen anders um.

Sprich: Es kommt nicht darauf an, ob
Delphi-Quellcode:
Farbe := Farbe + 1
schneller als
Delphi-Quellcode:
Inc(Farbe)
ist, sondern darauf, wie der Compiler das letztlich umsetzt. Und dann nimmt man jeweils die schneller Variante ;-) Die wesentliche Zeitersparnis liegt eh in der Reduzierung der Multiplikationen, die fressen die Zeit ;-)

Außerdem war nach Ideen gefragt und nicht nach ultimativ immer richtigen Vorgehensweisen ;-) Derweil: Die gibt es (vermutlich) nicht.

Und ja: Die Berechnung in der Schleife kann man in der Tat noch ein bisserl optimieren.

Uwe Raabe 20. Nov 2021 22:16

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Redeemer (Beitrag 1497921)
Hatte das aus der Doku geschlossen:
Zitat:

Auf manchen Plattformen erzeugt Inc u. U. hochoptimierten Maschinencode, der sich besonders für enge Schleifen eignet.
Ist dann wohl falsch.

Für Win32 offenbar, wobei der Compiler für jede Plattform nur wenig intelligent sein muss, um für
Delphi-Quellcode:
Farbe := Farbe + 1
den gleichen Code wie für
Delphi-Quellcode:
Inc(Farbe)
auszugeben. Andere Plattformen kommen wegen Extended aber auch wohl nicht in Frage.

jbg 21. Nov 2021 01:32

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Redeemer (Beitrag 1497921)
Zitat:

Auf manchen Plattformen erzeugt Inc u. U. hochoptimierten Maschinencode, der sich besonders für enge Schleifen eignet.
Ist dann wohl falsch.

So als historischer Hintergrund: Bis TurboPASCAL 5.5 war Inc() schneller. Seit TurboPASCAL 5.5 hat der Compiler gelernt, dass "A := A + 1" dasselbe wie "Inc(A)" ist. Der Doku-Satz wurde wohl aus älteren Handbüchern übernommen. Selbst der wirklich schlecht optimierende Win64 Delphi Compiler kennt diese Optimierung. Und die "LLVM Backend" Compiler haben damit überhaupt kein Problem.

Gausi 21. Nov 2021 08:16

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Diese Diskussion, wie man den Code so schreibt, dass man noch ein paar Takte sparen kann, ist sicherlich interessant. Aber ich denke, dass die hier nicht zielführend ist.

Wenn ich Truther richtig verstehe, dann hat er keine High-Performance-Situation, wo es wichtig ist, dass man noch die letzten paar Mikro- oder gar Nanosekunden einspart. Ich denke eher, dass sein Programm "spürbar" zu lange dauert. Ob das in dem Fall nun ein paar Sekunden sind, oder evtl. sogar in den Minutenbereich geht, kann ich nicht abschätzen. Da liegt der Flaschenhals mit ziemlicher Sicherheit nicht bei "inc vs. x+1", sondern ganz woanders.

Bei "Bilder auf Ähnlichkeit prüfen" würde ich wie gesagt ganz stark auf "Canvas.Pixels" tippen, oder generell auf ein Verfahren mit kubischer Laufzeit (also 3-fach ineinander geschachtelte Schleife o.ä.), für das es ggf. sinnvollere Alternativen gibt.

Wirklich konkret kann man aber ohne weitere Details zur Aufgabe und dem vorhandenen Code nicht werden. Denn wie in den verlinkten Folien in der Zusammenfassung schön zitiert: "Algorithmen zu optimieren ist eine Kunst".

jaenicke 21. Nov 2021 09:41

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Mich wundert, dass noch kein Profiler angesprochen wurde. Es gibt Tools, die analysieren welcher Teil des Codes wie lange benötigt. Daraus kann man dann ableiten wo man optimieren sollte, wenn möglich.

Die wirklich guten Profiler sind nicht gerade billig, aber dieser hier ist für den Anfang ganz gut:
https://yavfast.github.io/dbg-spider/
Quelltext:
https://github.com/yavfast/dbg-spider

Truther 21. Nov 2021 11:53

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Delphi.Narium
"Alle Berechnungen, deren Ergebnis mehr als einmal benötigt wird, wird nur einmal berechnet und das Ergebnis in einer Variabel gespeichert. Danach wird statt der Berechnung die Variabel genommen."

"Bei Grafikbearbeitung ist es hilfreich, für die Zeit der Berechnung alle Bildschirmaktuallisierungen zu deaktivieren. Ggfls. das Programm zu Beginn der Berechnung minimieren und am Ende der Berechnung wieder auf die normale Größe bringen."

Das sind auf jeden Fall schon mal hilfreiche Sachen. Da würde ich noch
Delphi-Quellcode:
ListBox.Items.BeginUpdate
und
Delphi-Quellcode:
ListBox.Items.EndUpdate
einwerfen, was sich auf das Neuzeichnen von grafischen Komponenten bezieht.

Zitat:

Zitat von Gausi
"Der erste Schritt dazu ist, die sogenannte Komplexität des vorhandenen Algorithmus abzuschätzen."

Man kommt also nicht drum herum, sich mit dieser Thematik genauer zu beschäftigen? Falls nicht, könnte jemand z.B. Bücher dazu empfehlen oder reicht schon eine Suche im Netz?
... Okay, offenbar gibt es gute Videos auf z.B. YouTube, die das gut erklären (siehe unten).

Zitat:

Zitat von Gausi
"Zur Verdeutlichung ein ganz einfaches Beispiel: Du hast eine sortierte Liste mit Zahlen gegeben, und möchtest wissen, an welcher Stelle dieser Liste eine Zahl X steht."

Für mich ist dieses Beispiel zu konkret auf ein Fallbeispiel. Ich hatte da eher an allgemeinere Sachen gedacht, unabhängig davon, welchen Algorithmus man programmiert, wie eben das Beispiel, dass man manche Berechnungen nicht andauernd wiederholt, sondern die Ergebnisse in eine Variable packt und dann auf diese zugreift, sofern diese nur einmal berechnet werden müssen, versteht sich.

Zitat:

Zitat von Gausi
"Der zweite Ansatz ist, den Algorithmus generell so zu belassen, aber die Ausführungsgeschwindigkeit dadurch zu verbessern, dass man das Verfahren geschickter implementiert."

Das klingt für mich eher nach dem, was ich suche. Ich hatte bei meinem Projekt den Aufruf
Delphi-Quellcode:
Image.Colors[X, Y].Red
, womit ich nur auf einen Farbkanal (Rot) eines Pixel zugreife, wenn ich mich nicht irre. Als ich das durch
Delphi-Quellcode:
ScanLine
ersetzt hatte, war es deutlich schneller, auch wenn ich nicht weiß, warum es an sich schneller ist.


Auszug aus einem Wikipedia-Artikel zum Thema "Overhead":

Zitat:

Zitat von Wikipedia
"Overhead wird aber auch ganz allgemein als Zusatzarbeit übersetzt, die z. B. durch Schleifen oft und unnötig durchgeführt werden muss, erst recht, wenn ein Abbruch-Kriterium schon erreicht war."

Sowas z.B. wäre auch etwas Allgemeines, was die Laufzeit optimieren würde.


Zitat:

Zitat von
Algorithmen und Datenstrukturen (YouTube-Kanal)
"Multiplizieren länger dauert als Addieren."

Video mit Zeitstempel (ab ca. Minute 4): https://youtu.be/D8n5qnyFIKc?t=244

Solche Sachen wären auch interessant zu wissen. Aber da es auch mitunter von der Programmiersprache abhängt (Aussage aus dem Video), kann man das nicht so sagen, das Addieren schneller als Multiplizieren ist.
Das wäre dann in etwa gleichzusetzen mit der Problematik oben zu
Delphi-Quellcode:
Inc()
und
Delphi-Quellcode:
i := i + 1
.

Wenn ich asymptotische Laufzeit richtig verstanden habe, bedeutet das, dass man grob sagen kann, wie die Laufzeit wäre (z.B linear oder quadratisch), aber nicht exakt bestimmen kann, wie der exakte Verlauf der Kurve ist, richtig?

Zitat:

Zitat von Gausi
"Wenn man so einen Code auf
Delphi-Quellcode:
Scanline
umschreibt, wird der Code um ein vielfaches schneller, auch wenn der zugrundeliegende Algorithmus die gleiche asymptotische Zeitkomplexität hat."

Also ist es dann eher eine Frage der Implementierung anstatt einer schnelleren asymptotischer Laufzeit?

Zitat:

Zitat von Gausi
"Wenn ich Truther richtig verstehe, dann hat er keine High-Performance-Situation, wo es wichtig ist, dass man noch die letzten paar Mikro- oder gar Nanosekunden einspart. Ich denke eher, dass sein Programm "spürbar" zu lange dauert."

Naja, wenn ich z.B. Millionen von Pixel vergleichen muss, um mal das Beispiel von meinem gescheiterten Bildvergleichsprogramm aufzugreifen, und das von mehreren tausenden Bildern, dann macht das schon was aus.

Zitat:

"Algorithmen zu optimieren ist eine Kunst".
Aber es muss doch Methoden geben, um diese Kunst zu erlernen.

Bei der Speicherreservierung (Allokation) bspw. für dynamische Arrays habe ich gelesen, dass es sinnvoll ist, wenn, sobald man mehr Elemente eines solchen Arrays hinzufügen möchte, die Länge des Arrays jeweils verdoppelt.

Artikel dazu: http://delphiblog.twodesk.com/dynami...ow-to-use-them

Zitat:

Zitat von delphiblog.twodesk.com
"When the time comes to reallocate the array, double its size: SetLength(arr, Length(arr) * 2). Research shows that this strikes the ideal balance between time and space for most cases."


Auch hatte ich mal aufgeschnappt, dass das Arbeiten mit Pointern die Laufzeiten auch verbessern können. Ob das stimmt, weiß ich nicht. Ich wüsste auch nicht, wie da der Zusammenhang wäre.

@jaenicke Das werde ich mir mal ansehen, auch wenn vielleicht nicht für Delphi sondern für Lazarus. Für Lazarus gibt es wohl auch solch Profiler. (https://wiki.freepascal.org/LazProfiler)

dummzeuch 21. Nov 2021 12:21

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Scanline zu verwenden ist schonmal ein guter Ansatz, allerdings ist auch jeder Scanline-Aufruf ziemlich langsam (zumindest in Delphi, keine Ahnung, ob das bei Lazarus auch so ist). Da lohnt es sich, die einzelnen Zeilen selbst per Pointer-Artithmetik zu ermitteln.

himitsu 21. Nov 2021 13:17

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Bei so kleinen Schleifen, die sehr oft schnell durchlaufen werden, funktionieren die Profiler auch nicht unbedingt sehr gut,

aber ansonsten sind die schon ganz praktisch.


Bezüglich Scanline: Man kann das auch einmal am Anfang in ein Array auslesen
oder nur den Anfang (eigentlich das Ende) sich holen, in einen Pointer, und dann Zeilen/Spalten entsprechend daraus berechen.

Incocnito 22. Nov 2021 07:29

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1497915)
...
Delphi-Quellcode:
    z    := x * x - y + y + 2 * a; // x² - y² + 2a
...

Hehe ... das wäre auch nicht richtig ;-)

Sinspin 22. Nov 2021 10:58

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Truther (Beitrag 1497938)
Naja, wenn ich z.B. Millionen von Pixel vergleichen muss, um mal das Beispiel von meinem gescheiterten Bildvergleichsprogramm aufzugreifen, und das von mehreren tausenden Bildern, dann macht das schon was aus.

Klar, gerade als Anfänger ist man da schnell überfordert, aber das macht es doch erst richtig interessant wenn es klemmt einen Weg zu finden das es weniger klemmt ;-)
Dank des Internets sind da draußen umglaubliche massen an Beispielen wie man dies oder jenes Problem angehen kann, und selber experimentieren ist schon immer der beste Weg gewesen etwas neues zu erfinden.

Delphi.Narium 22. Nov 2021 11:43

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Incocnito (Beitrag 1497952)
Zitat:

Zitat von Delphi.Narium (Beitrag 1497915)
...
Delphi-Quellcode:
    z    := x * x - y + y + 2 * a; // x² - y² + 2a
...

Hehe ... das wäre auch nicht richtig ;-)

Upps, das ist ein Schreibfehler, der nur hier im Forum auftaucht. Im Original kann ich ihn nicht finden. Was ist denn da nur wieder in meinem Schreibfehlerchaos passiert?
Natürlich muss es
Delphi-Quellcode:
z    := x * x - y * y + 2 * a; // x² - y² + 2a
heißen:pale:

Andreas13 22. Nov 2021 14:30

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1497915)
...Natürlich muss es
Delphi-Quellcode:
z    := x * x - y * y + 2 * a; // x² - y² + 2a
heißen:pale:

Wahrscheinlich wäre noch eine Mikrosekunde Ersparnis dabei, wenn man anstelle von
Delphi-Quellcode:
2*a
besser
Delphi-Quellcode:
a + a
schreibt...:-D
Gruß, Adreas

himitsu 22. Nov 2021 15:00

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Beim Integer ist Mal schneller, weil ja "nur" ein Shift.

Aber hätte gedacht, dass es beim Float auch zutrifft.

Truther 22. Nov 2021 18:49

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Ich bin hier auf diese Seite gestoßen, die sich mit Optimierung von Code befasst.

Link: http://www.rinneberg.de/programming/opti.htm

Was sind eure Meinungen dazu? Vielleicht könnte man auf jeden einzelnen Punkt davon eingehen und näher erläutern, sofern das nicht auf der Seite selbst geschehen ist.
Möglicherweise könnte man diese Liste eben auch erweitern.

Nachtrag: In einem Artikel zu Fast direct pixel gibt es einen Punkt zu Pointer. Dort steht:

Zitat:

With use of pointers we can eliminate much of pixel address addition and multiplication by Pixels property access. Only fast increment operation is performed.
Link: https://wiki.lazarus.freepascal.org/...ccess#Pointers

Warum ist das Nutzen von Pointer in dem Fall schneller? Das würde sich auf die Implementierungsfrage beziehen, wie oben an dem Beispiel von
Delphi-Quellcode:
ScanLine
.
Könnte man sagen, dass das Nutzen von Pointern in der Regel schneller ist?

Sinspin 23. Nov 2021 08:23

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Truther (Beitrag 1498008)
Warum ist das Nutzen von Pointer in dem Fall schneller? Das würde sich auf die Implementierungsfrage beziehen, wie oben an dem Beispiel von
Delphi-Quellcode:
ScanLine
.
Könnte man sagen, dass das Nutzen von Pointern in der Regel schneller ist?

Pointer sind Zeiger auf Speicherbereiche. Mit Pointern kann man Rechnen und selber festlegen auf welche Stelle im Speicher man zugreifen will.
Aber schneller als andere Methoden? Nicht wirklich.

Wenn es dir auf Speed ankommt dann vezichte darauf das Bild in irgend einem Objekt (oder einer Komponente) zu lassen.
Ein Bild kann auch als eindimensionales Array gesehen werden. Im Regelfall aus drei Bytes, eins pro Farbe.
Noch schneller wird der Zugriff mit 4 Bytes. Da die Speicherzugriffe dann noch weiter optimiert werden können. Das 4. Byte wird dann einfach nicht werwendet, Speicherverschwendung aber egal wenn es nur um Speed geht.
Also nach dem laden des Bildes die Pixel in ein Array kopieren und mit dem Array arbeiten.
Den Index zum Zugriff berechnet man sich einfach selber um weiterhin Zeilen und Spalten zu haben.

dummzeuch 23. Nov 2021 08:37

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Truther (Beitrag 1498008)
Zitat:

With use of pointers we can eliminate much of pixel address addition and multiplication by Pixels property access. Only fast increment operation is performed.
Link: https://wiki.lazarus.freepascal.org/...ccess#Pointers

Warum ist das Nutzen von Pointer in dem Fall schneller? Das würde sich auf die Implementierungsfrage beziehen, wie oben an dem Beispiel von
Delphi-Quellcode:
ScanLine
.
Könnte man sagen, dass das Nutzen von Pointern in der Regel schneller ist?

Die Alternative zu Pointern ist ein Array. Das ist einfacher zu verwenden, aber je nachdem wie gut der Compiler es umsetzt besteht der erzeugte Code zum Zugriff auf ArrayDaten[x,y] immer aus einem Pointer auf den Datensatz, der berechnet wird aus:

(Pointer auf ArrayDaten) + (Datensatzgröße) * (1. Dimension) * y + (Datensatzgröße) * x

Je nachdem wie gut der Compiler das optimiert wird das Ergebnis gespeichert und kann für mehrere aufeinanderfolgende Zugriffe auf einen Datensetz verwendt werden. Wenn sehr gut optimiert wird, wird in einer Schleife der Pointer immer nur um einen Offset erhöht. Im schlimmsten (unoptimierten) Fall wird diese Berechnung bei jedem Zugriff auf ein Feld des Datensatzes neu durchgeführt.

Da aber der Delphi-Compiler dabei nicht besonders gut optimiert, kann man den Zugriff deutlich beschleunigen, indem man diese Pointer-Arithmetik selbst implementiert.

Beim Zugriff auf die ScanLine Property kommt noch dazu, dass die Getter-Funktion noch komplexere Berechnungen anstellt als einfach nur Pointer-Arithmetik.

(Alles bezogen auf Delphi, ich habe keine Ahnung, wie gut Lazarus / Free Pascal solche Zugriffe optimiert.)

KodeZwerg 23. Nov 2021 08:53

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
>> Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)

Nachdem ich gelesen habe was du geschrieben hast komme ich nur zu dem Schluß "selbst-schreiben".
Nur so kannst du das volle potenzial ausschöpfen.
"vorgefertigter" code kann gut sein, doch die sind meist auf stabilität aufgebaut und nicht auf geschwindigkeit.

Jetzt musst du halt für dich selber entscheiden was dir wichtiger ist, das erlangen neuen wissens um daraus eine hochoptimierrte variante zu entwickeln die wiederum in der herstellung viel zeit kostet,
oder nehme produkt xyz mit dessen bereitgestellten code und lebe mit der geschwindigkeit wie sie ist.

Uwe Raabe 23. Nov 2021 11:06

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von KodeZwerg (Beitrag 1498027)
"vorgefertigter" code kann gut sein, doch die sind meist auf stabilität aufgebaut und nicht auf geschwindigkeit.

Jetzt bin ich etwas besorgt ob des Umkehrschlusses...

KodeZwerg 24. Nov 2021 06:27

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1498038)
Zitat:

Zitat von KodeZwerg (Beitrag 1498027)
"vorgefertigter" code kann gut sein, doch die sind meist auf stabilität aufgebaut und nicht auf geschwindigkeit.

Jetzt bin ich etwas besorgt ob des Umkehrschlusses...

Was ich damit sagen wollte, selbst erstellter code fängt nur das ab was benötigt ist, "vorgefertigter" code hat meist viel mehr Prüfungen und Routinen enthalten, die die Ausführung verlangsamen aber es sichergestellt ist das hinten was bei rauskommt.
Generic vs Specific

TSchnuckenbock 24. Nov 2021 10:22

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Mal etwas klugscheissend: Man kann auch darauf warten, daß die Rechner schneller werden.

Das Projekt, welches ich betreue, ist so 20 Jahre oder Teile davon sogar älter. Damals mußten einige Dinge sehr zeitoptimiert ablaufen, weil die damaligen Rechner es sonst nicht schafften, die Daten zu wuppen und darzustellen.
Der Code basiert z.B. auf Reservierung von Speicher und dann die Zugriffe über Pointer. Jede Änderung am Code bedeutet immer wieder eine intensive Einarbeitung und ist extrem fehleranfällig.
Heutzutage würde man diese Code-Konstrukte durch dynamische Arrays implementieren, was viel einfacher zu verstehen und wartbarer wäre.

Was ich damit sagen will: Man sollte sich bei solchen "tricky" Optimierungen nur auf die notwendigsten Bereiche beschränken.

Uns wurde schon vor 25-30 Jahren im Studium von einem Prof. gepredigt, daß Code möglichst immer leicht verständlich sein sollte. Er warnte damals vor Code, der zwar z.B. in genial wenigen Zeilen umgesetzt wurde, aber eben "tricky" und schwer verständlich ist.

Ich meine, man kann rechenintensive Sachen auch in die Grafikkarte auslagern. Ich meine, das geht mit so ziemlich allem Krams. Ich hab da so im Hinterkopp OpenCL.

TSchnuckenbock 26. Nov 2021 07:56

AW: Möglichkeiten Code zu optimieren (z.B. Laufzeit verringern)
 
Zitat:

Zitat von jaenicke (Beitrag 1497934)
Mich wundert, dass noch kein Profiler angesprochen wurde. Es gibt Tools, die analysieren welcher Teil des Codes wie lange benötigt. Daraus kann man dann ableiten wo man optimieren sollte, wenn möglich.

Die wirklich guten Profiler sind nicht gerade billig, aber dieser hier ist für den Anfang ganz gut:
https://yavfast.github.io/dbg-spider/
Quelltext:
https://github.com/yavfast/dbg-spider

Ich hab mir das Spider-Projekt mal kompiliert. Nur jetzt weiß ich nicht, wie ich genau was damit machen kann. Gibt es dazu irgendwie/irgendwo eine Anleitung? Muß die Dll irgendwie ins zu analysierende Projekt eingebunden werden?
Ich hab noch nie mit so Profilern gearbeitet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:36 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