| Autor |
Nachricht |
Fiete
      
Beiträge: 230
Erhaltene Danke: 17
WinXP und Win98SE
Delphi 6 pro, Delphi 2006 und Turbo Pascal 7
|
Verfasst: Mo 20.06.11 11:06
Verwendete Sprache: Delphi
Die Quicksortprocedure hab ich in Assembler umgesetzt, die fünf lokalen Variablen ließen sich gut mit dem Stack verarbeiten. Der Geschwindigkeitszuwachs hält sich in Grenzen
alte Prozedur
neue Prozedur
Viel Spaß beim studieren
Gruß Fiete
Einloggen, um Attachments anzusehen!
_________________ Fietes Gesetz: use your brain (THINK)
|
| |
|
|
Werbung ausblenden? Dann registriere Dich kostenlos.
Weitere Gründe für eine Registrierung.
Werbung ausblenden? Dann registriere Dich kostenlos.
Weitere Gründe für eine Registrierung.
|
|
BenBE
       
Beiträge: 8625
Erhaltene Danke: 147
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 20.06.11 11:24
Du kannst deine SHL EBX,2 gefolgt von nem Displacement durch
ersetzen. Außerdem kannst Du das begin/end der Methode an sich weg lassen, wenn Du die Stack-Behandlung eh selber machst. Das spart auch noch mal zyklen.
Deine Stack-Frames sind übrigens absolut unsauber. Pfui! Außerdem: So viel, wie Du auf dem Stack rumwurschtelst, ist das absolut klar, dass das nicht schneller wird  Außerdem gibt's zum Tauschen von Speicherzellen mit Register ne Anweisung XCHG, die recht gut funktioniert, wenn Du das inline machen willst.
Insgesamt ist da also noch einiges zu verbessern; hab leider nur grad wenig Zeit für's Optimieren.
Und Edith meint, du solltest nicht mit den Offsets arbeiten (SUB EBX, 4), sondern die Indizes nutzen und die Displacements dann entsprechend Multiplizieren; das macht die CPU dann nämlich intern und brauch keinen zusätzlichen Zyklus.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
| |
|
|
herr-master
      
Beiträge: 25
|
Verfasst: Mo 27.06.11 16:06
Hm allso ich hab mir das mal im debugger angeschaut du solltest es veleicht so lösen.
Das ist nur ein teil des optiermierten codes.
Da mir der code sonst zu lang wird und ich nicht genau weiß wieviel zeilen man hier zu verfügung hat zum schreiben.
|
| |
|
|
jaenicke
      
Beiträge: 15841
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Mo 27.06.11 17:35
|
| |
|
|
Horst_H
       
Beiträge: 1004
Erhaltene Danke: 10
WIN7,PuppyLinux
Turbo Delphi, FreePascal
|
Verfasst: Di 28.06.11 08:46
Hallo,
was ist wo optimiert?
EAX wird "von" sein und EDX ist dann "bis"
Es wird statisch gegen $05f5e0fe = 99999998 verglichen, was irgendwie merkwürdig ist für etwas universelles.
Da fehlt wo Label steht, es sieht nach einer procedure außerhalb aus.
Es ist zuwenig Code um etwas damit anfangen zu können.
Gruß Horst
|
| |
|
|
Delphi-Laie
      
Beiträge: 503
Erhaltene Danke: 30
Delphi 2-4
|
Verfasst: Di 28.06.11 18:01
Fiete hat folgendes geschrieben : | | Die Quicksortprocedure hab ich in Assembler umgesetzt, die fünf lokalen Variablen ließen sich gut mit dem Stack verarbeiten. Der Geschwindigkeitszuwachs hält sich in Grenzen |
Das ist zwangsläufig, denn Quicksort gehört bereits zu den (asymptotisch) optimalen Sortieralgorithmen. Mithin kann auch eine Assemblerimplementierung keinen nennenswerten Geschwindigkeitsvorteil mehr bewirken. Nichtdestoweniger ist eine solche Mühe bemerkens- und lobenswert.
Für welchen Datentyp und welche Datenmenge ist Dein Algorithmus möglich? Ich sehe in der Menge der zu übergebenden Variablen nur zwei Integer. Wie wird die eigentliche, nämlich die zu sortierende Datenmenge übergeben oder sonstwie adressiert?
|
| |
|
|
herr-master
      
Beiträge: 25
|
Verfasst: Di 28.06.11 19:15
Hier ist der gesammte code:
|
| |
|
|
jaenicke
      
Beiträge: 15841
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Di 28.06.11 19:18
|
| |
|
|
herr-master
      
Beiträge: 25
|
Verfasst: Di 28.06.11 19:30
Das ist doch nur der disassemblierte Code, den Delphi generiert. Und was soll das jetzt bringen im Hinblick auf das Thema?
Damit wollte ich drauf hindeuten das es nicht überall notwendig ist den code zu optimiren.
Da delphi von sich aus den code in asm schon optimiert.
Hier ist der pure asm code:
Der code kommt direckt aus dem debugger(ollydbg)
|
| |
|
|
BenBE
       
