Ich habe mich gefreut, bei meinem Fraktaleprogramm durch Assemblerroutinen bis zu 75%
Zeitersparnis zu erreichen.
Hier die procedure: (in frak_un1)
Den ursprünglichen Code habe ich in der Repeat-Schleife in Klammern stehenlassen.
Man kann leicht die alte Version probieren.
Für mich überraschend war, dass ich den Stack vor der Schleife laden kann, in der Schleife
die Werte im Stack halte und nachher erst den Stack poppe. Die Schleife wird u.U. bis zu
über 500 000 mal durchlaufen und da wird der Vorteil erst sichtbar. Siehe die zwei mitgelieferten Bilder, die denselben Ausschnitt zeigen.
Vorher entzippen
Compiler:
Optmization: on
Record firld alignment: on
Extended syntax: on
sonst: off
Folgender Code beinhaltet den Wesentlichen Teil der Berechnung. Für den gesamten Algorithmus bitte die ZIP-Datei entpacken.
Delphi-Quellcode:
procedure apf_beliebiger_ausschnitt;
var
m, n, i: longint;
p: PByteArray;
zwei, x, y, x_k, x1_k, y_k, y2wert, xqu, yqu, summe,
deltax, deltay: extended;
procedure laden;
asm //ST(0) ST(1) ST(2) ST(3) ST(4) ST(5) ST(6) ST(7)
fld x_k;
//x_k
fld y_k;
//y_k x_k
fld xqu;
//xqu y_k x_k
fld yqu;
//yqu xqu y_k x_k
fld y;
//y yqu xqu y_k x_k
fld x;
//x y yqu xqu y_k x_k
end;
procedure rechnen;
asm //ST(0) ST(1) ST(2) ST(3) ST(4) ST(5) ST(6) ST(7)
fmulp;
//x*y yqu xqu y_k x_k
fadd ST(0),ST(0)
//2*x*y yqu xqu y_k x_k
fsub ST(0),ST(3)
//y(neu) yqu xqu y_k x_k
fxch ST(2)
//xqu yqu y y_k x_k
fsubrp
//xqu-yqu y y_k x_k
fsub ST(0),ST(3)
//x(neu) y y_k x_k
fld ST(0)
//x x y y_k x_k
fmul ST(0),ST(1)
//xqu x y y_k x_k
fld ST(1)
//y xqu x y y_k x_k
fmul ST(0),ST(3)
//yqu xqu x y y_k x_k
fld ST(1)
//xqu yqu xqu x y y_k x_k
fadd ST(0),ST(1)
//xqu+yqu yqu xqu x y y_k x_k
fstp summe
//yqu xqu x y y_k x_k
fxch ST(1)
//xqu yqu x y y_k x_k
fxch ST(3)
//y yqu x xqu y_k x_k
fxch ST(1)
//yqu y x xqu y_k x_k
fxch ST(2)
//x y yqu xqu y_k x_k
end;
procedure poppen;
asm
fstp x
// nur Stack freigeben
fstp y
fstp yqu
fstp xqu
fstp y_k
fstp x_k
end;
begin
ausschnitt_check := true;
deltax := (c_reel2 - c_reel1)/639;
deltay := (c_imag2 - c_imag1)/479;
y_k := c_imag1 - deltay;
zwei := 2.0;
m := 0;
repeat
p := a_bild.ScanLine[m];
y_k := y_k + deltay;
x_k := c_reel1 - deltax;
for n:=0
to 639
do
begin
x1_k := x_k + deltax;
x_k := x1_k;
x := 0.0;
y := 0.0;
xqu := 0.0;
yqu := 0.0;
color := 0;
laden;
repeat
{
y:=zwei*x*y-y_k;
x:=xqu-yqu-x_k;
xqu:=x*x;
yqu:=y*y;
summe:=xqu+yqu;
}
rechnen;
inc(color);
until (summe > maxsum)
or (color = colormax);
poppen;
if form7.checkbox6.checked
then
begin
if (color >= colormin)
or (color = colormax)
then
begin
i := 3*n;
p[i] := farbe_blau;
p[i+1] := farbe_gruen;
p[i+2] := farbe_rot;
form7.canvas.pixels[n,m] := farben;
end;
end
else
begin
if (color <= colormin)
or (color = colormax)
then
begin
i := 3*n;
p[i] := farbe_blau;
p[i+1] := farbe_gruen;
p[i+2] := farbe_rot;
form7.canvas.pixels[n,m] := farben;
end;
end;
end;
m := succ(m);
Application.processMessages
until (m = 840)
or Ende;
daten_aktualisieren(werte_apf_alt);
BitBlt(bild_apf.canvas.handle, 0, 0, 640, 480,
a_bild.canvas.handle, 0, 0, SRCCOPY);
end;
Arno
[edit=Chakotay1308]Code-Style angepasst und Hinweise angefügt. Mfg, Chakotay1308[/edit]