Lazarus Projekt-Einstellungen: Optimierungen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
PeterS
Beiträge: 161
Registriert: So 22. Feb 2015, 11:36
OS, Lazarus, FPC: L 3.8
CPU-Target: win32

Lazarus Projekt-Einstellungen: Optimierungen

Beitrag von PeterS »

Hallo zusammen,

ich habe gestern im Multithreaded Application Tutorial
https://wiki.freepascal.org/Multithread ... n_Tutorial

folgendes gelesen:
"When switching optimisation level from 1 to 3, a program may become about 5 times faster."

Da ich schonmal irgendwann gehört hatte, daß das Optimieren nicht zu 100% ungefährlich ist,
habe ich hier im Forum gesucht nach diesem Thema, und als ersten Treffer das hier gefunden [solved]:
https://lazarusforum.de/viewtopic.php?f=10&t=16060

Das "Ding" scheint ja gelöst zu sein, und beträfe micht garnicht, da ich eine 32-Bit-EXE generieren lasse.


Aber mal generell:
.
- ist Stufe 2 die Standard-Einstellung ? (ich kann mich nicht daran erinnern, daran "gespielt" zu haben)
- ist Stufe 4 "gefährlich" ? Under which circumstances ?
.
Screenshot (823).png
Screenshot (823).png (47.44 KiB) 2087 mal betrachtet

Ekkehard
Beiträge: 67
Registriert: So 12. Feb 2023, 12:42
OS, Lazarus, FPC: Windows Lazarus 3.6, FPC 3.2.2
CPU-Target: 64-Bit
Wohnort: Hildesheim

Re: Lazarus Projekt-Einstellungen: Optimierungen

Beitrag von Ekkehard »

Hallo,
erst jetzt gesehen, deshalb eine später Antwortversuch.
Die Optimierung versucht Vereinfachungen im Assembler-Code zu machen, die zum einen die Dinge deutlich beschleunigen können, zum anderen aber auch die Gefahren bergen, dass das Programm nicht mehr das tut, was es soll.
Einfache Optimierungen halten bspw. alle lokalen Funktionsvariablen in Registern der CPU, statt im RAM. Wenn man jetzt "Schweinereien" macht, bspw. Zeiger auf lokale Variablen an parallel laufende Threads gibt, die während der Abarbeitung der Funktion diese Variablen verändern, dann wird dies nur ohne Optimierung (= Variablen im RAM) funktionieren, mit der Optimierung (= Variablen in Registern der CPU) aber nicht mehr. Das ist kein Compiler-Fehler, sondern immanent mit der Methode der Optimierung.
Eine komplexere Form der Optimierung versucht die Verwendung von Variablen zu prüfen, also ob das Ergebnis später verwendet wird. Alle Zweige im Programmablauf, die zur Berechnung nie verwendeter Ergebnisse verwendet werden, werden dann eliminiert. Beim Debuggen ohne Optimierung merkt man dann nichts, aber das Programm wird optimiert dann anders ablaufen und Breakpoints können dort nicht mehr gesetzt werden.
Beispiel:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  a, b : Integer;
begin
  a := 10;
  b := a div 2;
  if b > 5 then
     a := a * 2;
  Label1.Caption := IntToStr(a);
end; 
Die beiden Zeilen

Code: Alles auswählen

  if b > 5 then
     a := a * 2;
wird es nur in Optimierung Stufe 0 geben, weil sie ansonsten weggeworfen werden, weil sie offensichtlich nie benötigt werden. In Stufe 0 kann man aber im Breakpoint auf if b > 5 then (via Dialog ) den Wert der Variable b verändern und dann läuft das Programm durch den vorhandenen if-Zweig!

Normale Programmierung sollte mit allen Optimierungsstufen funktionieren.
Der Hnweis bei 4 bedeutet, dass eben nicht alles getestet ist und möglichweise auch "normale" Kniffe schiefgehen können.
Mein Problem im erwähnten Beitrag deckte einen Fehler im Compiler auf, der demnächst dann behoben ist und nicht mehr auftreten soll, er fällt nicht in diese Klasse.
Gruß Ekkehard

Warf
Beiträge: 2146
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Lazarus Projekt-Einstellungen: Optimierungen

Beitrag von Warf »

Optimierungen ist grundsätzlich nix anderes als das ersetzen von Operationen durch schnellere Operationen die das selbe machen unter gewissen Annahmen.

Das heißt wenn ein Programmierer sich an die Regeln der Programmiersprache hält, dann sind sie korrekt. Allerdings versuchen manchmal Programmierer schlauer zu sein als der Compiler oder kennen die Rahmenbedingungen der Programmiersprache nicht, oftmals weil man Dinge mit Trial und Error lernt aber nicht alles was der Compiler akzeptiert ist auch korrekt.

Ein typisches Beispiel dafür ist field reordering. I'm Gegensatz zu einem record bei dem die Reihenfolge der Felder im Speicher garantiert so ist wie in der Deklaration angegeben, kann der Compiler Felder in einer Klasse umsortieren. Das ist kein Problem, da der FPC für das Internet layout der Klassen keine Garantien gibt (Klassen sind nicht ABI stabil). Das hält aber manche Entwickler nicht davon ab sich Pointer auf Klassenfelder zu besorgen und damit dann auf den Speicher der Klasse direkt zuzugreifen. Und wenn man das macht und dann werden die Felder unsortiert, dann geht der code nunmal kaputt.

Aber das ist wie gesagt nicht das die Optimierungen nicht korrekt sind, sondern das die Optimierungen kein koherentes Verhalten für inkorrekten code (z.b. code der die Speicherdarstellung von Klassen ausnutzt) garantiert

Warf
Beiträge: 2146
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Lazarus Projekt-Einstellungen: Optimierungen

Beitrag von Warf »

Was man auch noch dazu sagen sollte, Optimierungen machen debuggen schwerer, da nach Optimierungen der generierte Code sich oftmals nicht mehr 1-1 auf den geschriebenen code übertragen lässt, oder manche Operationen einfach komplett weg optimiert werden.

Daher ist wenn du build modes verwendest die Voreinstellung für Debug Mode O0 oder O1 und für Release Mode O2 oder O3.

Manche Optimierungen werden auch immer gemacht, unabhängig von der Optimierungsstufe, z.b. werden copies bei comst Operationen vermieden, womit dieser Code kaputt ist:

Code: Alles auswählen

procedure Foo(const s: string; out s2: string);
begin
  s2:='';
  writeLn(s);
end;
 
var
  S: String;
begin
  s:='Hello World';
  UniqueString(s);
  Foo(s,s);
end.

Antworten