Beiträge: 8625
Erhaltene Danke: 147
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 29.06.11 11:01
@Herr_master: Und was ist an dem Code vom Delphi-Compiler bitte optimiert? So viele Speicherzugriffe da drin sind, ist das weder optimal noch guter ASM-Code.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
| |
|
|
Fiete 
      
Beiträge: 230
Erhaltene Danke: 17
WinXP und Win98SE
Delphi 6 pro, Delphi 2006 und Turbo Pascal 7
|
Verfasst: Mi 29.06.11 11:42
@BenBE: habe einiges geändert - hoffentlich verbessert
Gruß Fiete
_________________ Fietes Gesetz: use your brain (THINK)
|
| |
|
|
Horst_H
       
Beiträge: 1004
Erhaltene Danke: 10
WIN7,PuppyLinux
Turbo Delphi, FreePascal
|
Verfasst: Mi 29.06.11 12:01
Hallo,
Es wäre schön, die Startadresse von Liste zu übergeben
Nebenbei bemerkt:
Ist es schneller?
Gruß Horst
|
| |
|
|
herr-master
      
Beiträge: 25
|
Verfasst: Mi 29.06.11 16:53
Allso leut google und einigen seiten ist der code den delphi generiert in asm schon zimlich gut optiermiert zwar nicht bei allen functionen aber bei den meisten.@Horst_H so eine version gibt es schon für delphi :
Auf dieser seite gefunden:
delphi.about.com/od/...lide/a/quicksort.htm
|
| |
|
|
jaenicke
      
Beiträge: 15841
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Mi 29.06.11 17:32
herr-master hat folgendes geschrieben : | | Allso leut google und einigen seiten ist der code den delphi generiert in asm schon zimlich gut optiermiert |
Man merkt, dass du nicht viel Ahnung von Assembler hast...
Manchmal kommen da so viele unnötige Befehle heraus... Nur hat eine solche Optimierung in Assembler eben auch gravierende Nachteile, so dass ich es meistens eben akzeptiere...
|
| |
|
|
BenBE
       
Beiträge: 8625
Erhaltene Danke: 147
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 30.06.11 02:25
@Fiete: Das End; von nem ASM-Block ist bereits ein RET-Befehl. Du kannst also
machen und bekommst auch den richtigen Code raus. ist 1 Byte sogar kleiner
Das ist auch der Hintergrund, warum ich gesagt hab, dass man ohne das begin/ end arbeiten sollte, weil Delphi dann kein eigenes Stackframe schreibt.
Irgendwie kann ich mich mit deinem pushad/popad noch nicht so recht anfreunden. Ist zwar wegen dem call @Quick nur einmal für den gesamten Sortier-Vorgang, aber sieht trotzdem unschön aus.
Noch ne kleine Schönheitssache:
statt
ist zwar paar Zeichen mehr zu tippen, ist aber schon anhand des Mnemonic etwas eindeutiger (LEA = Load Effective Address). Wird aber intern auch nur in ein MOV übersetzt. Hintergrund ist der, dass ältere Delphi-Versionen mit der Offset-Syntax nichts anfangen können; mit LEA aber schon. Damit wird der Code etwas portabler.
Ein anderer Trick zum Tauschen von Speicherinhalten ist:
Wenn man den Wert von PtrExpr1 oder PtrExpr2 bereits im Speicher hat, entfällt eine der XCHG-Anweisungen entsprechend. Wäre bei @Swap der Fall, weil Du durch den Vergleich eh bereits in EAX einen der beiden Werte hast.
Wenn man Platz sparen möchte, kann man sogar das
umbauen zu
Was auf aktuellen Superskalaren CPUs (also allen ^^) zwar kleineren Code erzeugt, aber langsamer ist und zudem den Nachteil hat, dass in EDI der fertig berechnete Pointer stehen muss. Analog ginge das Lesen mit
mit
zu vereinfachen, wobei aber die gleichen Nachteile gelten. Die Variante mit 2 Befehlen ist hier also in beiden Fällen trotz des längeren Codes zu bevorzugen.
Ach ja: In deiner Konstruktion ab Zeile 38 solltest Du ggf. schauen, dass Du EDI (Zeile 47 und 50) direkt auf dem Stack lässt und ESI/EBP umordnest, so dass Du nur eines von beiden vom Stack holen musst:
Ja, es gehen auch Displacements über den Stack-Pointer  Und durch dein Wiederherstellen der ganzen Register beim Verlassen von Quick könnte man sogar das POP ESI/PUSH ESI weglassen und EBP als beibehalten annehmen. Da EBP nie geschrieben wird in @Quick, könnte man sich sogar das PUSH EBP/POP EBP sparen. Den CMP bei Weiter hatte ich zuerst mit
was das gleiche ist. Man kann aber, wenn man sich einen Speicherzugriff sparen möchte:
machen. Das dürfte aber unter Nutzung des L1 Data-Cache eher wenig ausmachen.
Mehr seh ich jetzt grad erstmal nicht mehr. Erstens zu müde und zweitens keinen Debugger da zum Durchsteppen.
HTH.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
| |
|
|
|