Autor Beitrag
enyaw_ecurb
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Mi 12.10.05 15:22 
Ich habe neulich eine ganz simple Mandelbrotfunktion geschrieben und wollte die dann optimieren bzw. testen. Da ich die Punkte in einem zweidimensionalen Array gespeichert hab und ich ja nur die Laufzeit der Rechnungen messen wollte hab ich die entsprechende Zeile entfernt. Als Folge darauf ist mein Code aber um ca. eine Sekunde langsamer geworden! Dabei verbraucht der Zugriff doch eigentlich Rechenzeit und die Funktion sollte schneller werden?
Für die Optimierung ist das ja eigentlich irrelevant, aber es hat mich einfach so gewundert das ich das jetzt hier poste.

Der Code:
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:
procedure Mandelbrot;
var
  counterv, counterh, counteri: integer;
  Pointv, Pointh: Double;
  Stepv, Steph: Double;
  Sizev, Sizeh: integer;
  Zreal, Zimag, tmp: Double;
  Density: integer;
  Bild: array[0..767,0..1023of Double;
begin
Sizev := 768; Sizeh := 1024;
Steph := 3 / Sizeh; Stepv := 2 / Sizev;
Pointv := 1; Density := 2000;
counterv := 0;

while counterv < Sizev do begin
    counterh := 0; Pointh := -2;
    while counterh < Sizeh do begin
         Zreal := 0; Zimag := 0; counteri := 0;
         while (counteri < Density) and
               (sqr(Zreal) + sqr(Zimag) < 4do begin
               tmp := sqr(Zreal) - sqr(Zimag) + Pointh;
               Zimag := Zreal*Zimag*2 + Pointv;
               Zreal := tmp;
               counteri := counteri+1;
         end;
         Bild[counterv, counterh] := counteri / Density; //Die entfernte Zeile
         Pointh := Pointh + Steph;
         counterh := counterh+1;
    end;
    Pointv := Pointv - Stepv;
    Counterv := counterv+1;
end;
end;


Die Zeitmessung wurde mit QueryPerformanceCounter durchgeführt und unter Delphi 5 kompiliert. Falls euch der Code oder die Variablenbezeichnungen stören...
Es geht bei meiner Frage nur um den Grund der Verlangsamung. Ich weiß selber, dass das da oben nicht so toll ist.
Also testet es am Besten mal und ich hoffe, dass einer von euch den Grund weiß und ich bedanke mich im Voraus für die Antworten.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 12.10.05 21:04 
Lach nich, bei mir verdoppelt sich die Zeit, wenn ich die Zeile rausnehme.... WENN ICH DIE ZEILE RAUSNEHME!!!
Das ist mir zu hoch :gruebel:

_________________
Na denn, dann. Bis dann, denn.
zemy
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 207

Win XP Prof.
D7
BeitragVerfasst: Mi 12.10.05 21:45 
kann eigentlich nicht sein. Müsste ein Messfehler sein... wiederhohl einfach mal deine Messungen und mach gleich 4.5 und bilde das Mittel. Dürften die Ergebnisse besser werden.

_________________
LifeIsToShortToThinkAboutTheShortness
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 12.10.05 21:53 
Würde ich auch so sehen, aber die Routine benötigt 30 Sekunden, da sind Messfehler ausgeschlossen.

Probiers doch beim nächsten Mal selbst, bevor Du solche Ratschläge gibst. :wink:
Einloggen, um Attachments anzusehen!
ManuelGS
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 173

Win XP HE, Suse Linux
D6, D7, D2005 Personal
BeitragVerfasst: Mi 12.10.05 22:22 
786.432 Arrayfelder + 786.432 FP-Operationen = viel Zeit!
Könnt ihr keine Mathe mehr? :gruebel:

_________________
"Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
Grishnak
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 221

Windows XP Home
Delphi 7 PE, Delphi 2005 PE
BeitragVerfasst: Mi 12.10.05 22:25 
Tja, würde gerne helfen, aber bei mir läuft diese Prozedur (fast) nicht!

Als VCL-Anwendung oder Consolen-Anwendung (D7) bekomme ich bei Zeile 10 ('begin') eine StackOverflow-Exception (bzw. die Consolen-Anwendung steigt einfach aus). Wenn ich Zeile 27 auskommentiere, läuft die Prozedur einwandfrei durch! Ich denke, mein Delphi "merkt", dass das Bild-Array nicht benutzt wird und lässt es komplett weg.

Das Problem liegt bestimmt an diesem Bild-Array (immerhin 6 MB groß)!

_________________
Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
ManuelGS
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 173

Win XP HE, Suse Linux
D6, D7, D2005 Personal
BeitragVerfasst: Mi 12.10.05 22:34 
wenn du die variabel global deklarierst geht es. bei mir braucht das ganze mit oder ohne speichern in "bild" etwa 25,5s.

_________________
"Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
Grishnak
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 221

Windows XP Home
Delphi 7 PE, Delphi 2005 PE
BeitragVerfasst: Mi 12.10.05 22:38 
@enyaw_ecurb & alzaimar: Läuft die Prozedur bei euch auch nur, wenn ihr Bild[] global deklariert? Oder läuft es genau so wie oben geposted? Und wenn ja, warum läuft es bei mir nicht?

_________________
Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 12.10.05 22:46 
Ich musste die Bild-Variable global deklarieren.
MIT Zuweisung zum Array werden 15 Sekunden benötigt, OHNE Zuweisung 28 Sekunden.

_________________
Na denn, dann. Bis dann, denn.
Grishnak
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 221

Windows XP Home
Delphi 7 PE, Delphi 2005 PE
BeitragVerfasst: Mi 12.10.05 23:04 
Ich habe "Bild: array[0..767,0..1023] of Double;" durch "Bild: array of array of Double" ersetzt, es am Anfang der Prozedur per "SetLength(Bild, 768, 1024)" die Größe angepasst und es am Schluss der Prozedur mit "SetLength(Bild, 0)" gelöscht. Ergebnis: Mit und ohne Zuweisung (Zeile 27) braucht es nun bei mir 17-18 Sekunden!

_________________
Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
enyaw_ecurb Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Mi 12.10.05 23:09 
Tja, da ist mir wohl ein Fehler unterlaufen, sorry. Ich hatte die Arraydeklaration wegen der Übersichtlichkeit in die Prozedur gepackt und es natürlich ausprobiert. Leider war die Zeile von den letzten Tests noch auskommentiert...

Also ich bin auf jeden Fall vollends verwirrt denn ich hab noch ein paar Durchläufe
gemacht. Dazu hab ich die Variable Density, die innerste Iteration, auf verschiedene
Werte gestellt, die Funktion 50 mal durchlaufen lassen und den Durchschnittswert errechnet.

Density: Ohne Zeile, Mit Zeile
1: 45ms, 52ms
10: 238ms, 321ms
100: 1491ms, 1294ms

Insofern völlig normal und entgegen dem Verhalten, das ich beschrieben hab. :oops:
Wenn ich aber dann Density auf 1000 oder höher stelle - ja, ich habs keine 50 mal durchlaufen lassen, sondern nur 10 - bekomme ich falsche Durchschnittswerte, die Funktion brauch viel länger als normal, usw. Wenn ichs aber nur zwei- oder dreimal mache ist sie mit der Zeile wieder schneller. ARRGHHH :evil:
Ich hab heute auf jeden Fall nicht mehr die Nerven das nochmal zu prüfen, aber ich denke das Ganze wird schon irgendwie an einem Messfehler liegen oder zumindest damit zu tun haben.

Gute Nacht und danke für die Antworten.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 13.10.05 13:33 
Hallo,

bei meinem Duron 800 tut sich da fast nichts, ob mit oder ohne diese Zeile.
Es bleiben ja nur 768*1024 Zugriffe, aber 400.576.414 Berechnungen.
Vielleicht sind modernere CPU's da ein bisschen zickiger.

Gruss Horst
P.S.
Ich habe auch Konstanten verwendet, statt Variablen, falls das einen Unterschied macht.
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:
const
 Sizev = 768;
 Sizeh = 1024;

var
  Bild: array[0..SizeV-1,0..SizeH-1of Double;
{$R *.dfm}
function Mandelbrot:int64;
var
  counterv, counterh, counteri: integer;
  Pointv, Pointh: Double;
  Stepv, Steph: Double;
  Zreal, Zimag, tmp: Double;
  Density: integer;

begin
result :=0;
Steph := 3 / Sizeh;
Stepv := 2 / Sizev;
Pointv := 1;
Density := 2000;
counterv := 0;

while counterv < Sizev do
  begin
  counterh := 0;
  Pointh := -2;
  while counterh < Sizeh do
    begin
    Zreal := 0;
    Zimag := 0;
    counteri := 0;
    while (counteri < Density) and(sqr(Zreal) + sqr(Zimag) < 4do
      begin
      tmp := sqr(Zreal) - sqr(Zimag) + Pointh;
      Zimag := Zreal*Zimag*2 + Pointv;
      Zreal := tmp;
      inc(Counteri);
      inc(result)
      end;
    Bild[counterv, counterh] := counteri / Density; //Die entfernte Zeile
    Pointh := Pointh + Steph;
    counterh := counterh+1;
    end;
  Pointv := Pointv - Stepv;
  Counterv := counterv+1;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t1,t0,f,Erg : int64;
begin
  queryperformancefrequency(f);
  queryperformancecounter(t0);
  Erg :=Mandelbrot;
  queryperformancecounter(t1);
  Button1.Caption := Format('Zeit %10.5f %20d',[(t1-t0)/f,Erg]);
end;