Autor Beitrag
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 12.09.12 18:38 
Hallo Horst_H,
user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
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
ausblenden 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
ausblenden 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. :nixweiss:
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.
ausblenden 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. :bawling:

Nachtrag 2: Ich hab es durch Versuch und Irrtum!
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 12.09.12 21:29 
Hallo,
meine ASM-Versuche machen ja richtig Spaß. :rofl: Ich habe die alte farbmitte-Prozedur
ausblenden 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 2mod 256);
    end;

durch
ausblenden 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
//      mov ecx, 256
//      div ecx
//      mov 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
ausblenden Delphi-Quelltext
1:
and eax, 255					

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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.
ausblenden volle Höhe 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:
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 // all non-used bitmap palette entries equals the first entry
      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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 13.09.12 13:47 
Hallo Horst_H,
user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
Wie wäre ein Test, wieviel canvas.pixels ausmacht?
Also in der procedure fenster alle
bitmap.canvas.Pixels[xe,ym]:=???;
auszukommentieren.

Geniale Idee :zustimm: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 13.09.12 13:57 
user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 13.09.12 14:19 
Hall Tranx,
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Do 13.09.12 15:51 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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 :oops:

Jetzt erstellt das Programm ratz-fatz in knapp 0,07 Sekunden eine neue Darstellung.
Die Zeile
ausblenden Delphi-Quelltext
1:
 if anzahl mod 50000 = 0 then application.processmessages;					

kann man sich sparen.Nur echte Gamer sind so schnell.
Statt
ausblenden Delphi-Quelltext
1:
2:
3:
anzahl mod 50000 = 0 then
lieber etwas wie 
anzahl AND ( (1 shl 16) - 1) = 0 // AND 65535 == Mod 65536

Mein AMD dividiert ungern.
Gruß Horst.
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 13.09.12 18:02 
Hallo Gammatester,
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
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.
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
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
ausblenden 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       //(f1+f2) div 2
         shr eax, 1
         push eax           //(f1+f2) div 2 speichern
         xor eax, eax       //Initialisierung auf 0 bis abweich
         mov edx, ecx
         push eax           //Zufallsgenerator
         xchg eax, edx
         sub eax, edx
         imul edx, [randseed], $08088405
         inc edx
         mov [randseed], edx
         mul edx
         pop eax
         add eax, edx       //in eax steht zufallswert [0,abweich-1] , getestet!!!
         shr ecx, 1         //abweich div 2
         sub eax, ecx       //subtraktion abweich div 2
         pop edx            //(f1+f2) div 2 zurückholen
         add eax, edx       //Addition (f1+f2) div 2
         and eax, 255       //mod 256
         cmp eax, 0         //Test auf größer Null
         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
ausblenden 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 2mod 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,
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
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).
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Fr 14.09.12 23:52 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden 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       //subtraktion abweich div 2
         pop edx            //(f1+f2) div 2 zurückholen
         add eax, edx       //Addition (f1+f2) div 2
         and eax, 255       //mod 256
         cmp eax, 0         //Test auf größer Null
         jna @null
         ret
         @null: mov eax, 1
       end;



Ich hätte da eine winzige Optimierung anzubieten, was diesen Assemblerteil angeht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function farbmitte(f1,f2,abweich: integer): integer;
    asm
         [...]
         sub eax, ecx       //subtraktion abweich div 2
         pop edx            //(f1+f2) div 2 zurückholen
         add eax, edx       //Addition (f1+f2) div 2
         and eax,255        //AND setzt bereits Zeroflag, wenn EAX 0 wird
         cmovnz eax,1       //Conditional Move
         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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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:
ausblenden volle Höhe 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:
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);

          //rekursive Konstruktion
          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;
// Neue Version mit fruehzeitigem Abbruch und nur den notwendigen Berechnungen
    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) AND Not(bDy)  then 
          if Not(bDx OR bDy)  then 
            exit;

          inc(AnzahlBerechnungen);    
          //Diamond-Square-Algorithmus
 
          xm:=(xa+xe) div 2;
          ym:=(ya+ye) div 2;
          IF xa = 0 then
            inc(farbtupfer);    
          IF ya = 0 then
            inc(farbtupfer);
          
{   Nur bei dy > 1 ergibt sich ein neues ym           
        farbe3:=farbmitte(pixel2,pixel4,dy);
          farbfeld[xe,ym]:=farbe3;
}

          IF bdy then
            inc(farbtupfer,1);
            
{  Nur bei dx > 1 ergibt sich ein neues xm
         farbe4:=farbmitte(pixel3,pixel4,dx);
          farbfeld[xm,ye]:=farbe4;        
}

          IF bdx then
            inc(farbtupfer);
{Entsprechendes hier
          farbe5:=((farbe1+farbe3) div 2 + (farbe2+farbe4) div 2) div 2;
          farbfeld[xm,ym]:=farbe5;          
}

          IF bdx AND bdy then
            inc(farbtupfer);

          //rekursive Konstruktion
          
          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//Startwerte   

  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//Startwerte   
  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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 15.09.12 08:55 
Hallo OlafSt,
user profile iconOlafSt hat folgendes geschrieben Zum zitierten Posting springen:
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
ausblenden 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
ausblenden 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
ausblenden Delphi-Quelltext
1:
 if (xe-xa<=1and (ye-ya<=1then 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 15.09.12 12:06 
Hallo,
ich hab's gefunden und bin etwas stolz auf mich. :P
Die Assembler-Routine farbmitte läuft einwandfrei:
ausblenden 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;
    //max(1,((f1+f2) div 2 + random(abweich) - abweich div 2) mod 256)
    asm
         add eax, edx       //(f1+f2) div 2
         shr eax, 1
         cmp ecx, 1
         jbe @ohnea         //abweich < 2
         push eax           //(f1+f2) div 2 speichern
         xor eax, eax       //Initialisierung auf 0 bis abweich
         mov edx, ecx
         push eax           //Zufallsgenerator
         xchg eax, edx
         sub eax, edx
         imul edx, [randseed], $08088405
         inc edx
         mov [randseed], edx
         mul edx
         pop eax
         add eax, edx       //in eax steht zufallswert [0,abweich-1]
         pop edx            //(f1+f2) div 2 zurückholen
         add eax, edx       //Addition (f1+f2) div 2
         shr ecx, 1         //abweich div 2
         sub eax, ecx       //subtraktion abweich div 2
         jc @null
         @ohnea: and eax, 255       //mod 256
         cmp eax, 0         //Test auf Null
         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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: 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:
ausblenden 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;
    //max(1,((f1+f2) div 2 + random(abweich) - abweich div 2) mod 256)
    asm
         add eax, edx       //(f1+f2) div 2
         shr eax, 1
         cmp ecx, 1
         jbe @ohnea         //abweich < 2
         push eax           //(f1+f2) div 2 speichern
         xor edx, edx       //Zufallsgenerator
         mov eax, ecx       //Initialisierung auf 0 bis abweich
         imul edx, [randseed], $08088405
         inc edx
         mov [randseed], edx
         mul edx
         mov eax, edx       //in eax steht zufallswert [0,abweich-1]
         pop edx            //(f1+f2) div 2 zurückholen
         add eax, edx       //Addition (f1+f2) div 2
         shr ecx, 1         //abweich div 2
         sub eax, ecx       //subtraktion abweich div 2
         jc @null
         @ohnea: and eax, 255       //mod 256
         cmp eax, 0         //Test auf Null
         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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: So 16.09.12 10:10 
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
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