AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Fraktalrechner mit Thread(s) macht Unfug

Ein Thema von everdream · begonnen am 18. Apr 2008 · letzter Beitrag vom 18. Apr 2008
Antwort Antwort
Benutzerbild von everdream
everdream

Registriert seit: 22. Feb 2007
Ort: Hiddenhausen
192 Beiträge
 
Delphi 2005 Personal
 
#1

Fraktalrechner mit Thread(s) macht Unfug

  Alt 18. Apr 2008, 00:12
Hallo,

ich wollte meinen kleinen Fraktal-Visualisierer auf Threads umstellen, um meinen DualCore nutzen zu können. Das Programm erstellt eine Reihe von Bitmaps, die man dann zu einem Video konvertieren kann. Am Ende hat mein ein Video, das in das Mandelbrot Fraktal hineinzoomt.
Ich habe mich an das Tutorial "Threads mit Delphi" von Luckie gehalten, aber schon bei einem Thread gibt es große Schwierigkeiten. Folgendes ist mir schon untergekommen (ohne, dass ich zwischendurch das Programm neu kompiliert oder etwas im Code geändert habe):

• Das Bild steht still, keine Zoombewegung
• Das Bild wird nur am linken Rand etwas bemalt, der Rest bleibt weiß
• Es gibt eine Exception "Ungültiges Handle", was sich auf das Thread Handle bezieht
• Es läuft alles ganz normal

Diese Dinge treten meißtens irgendwann während der Berechnung auf (jedoch relativ schnell, nach einigen Dutzend Frames), können aber auch mal beim ersten Durchlauf erscheinen.

Ich muss viele Parameter an den Thread übergeben, habe es aber wie im Tutorial beschrieben gemacht. Am besten zeige ich mal den betreffenden Code:
Delphi-Quellcode:
type
  TThreadParams = packed record
  public
    Center_x, Center_y, Range_x, Range_y, dx, dy, MaxValue: extended;
    MaxIterations, Counter: integer;
    Bitmap: TBitmap;
  end;

  PThreadParams = ^TThreadParams;

//[...]

procedure TMandelbrotSet.SaveSetZoom;
var
  counter: integer;
  dx, dy: extended;
  Parameter: TThreadParams;
  Thread: THandle;
  ThreadID: Cardinal;
  Bitmap: TBitmap;
begin
  // Parameter initialisieren
  counter:=1;
  Bitmap:=TBitmap.Create;
  Bitmap.Width:=x; // Konstante
  Bitmap.Height:=y; // Konstante
  Range_x:=4;
  Range_y:=3;
  dx:=Range_x / x;
  dy:=Range_y / y;
  maxIterations:=200;

  // Konstante Parameter einmalig setzen (gehören zu TMandelbrotSet (privat) und sind initialisiert)
  Parameter.MaxValue:=MaxValue;
  Parameter.Center_x:=Center_x;
  Parameter.Center_y:=Center_y;
  Parameter.Bitmap:=Bitmap;

  // Prozesspriorität verringern, um andere Programme nicht zu "stören"
  SetPriorityClass(GetCurrentProcess, IDLE_PRIORITY_CLASS);

  while (Range_x>0.0000001) do
  begin
    // Aktuelle Parameter für Thread übernehmen
    Parameter.Range_x:=Range_x;
    Parameter.Range_y:=Range_y;
    Parameter.dx:=dx;
    Parameter.dy:=dy;
    Parameter.MaxIterations:=MaxIterations;
    Parameter.Counter:=Counter;

    // Thread erzeugen
    Thread := BeginThread(nil, 0, @ThreadFunc, @Parameter, CREATE_SUSPENDED, ThreadID);
    // Threadpriorität und gewünschten Prozessor setzen
    SetThreadPriority(Thread, THREAD_PRIORITY_IDLE);
    SetThreadIdealProcessor(Thread, 0);
    // Thread starten
    ResumeThread(Thread);

    // Parameter für nächsten Frame setzen:
    Range_x:=Range_x*0.95;
    Range_y:=Range_y*0.95;
    dx:=Range_x / x;
    dy:=Range_y / y;
    maxIterations:=round(200+(Counter*1.2));
    Inc(Counter);

    Application.ProcessMessages;

    // Auf Thread warten
    WaitForSingleObject(Thread, INFINITE);
    CloseHandle(Thread);
  end;
  
  Bitmap.Free;

  // Priorität auf Standard zurücksetzen
  SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS);
