Autor |
Beitrag |
Tranx
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Mi 12.09.12 17:49
Horst_H, ohne Random kommen keine zufälligen Abweichungen zustande. Aber random ist nicht so verlangsamend (statt 0,89 s ohne sind es 0,91 s mit Random). Allerdings ist die Darstellung ohne Random alles andere als plasmaähnlich). Das Problem sind die 2 Mio Aufrufe. Das sind bei 0,9 s ja bloß 0,45 µs pro Aufruf. (Mal so global berechnet. Es sind ja noch andere Prozeduren da)
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Mi 12.09.12 18:38
Hallo Horst_H,
Horst_H hat folgendes geschrieben : | ist nicht die Funktion random nicht die Wurzel allen Übels in der Funktion Farbmitte?
Einfach mal weglassen und testen. |
Die Bilder sehen ganz lustig aus, die ohne Random entstehen. Leider geht's ohne Zufallszahlen wirklich nicht.
Aber vielleicht ist das Bestimmen der Zufallszahlen doch veränderbar.
Schon bei meinen aller ersten Versuchen hatte mich gestört, dass ich eine Zufallszahl aus dem Intervall [-abweich/2 , +abweich/2] nur bestimmen konnte durch die merkwürdige Konstruktion
Delphi-Quelltext 1:
| random(abweich) - abweich div 2 |
Halbiere ich von Anfang an die Variable und suche im Bereich [-abweich, abweich], so wird es mit
Delphi-Quelltext 1:
| random(2*abweich) - abweich |
auch nicht schneller. Die Operationen div 2 oder mit 2 multiplizieren sind scheinbar gleich schnell.
Ich habe auch schon versucht über real-Zahlen, also nur mit random, zu arbeiten. Dort bremst das dann notwendige round aus.
Vielleicht gibt es ein bessere Methode eine zufällige Zahl im genannten Intervall zu ermitteln. Ich grüble schon länger darüber nach, leider ohne Erfolg.
Ein superschneller Pseudozufallsgenerator könnte vielleicht helfen?
Beste Grüße
Mathematiker
Nachtrag: Ich habe versucht den im Forum www.entwickler-ecke....ight=zufallszahl+asm beschriebenen Zufallsgenerator einzubauen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function randomrange(a,b: integer): integer; asm push eax xchg eax, edx sub eax, edx imul edx, [randseed], $08088405 inc edx mov [randseed], edx mul edx pop eax add eax, edx end; |
Die Geschwindigkeit bleibt vorerst etwa gleich, da ich an a und b -abweich div 2 und +abweich div 2 übergeben muss.
Könnte man nur einen Wert übergeben, so könnte es vielleicht schneller werden.
Aber ohne ASM-Kenntnisse weiß ich nicht einmal, wo eigentlich die Variable b steckt? a ist wohl in eax.
Es wird sich wohl nicht vermeiden lassen. Ich muss mich mit ASM beschäftigen.
Nachtrag 2: Ich hab es durch Versuch und Irrtum!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function randomrange(a: integer): integer; asm shr eax, 1 mov edx, eax neg eax push eax xchg eax, edx sub eax, edx imul edx, [randseed], $08088405 mov [randseed], edx mul edx pop eax add eax, edx end; |
ermittelt eine Zufallszahl im Intervall [-a/2,a/2]. Leider ist der Gesamtzeitgewinn nur unwesentlich.
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Mi 12.09.12 21:29
Hallo,
meine ASM-Versuche machen ja richtig Spaß. Ich habe die alte farbmitte-Prozedur
Delphi-Quelltext 1: 2: 3: 4:
| function farbmitte(f1,f2,abweich:integer):byte; begin farbmitte:=max(1,((f1+f2) div 2+ random(abweich)-abweich div 2) mod 256); end; |
durch
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function farbmitte(f1,f2,abweich:integer):byte; function randomrange(f1,f2,a: integer): integer; asm add eax, edx shr eax, 1 push eax mov eax, ecx shr eax, 1 mov edx, eax neg eax push eax xchg eax, edx sub eax, edx imul edx, [randseed], $08088405 mov [randseed], edx mul edx pop eax add eax, edx pop edx add eax, edx end; begin farbmitte:=max(1,randomrange(f1,f2,abweich) mod 256); end; |
ersetzt und man spart schon etwas Zeit (rund 5 %). Schön wäre nun, wenn ich auch gleich noch mod 256 durchführen könnte.
Mein Versuch mit den 3 mit // gekennzeichneten Zeilen funktioniert nicht richtig. Oder gibt es auch unter ASM einen Mod-Befehl? In meiner Befehlsliste habe ich keinen gefunden.
Auch die Idee mit
Delphi-Quelltext
an Stelle der 3 Zeilen bringt nicht das Gewünschte.
Ganz toll wäre natürlich, wenn die Assemblerroutine auch gleich noch das Maximum bestimmt. Aber da habe ich nun gar keine Ahnung mehr.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Horst_H
Beiträge: 1652
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 13.09.12 11:11
Hallo,
etwas offtopic, oben auf dem Rechner läuft die angehängte EXE rev5 1,4 Sekunden unter Win7 und unter Linux mittels wine 1.5.2 in nur ( auch gefühlt ) 0,75 in Sekunden.
Mit Lazarus 0.93/fpc 2.6.1 ( es gibt jetzt Version 1.0 ) kompiliert ( dazu habe ich scanline aus dem Farbwechsel rausgeworfen und .canvas.pixels genutzt, was so langsam ist das eine CPU uner Volllast läuft ) sind es unter Win7 auch 0.8 Sekunden.
Wie wäre ein Test, wieviel canvas.pixels ausmacht?
Also in der procedure fenster alle
bitmap.canvas.Pixels[xe,ym]:=???;
auszukommentieren.
Man sieht zwar nichts, aber die Zeiten sind ja interessant.
Man könnte bei ausreichendem Zeitunterschied ja statt der Bitmap ein eigenes Feld nutzen und dieses dann kopieren.
Zudem müßte ein 32-bit Format für die Farben schneller sein.
"Früher" hat man für ein VGA-Plasma ein 8 Bit Format gehabt und auf dem VideoChip die Palette geändert.
de.wikibooks.org/wik...rrupts_80x86/_INT_10
Farbpalatte festlegen
Das muss auch immer noch gehen.
Siehe wincrt/winGraph von Stefan Berinde math.ubbcluj.ro/~sbe...e/wingraph/main.html macht das ja auch.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| Aus wingraph procedure SetAllPalette(var palette); var pe: array of PALETTEENTRY; i: longint; begin grResult:=grOK; if not(grEnabled) then begin grResult:=grNoInitGraph; Exit; end; if not(palExist) then begin grResult:=grNoPalette; Exit; end; with PaletteType(palette) do begin if (size > maxColors) then begin grResult:=grInvalidParam; Exit; end; SetLength(pe,size); for i:=0 to size-1 do with pe[i],colTable[i] do begin peRed:=GetRValue(colors[i]); peGreen:=GetGValue(colors[i]); peBlue:=GetBValue(colors[i]); peFlags:=0; rgbRed:=peRed; rgbGreen:=peGreen; rgbBlue:=peBlue; rgbReserved:=0; end; for i:=size to maxColors-1 do with pe[0],colTable[i] do begin rgbRed:=peRed; rgbGreen:=peGreen; rgbBlue:=peBlue; rgbReserved:=0; end;
EnterCriticalSection(protect_devices); ResizePalette(grPalette,size); SetPaletteEntries(grPalette,0,size,pe[0]); SetDIBColorTable(grMemory,0,maxColors,colTable[0]); MapPaletteColors; RealizePalette(grWindow); RealizePalette(grMemory); RealizePalette(grTemp); LeaveCriticalSection(protect_devices);
InvalidateRect(grHandle,nil,false); palSize:=size; SetLength(pe,0); end; end; |
Gruß Horst
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 13.09.12 13:47
Hallo Horst_H,
Horst_H hat folgendes geschrieben : | Wie wäre ein Test, wieviel canvas.pixels ausmacht?
Also in der procedure fenster alle
bitmap.canvas.Pixels[xe,ym]:=???;
auszukommentieren. |
Geniale Idee und siehe da, die Berechnungszeit schrumpft auf weniger als 10%. Selbst meine alte "Mühle" braucht nun nur noch 0,1 s. Das Bild erscheint nahezu sofort! Besser geht es kaum noch. In der Rev 6 habe ich die Änderung sofort untergebracht.
Wenn ich jetzt noch mein ASM-Problem erfolgreich löse, dürfte es kaum noch schneller gehen.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Horst_H
Beiträge: 1652
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 13.09.12 13:54
Hallo,
Revision 6 hat wohl seine Macken.
Soviele Zugriffe auf Adresse $00 in so kurzer Zeit hatte ich noch nie....
Gruß Horst
P.S.
Ohne Canvas.Pixels schreibt man eigentlich auch keine Farbe an irgendeine Stelle, es ging nur darum zu zeigen, was die wahre Bremse ist.
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 13.09.12 13:57
Horst_H hat folgendes geschrieben : | Revision 6 hat wohl seine Macken.
Soviele Zugriffe auf Adresse $00 in so kurzer Zeit hatte ich noch nie.... |
Tut mir leid und verstehe ich auch nicht. Bei mir läuft es einwandfrei. Ich werde testen!
Beste Grüße
Mathematiker
Nachtrag: Ich habe plasma.zip im ersten Eintrag, ohne meine stümperhaften ASM-Versuche, die offensichtlich nicht funktionieren, angefügt.
Noch einmal: Tut mir leid.
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Zuletzt bearbeitet von Mathematiker am Do 13.09.12 14:37, insgesamt 1-mal bearbeitet
|
|
Tranx
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Do 13.09.12 14:11
Ich glaube kaum, dass Assemblerroutinen viel bringen, da der Compiler ja eh den Code optimiert. Da werden dann schon die entsprechenden Assemblerschritte erzeugt. Irgendwo habe ich mal gelesen, dass auch die Registerverwendung wenig bringt, da der Compiler auch hier diese optimiert. Da entstehen dann oft nur Fehler, weil irgendwelche Sprünge im Nirwana landen. Ich würde wegen der 5% da keine weitere Anstrengung unternehmen. Wenn es möglich wäre, die Aufrufe z.B. von Farbmitte und Fenster drastisch zu reduzieren, bringt das sicher wesentlich mehr.
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 13.09.12 14:19
Hall Tranx,
Tranx hat folgendes geschrieben : | Ich glaube kaum, dass Assemblerroutinen viel bringen, da der Compiler ja eh den Code optimiert. Da werden dann schon die entsprechenden Assemblerschritte erzeugt. |
Ich lasse mich gern überzeugen. Es war ein erster (erfolgloser) Versuch mit ASM. Ich habe es zwar noch im Text stehen, rufe es aber in Rev 7 nicht mehr auf. Und bei der jetzt erreichten Geschwindigkeit ist es wohl auch nicht mehr notwendig.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Gammatester
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Do 13.09.12 15:51
Mathematiker hat folgendes geschrieben : | Es war ein erster (erfolgloser) Versuch mit ASM. Ich habe es zwar noch im Text stehen, rufe es aber in Rev 7 nicht mehr auf. |
Hallo, das and eax,255 als Ersatz für mod 256 ist schon richtig!
Ich weiß zwar nicht, was genau bei Deinem ASM-Versuch erfolglos war, aber Deine Funktion erzeugt auf jeden Fall keine random-komptatible Zahlen. Delphi verwendet einen Linearen Kongruenzgenerator, und zwar im wesentlichen randseed := (randseed * $08088405 + 1) mod 2^32. Bei Dir fehlt der wichtige (+ 1)-Teil, und durch das Weglassen wird der Generator zur programmierten Katastrophe; in dem von Dir zitierten Kodeschnipsel ist er (via inc edx) noch vorhanden.
Einen Versuch mit der wiedereingebauten verlorenen Zeile solltest Du allemal machen, und sei's nur im zu sehen, daß das der Grund für die Erfolglosigkeit war.
Gruß Gammatester
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Horst_H
Beiträge: 1652
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 13.09.12 16:37
Hallo,
ich habe einen Fehler begangen und einfach nur die EXE extrahiert und gestartet.Dadurch fehlte die Datei palette.c00 und deshalb erst IO-Fehler 103 und dann die nicht enden wollenden Zugriffsverletzungen.
Liegt also nicht am ASM-Teil sondern nur an meiner Bequemlichkeit
Jetzt erstellt das Programm ratz-fatz in knapp 0,07 Sekunden eine neue Darstellung.
Die Zeile
Delphi-Quelltext 1:
| if anzahl mod 50000 = 0 then application.processmessages; |
kann man sich sparen.Nur echte Gamer sind so schnell.
Statt
Delphi-Quelltext 1: 2: 3:
| anzahl mod 50000 = 0 then lieber etwas wie anzahl AND ( (1 shl 16) - 1) = 0 |
Mein AMD dividiert ungern.
Gruß Horst.
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Do 13.09.12 16:43
Die Geschwindigkeitsfortschritte dieses Programmes sind atemberaubend.
Leider mußte ich mich schon sehr bald mit meinen nicht allzu hilfreichen Hinweisen ausklinken.
Eine Ergonomieangelegenheit fiel mir noch auf: Trotz der deutlich schnelleren Geschwindikeit gibt es ggf. immer noch eine spürbare Verzögerung zwischen dem Aufrufen der Combobox für die Farbpalette und dem Darstellen des Bildes. Klickt man währenddessen im Eifer des Gefechtes auf den Druckschalter "Darstellung" (weil man z.B. annimmt, daß das erforderlich sei), so wird nach Erscheinen des Bildes dieses dann zweimal gezeichnet. Vielleicht könnte man während des Bildaufbaus den Druckschalter "Darstellung" unbedienbar machen?
Daß es für mod noch einen schnelleren Ersatz gibt, wußte ich bis dato nicht. Immerhin wird diese Funktion n.m.W. 1:1 als Maschinencoe übersetzt. Verstehe nicht, daß es da keine "prozessorinterne" Optimierung gibt. Schließlich gibt es sozusagen zwei Funktionen für das gleiche.
Sollte der Assembler-Integer-Zufallsgenerator es wirklich zur "Serienreife" schaffen, rege ich an, ihn separat in der Bibliothek zu veröffentlichen.
Zuletzt bearbeitet von Delphi-Laie am Do 13.09.12 22:40, insgesamt 1-mal bearbeitet
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 13.09.12 18:02
Hallo Gammatester,
Gammatester hat folgendes geschrieben : | Bei Dir fehlt der wichtige (+ 1)-Teil, und durch das Weglassen wird der Generator zur programmierten Katastrophe; in dem von Dir zitierten Kodeschnipsel ist er (via inc edx) noch vorhanden. |
Danke für den Hinweis. Es ist typisch für mich! Beim Abtippen habe ich eine Zeile übersehen. Aber das kommt davon, wenn man doch nicht so richtig weiß, was bei Assembler passiert.
Gammatester hat folgendes geschrieben : | Einen Versuch mit der wiedereingebauten verlorenen Zeile solltest Du allemal machen, und sei's nur im zu sehen, daß das der Grund für die Erfolglosigkeit war. |
Habe ich gleich gemacht. Im Ergebnis habe ich nun
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| function farbmitte(f1,f2,abweich: integer): integer; asm add eax, edx shr eax, 1 push eax xor eax, eax mov edx, ecx push eax xchg eax, edx sub eax, edx imul edx, [randseed], $08088405 inc edx mov [randseed], edx mul edx pop eax add eax, edx shr ecx, 1 sub eax, ecx pop edx add eax, edx and eax, 255 cmp eax, 0 jna @null ret @null: mov eax, 1 end; |
Irgendwie funktioniert es schon und es ist auch schneller. Dennoch sehen die entstehenden Abbildungen etwas anders aus, als bei
Delphi-Quelltext 1: 2: 3: 4:
| function farbmitte(f1,f2,abweich:integer):byte; begin result:=max(1,((f1+f2) div 2 + random(abweich) - abweich div 2) mod 256); end; |
Mit Assembler entstehen mitunter merkwürdige, kleine farbige Bereiche, ohne nicht. Irgendwo steckt also noch ein Fehler.
Hallo Horst_H,
es freut mich, dass es doch funktoniert.
Hallo Delphi-Laie,
Delphi-Laie hat folgendes geschrieben : | Die Geschwindigkeitsfortschritte dieses Programmes sind atemberaubend. |
Ich hätte nie gedacht, dass es so schnell wird, von ursprünglich gut 8 Sekunden auf nun weniger als 0,1 Sekunden (auf meinem PC).
Delphi-Laie hat folgendes geschrieben : | Trotz der deutlich schnelleren Geschwindikeit gibt es ggf. immer noch eine spürbare Verzögerung zwischen dem Aufrufen der Combobox für die Farbpalette und dem Darstellen des Bildes. Klickt man währenddessen im Eifer des Gefechtes auf den Druckschalter "Darstellung" (weil man z.B. annimmt, daß das erforderlich sei), so wird nach Erscheinen des Bildes dieses dann zweimal gezeichnet. Vielleicht könnte man während des Bildaufbaus den Druckschalter "Darstellung" unbedienbar machen? |
Ich habe schon etwas geändert. Mal sehen, was noch machbar ist.
In der Rev 8 (schon wieder eine!) sind beide farbmitte-Methoden (ohne und mit ASM) enthalten. Voreingestellt habe ich im Moment noch ohne Assembler.
Das 2.Bitmap habe ich im Text entfernt. Man braucht es nicht mehr. Außerdem kann man die Größe des Programmfensters jetzt ändern.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
OlafSt
Beiträge: 486
Erhaltene Danke: 99
Win7, Win81, Win10
Tokyo, VS2017
|
Verfasst: Fr 14.09.12 23:52
Mathematiker hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function farbmitte(f1,f2,abweich: integer): integer; asm [...] sub eax, ecx pop edx add eax, edx and eax, 255 cmp eax, 0 jna @null ret @null: mov eax, 1 end; |
|
Ich hätte da eine winzige Optimierung anzubieten, was diesen Assemblerteil angeht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function farbmitte(f1,f2,abweich: integer): integer; asm [...] sub eax, ecx pop edx add eax, edx and eax,255 cmovnz eax,1 ret end; |
Sollte der Conditional Move falsch herum sein, einfach in CMOVZ umändern CMOVxx gibts seit dem 80486, sollte also auch auf alten Maschinen problemlos laufen und auch von alten Delphi-Compilern übersetzbar sein.
Was die Abweichungen mit/Ohne ASM angeht: Mir war so, als wäre der div-Operator noch unterhalb der Additions- und Subtraktionsoperatoren angesiedelt. Ich habe nicht den Eindruck, das das richtig in der ASM-Routine berücksichtigt ist.
Aber ich mag hier irren, es ist Jahre her, das ich in der Gegend im Helpfile unterwegs war.
_________________ Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Für diesen Beitrag haben gedankt: Martok
|
|
Horst_H
Beiträge: 1652
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Sa 15.09.12 06:58
Hallo,
Ich habe neben der Zeit auch anzahl ausgegeben und war erstaunt.
Die Anzahl der Berechnungen fand ich verbesserungswürdig.
Farbtupfer steht als Ersatz für eine Berechnung:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118:
| program unbenannt;
var AnzahlBerechnungen, Farbtupfer: longInt;
procedure fensterOrg(xa,xe,ya,ye:integer); var xm,ym,dx,dy:integer; begin inc(AnzahlBerechnungen); xm:=(xa+xe) div 2; ym:=(ya+ye) div 2; if xa>0 then else begin inc(Farbtupfer); end;
if ya>0 then else begin inc(Farbtupfer); end;
inc(Farbtupfer);
inc(Farbtupfer);
inc(Farbtupfer);
if xm>xa then begin fensterOrg(xa,xm,ya,ym); fensterOrg(xa,xm,ym,ye); end; if xe>succ(xm) then begin fensterOrg(xm,xe,ya,ym); fensterOrg(xm,xe,ym,ye); end; end; procedure fenster(xa,xe,ya,ye:integer); var xm,ym,dx,dy:integer; bDx,bDy : boolean; begin dx:=(xe-xa); dy:=(ye-ya); bDx := dx > 1; bDy := dy > 1; if Not(bDx OR bDy) then exit;
inc(AnzahlBerechnungen); xm:=(xa+xe) div 2; ym:=(ya+ye) div 2; IF xa = 0 then inc(farbtupfer); IF ya = 0 then inc(farbtupfer);
IF bdy then inc(farbtupfer,1);
IF bdx then inc(farbtupfer);
IF bdx AND bdy then inc(farbtupfer);
fenster(xa,xm,ya,ym); fenster(xa,xm,ym,ye); fenster(xm,xe,ya,ym); fenster(xm,xe,ym,ye);
end; const width= 620; height = 568; BEGIN AnzahlBerechnungen := 0; farbtupfer:= 4; fenster (0,width-1,0,height-1); writeln(' Anzahl Pixel :',width*height); writeln(' Anzahl Rekursionen :',AnzahlBerechnungen); writeln(' Anzahl berechneter Pixel :', FarbTupfer);
AnzahlBerechnungen := 0; farbtupfer:= 4; writeln; writeln('Original Plasma 8'); fensterOrg (0,width-1,0,height-1); writeln(' Anzahl Pixel :',width*height); writeln(' Anzahl Rekursionen :',AnzahlBerechnungen); writeln(' Anzahl berechneter Pixel :', FarbTupfer); END. |
Mit der Ausgabe:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| Anzahl Pixel :352160 Anzahl Rekursionen :164440 Anzahl berechneter Pixel :352160
Original Plasma 8 Anzahl Pixel :352160 Anzahl Rekursionen :382805 Anzahl berechneter Pixel :1150530 |
Es werden nur noch knapp 1/3 Berechnungen benötigt.
Anzahl Rekursionen ist der falsche Ausdruck, es sollte Anzahl Berechnugsdurchläufe heißen.
Meine Variante wird 822201 fach aufgerufen aber läuft nur in 164440 durch.
Ich habe es nicht mit Lazarus getestet, vielleicht morgen
Gruß Horst
faktor 0 sieht sweet aus.
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 15.09.12 08:55
Hallo OlafSt,
OlafSt hat folgendes geschrieben : | Ich hätte da eine winzige Optimierung anzubieten, was diesen Assemblerteil angeht:
...
Sollte der Conditional Move falsch herum sein, einfach in CMOVZ umändern CMOVxx gibts seit dem 80486, sollte also auch auf alten Maschinen problemlos laufen und auch von alten Delphi-Compilern übersetzbar sein.
Was die Abweichungen mit/Ohne ASM angeht: Mir war so, als wäre der div-Operator noch unterhalb der Additions- und Subtraktionsoperatoren angesiedelt. Ich habe nicht den Eindruck, das das richtig in der ASM-Routine berücksichtigt ist.
|
Danke für den Hinweis. Es gibt nur bei mir ein kleines Problem. Mein Delphi 5 meckert sowohl bei cmovz als auch cmovnz mit dem Kommentar "Syntaxfehler".
In meiner ASM-Befehlsliste für Delphi steht dieser Befehl auch nicht drin. Könnte es sein, dass er erst in späteren Delphi-Versionen richtig erkannt wird?
Schön wäre es, wenn es funktionieren würde, denn die Berechnung würde wohl noch schneller ablaufen.
Den 2.Hinweis werde ich genauer überprüfen. Ich habe Klammern gesetzt, so dass es jetzt
Delphi-Quelltext 1:
| result:=max(1,(((f1+f2) div 2) + random(abweich) - (abweich div 2)) mod 256); |
wird; mit dem weiterhin richtigen Ergebnis. Eigentlich dachte ich genau das in der Assembler-Routine umgesetzt zu haben. Offensichtlich aber nicht.
Meine Überlegung war, dass während der Berechnung ja auch negative Zahlen vor dem mod auftreten können. Delphi gibt nach mod einen negativen Wert zurück, der dann durch max richtig zu 1 wird.
Ich weiß nun nicht, ob auch im Assembler-Text das ebenso geschieht.
Vor vielen, vielen Jahren hatte ich etwas mit Assembler am U880 zu tun und errinere mich nur noch schwach, dass es da Probleme mit negativen Zahlen gab und man irgendwelche Flags abfragen musste.
Hallo Horst_H,
Danke für Deine neue Idee. Allerdings muss ich das erst einmal richtig verstehen. Ich melde mich wieder, so bald ich es ausprobiert habe.
Verwirrt bin ich nur, dass scheinbar die Prozedur Fenster nicht mehr aufgerufen wird. Jedenfalls markiert mein Compiler die Prozedur nach dem Übersetzen nicht mit den berühmten Pünktchen an der Seite.
Nachtrag: Ich glaube, Deine Idee verstanden zu haben und es geht erneut schneller. Lustiger Nebeneffekt ist, dass die Tests
Delphi-Quelltext 1: 2:
| bdx := dx>1; bdy := dy>1; |
nun bei Faktor = 1 geändert werden müssen auf >0. Setzt man >2, dann funktioniert es ab Faktor = 4.
Beste Grüße
Mathematiker
Nachtrag 2: Angeregt von der Horst_H-Idee die Berechnungen zu zählen, konnte ich diese durch Einfügen von
Delphi-Quelltext 1:
| if (xe-xa<=1) and (ye-ya<=1) then exit; |
als 1.Zeile der Fensterprozedur deutlich verringern. Dennoch sind immer noch einige zu viel.
Da es eine wichtige Änderung ist, füge ich dies als Rev 9 in den ersten Eintrag ein.
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 15.09.12 12:06
Hallo,
ich hab's gefunden und bin etwas stolz auf mich.
Die Assembler-Routine farbmitte läuft einwandfrei:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| function farbmitte(f1,f2,abweich: integer): integer; asm add eax, edx shr eax, 1 cmp ecx, 1 jbe @ohnea push eax xor eax, eax mov edx, ecx push eax xchg eax, edx sub eax, edx imul edx, [randseed], $08088405 inc edx mov [randseed], edx mul edx pop eax add eax, edx pop edx add eax, edx shr ecx, 1 sub eax, ecx jc @null @ohnea: and eax, 255 cmp eax, 0 jz @null ret @null: mov eax, 1 end; |
Ich musste erst (f1+f2) div 2 addieren und danach die halbe Abweichung subtrahieren. Damit ist bei einem Überlauf das Carry-Flag gesetzt und ich kann korrekt springen.
Ergebnis: Die Berechnung eines Bildes wird noch einmal schneller. Auf meinem PC dauert es nun höchstens 0,72 s, mitunter, je nach Zufallswerten, auch noch weniger.
Mittlerweile habe ich auch, zumindest für ungefähr quadratische Zeichenbereiche, die überflüssigen Berechnungen beseitigen können. d.h. die Horst_H-Idee umgesetzt. Der Geschwindigkeitsgewinn war nicht so groß, aber jetzt ist der Algorithmus exakter. Warum bei größeren Unterschieden von Breite und Höhe doch wieder mehr Berechnungen auftreten, weiß ich noch nicht. Die neue Version ist in der Revision 10.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 15.09.12 23:28
Hallo,
eine weitere Änderung der Assemblerroutine sorgt dafür, dass sie schneller durchlaufen wird. Da der Bereich der Zufallszahlen aus dem Intervall [0, abweich-1] bestimmt wird, können einige Schritte eingespart werden:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| function farbmitte(f1,f2,abweich: integer): integer; asm add eax, edx shr eax, 1 cmp ecx, 1 jbe @ohnea push eax xor edx, edx mov eax, ecx imul edx, [randseed], $08088405 inc edx mov [randseed], edx mul edx mov eax, edx pop edx add eax, edx shr ecx, 1 sub eax, ecx jc @null @ohnea: and eax, 255 cmp eax, 0 jz @null ret @null: mov eax, 1 end; |
Gesamtstand: Von ursprünglich 8,4 s je Bild nun nur noch 0,062 s auf meinem PC. Das ist 135 mal so schnell und war nur durch die Hilfe von Euch möglich. Danke.
Vielleicht schaffen wir ja noch mehr?
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: So 16.09.12 10:02
Die Größe des Programmfensters war in der vorvorigen Version laut Deiner Änderungsliste veränderbar, nun aber nicht mehr. Verpaßte ich, mir diese Version zu besorgen. Hat das einen Grund, daß diese Funktion wieder verschwand?
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 16.09.12 10:10
Delphi-Laie hat folgendes geschrieben : | Die Größe des Programmfensters war in der vorvorigen Version laut Deiner Änderungsliste veränderbar, nun aber nicht mehr. Verpaßte ich, mir diese Version zu besorgen. Hat das einen Grund, daß diese Funktion wieder verschwand? |
Tut mir leid. Ich habe wohl nicht die richtige "letzte" Version angefügt.
Ist schon in Rev 11 geändert.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Für diesen Beitrag haben gedankt: Delphi-Laie
|
|
|