end;
und die ThreadFunc:
Delphi-Quellcode:
function ThreadFunc(Params: PThreadParams): Cardinal;
var
  fBitmap: TBitmap;

  fMaxIterations, fIterations, fAverage, fPxl_x,
  fPxl_y, fi, fj, fcounter: integer;

  fx0, fx1, fy1, fCenter_x, fCenter_y, fRange_x, fRange_y,
  fRealC, fImagC, fMaxValue, fdx, fdy: extended;

  fr, fg, fb, ffulls: byte;
begin
  // Parameter auslesen
  fBitmap:=PThreadParams(Params)^.Bitmap;
  fdx:=PThreadParams(Params)^.dx;
  fdy:=PThreadParams(Params)^.dy;
  fCenter_x:=PThreadParams(Params)^.Center_x;
  fCenter_y:=PThreadParams(Params)^.Center_y;
  fRange_x:=PThreadParams(Params)^.Range_x;
  fRange_y:=PThreadParams(Params)^.Range_y;
  fMaxIterations:=PThreadParams(Params)^.MaxIterations;
  fMaxValue:=PThreadParams(Params)^.MaxValue;
  fCounter:=PThreadParams(Params)^.Counter;

  // Berechnung [...]

  Result:=0;
end;
Die Berechnung an sich habe ich nicht verändert. Sie hat vorher immer ohne Probleme funktioniert und daher gehe ich vorerst davon aus, dass es an den Parametern liegt.

Ich freue mich über Ratschläge!
Max
"Das Ziel ist im Weg!"
  Mit Zitat antworten Zitat
Benutzerbild von RavenIV
RavenIV

Registriert seit: 12. Jan 2005
Ort: Waldshut-Tiengen
2.875 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Fraktalrechner mit Threads hat Spaß

  Alt 18. Apr 2008, 08:55
Ich kann Dir zwar nicht weiterhelfen, aber ich suche schon lange einen Fraktalgenerator, der Filme produzieren kann.
Also halte mich bitte auf dem Laufenden.
Klaus E.
Linux - das längste Text-Adventure aller Zeiten...
Wer nie Linux mit dem vi konfiguriert hat, der hat am Leben vorbei geklickt.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.685 Beiträge
 
Delphi 2007 Enterprise
 
#3

Re: Fraktalrechner mit Threads hat Spaß

  Alt 18. Apr 2008, 14:37
Wie wäre es mit dem Quasi-Standard auf diesem Gebiet: ChaosPro?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von everdream
everdream

Registriert seit: 22. Feb 2007
Ort: Hiddenhausen
192 Beiträge
 
Delphi 2005 Personal
 
#4

Re: Fraktalrechner mit Threads hat Spaß

  Alt 18. Apr 2008, 16:41
Zitat von RavenIV:
halte mich bitte auf dem Laufenden.
Kann ich machen, momentan ist hat man aber noch so gut wie keine "Freiheiten". Man kann mit WASD + EQ(Zoom) auf dem Mandelbrot-Fraktal navigieren und wenn man etwas gefunden hat, was einem gefällt, dann werden die aktuelle MIttelpunktkoordinaten gespeichert und damit ein Zoom erstellt. Auch bei den Farben habe ich bis jetzt erst eine Variante.

So back2topic:
Gibts jemanden, der eine Idee hat, was ich falsch mache?
Max
"Das Ziel ist im Weg!"
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

Re: Fraktalrechner mit Thread(s) macht Unfug

  Alt 18. Apr 2008, 18:08
Wieso verwendest du die Klasse TThread nicht ?
Diese Klasse vergrössert dein Programm nur unwesentlich, vereinfacht aber das Programieren.
In dieser von TThread abgeleiteten Klasse könntest du z.B. zwei Prozeduren vorsehen:
die eine berechnet die Mandelbrot Menge richtig und die andere zeichnet nur ein einfaches Karomuster.
Zum Testen rufst du dann die Prozedure für das Karomuster auf und kannst so feststellen, ob dein gesamter Überbau richtig funktioniert.
An deiner Stelle würde ich auch alle Stellen zur Manipulation von Thread Prioritäten auskommentieren.
Dieser Feinschliff kommt erst dann, wenn alles funktioniert.

Und warum verwendest du einen packed record ?

Nachtrag:
du hast nur eine Variable Parameter: TThreadParams.
Diese gibst du als Zeiger mehreren Threads als Imput.
Wenn du die Parameter für den 2. Thread setzt, änderst du damit die Parameter für den 1. Thread gleich mit.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von everdream
everdream

Registriert seit: 22. Feb 2007
Ort: Hiddenhausen
192 Beiträge
 
Delphi 2005 Personal
 
#6

Re: Fraktalrechner mit Thread(s) macht Unfug

  Alt 18. Apr 2008, 18:19
Zitat von shmia:
Wieso verwendest du die Klasse TThread nicht ?
Und warum verwendest du einen packed record ?
Wie gesagt, habe mich erstmal an das Tutorial gehalten.

Zitat von shmia:
du hast nur eine Variable Parameter: TThreadParams.
Diese gibst du als Zeiger mehreren Threads als Imput.
Wenn du die Parameter für den 2. Thread setzt, änderst du damit die Parameter für den 1. Thread gleich mit.
Im Code oben rufe ich ja auch nur einen Thread auf. Bei den Versuchen mit 2 Threads, hatte ich natürlich auch jede Varaible doppelt (Parameter1, Parameter2: TThreadParams). Aber ich brauche ja erstmal nicht mit 2 Threads rumzufuchteln, wenn einer schon nicht das macht, was er soll.

Werde mir TThread jetzt mal angucken. Kann ich damit einen Thread wie eine Objektinstanz verwenden?
Max
"Das Ziel ist im Weg!"
  Mit Zitat antworten Zitat
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#7

Re: Fraktalrechner mit Thread(s) macht Unfug

  Alt 18. Apr 2008, 18:30
Zitat von everdream:
Kann ich damit einen Thread wie eine Objektinstanz verwenden?
Ja und nein...
Du haste eine Klasse von TThread abgeleitet. Diese hat die methode Execute, die gethreadet läuft. Du erstellst mit Create eine Instanz, wenn du dem Constructor True mitgibst ist der Thread angehalten, bei False wird gleich dannach der Thread gestartet! Mit MyThread.Resume kannst du den angehaltenen Thread starten.
Das besondere an der Klasse ist das sie sich selbst freigeben kann wenn sie fertig ist. Mit dem Property FreeOnTerminate kannst du das festlegen, default ist True.

Zu beachten ist das du keine Zugriffe auf VCL-Objekte vom Thread aus (also aus der Methode Execute) machst. Ich vermute mal das das auch dein jetziges Problem ist. Diese Fehler sind nur sehr schwer zu finden und können sogar erst zeitlich versetzt auftreten.
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Benutzerbild von everdream
everdream

Registriert seit: 22. Feb 2007
Ort: Hiddenhausen
192 Beiträge
 
Delphi 2005 Personal
 
#8

Re: Fraktalrechner mit Thread(s) macht Unfug

  Alt 18. Apr 2008, 18:41
Okay, dann ist es in etwa so, wie ich es aus einigen Beispielen grade herausinterpretiert habe. Scheint ja echt ziemlich simpel zu sein.

Ich greife in meinem jetzigen Thread nur auf Parameter in Form von Zahlenwerten und einer Bitmap zu. Wie dem auch sei: ich werde mein Programm mal auf TThread umstricken und sehen, ob ich damit weniger Schwierigkeiten habe.

Vielen Dank für die Tipps

edit: Okay, es funktioniert schon besser, allerdings tauchen ab und an immernoch unvollständig bemalte Bitmaps auf -.-
Da muss ich wohl noch weiter suchen.
Max
"Das Ziel ist im Weg!"
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz