Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Optimierung durch Threads (https://www.delphipraxis.net/137321-optimierung-durch-threads.html)

uuulf 18. Jul 2009 18:25


Optimierung durch Threads
 
Hallo Delphi-Gemeinde,

ich arbeite zur Zeit an einer Software zur Ansteuerung einer IP-Kamera über deine DLL im Rahmen meines Studiums. Daraus ergibt sich für mich die Frage, ob ich mit Threads den Bildaufbau (TBitmap) beschleunigen kann. Genauer geht es hier um den parallelen Zugriff auf den Arbeitsspeicher.

Zur Erklärung:

Die DLL ruft meine Callbackfunktion auf nachdem Sie die Bilddaten in den Arbeitsspeicher geschrieben hat. Dabei übergibt diese mir eine Referenz für ein Bild.
Delphi-Quellcode:
function TCamera.Callback(image: Pointer): Integer;
var
 data: ^Byte;
begin
 //Aufruf einer DLL-Funktion
 //Nun hole ich mir für dieses Bild den Pointer auf den Arbeitsspeicher, wo die Bilddaten liegen.
 //data als Var-Parameter übergeben
  getImage(image, Pointer(data));  
end;
Anschließend beschreibe ich das TBitmap, hier der wesentliche Code

Delphi-Quellcode:
type
  TRGBTripleArray = ARRAY[WORD] OF TRGBTriple;
[..]
var
 Row_c: ^TRGBTripleArray;
[..]
bitmap := TBitmap.Create;
bitmap.PixelFormat := pf24Bit;
for j:= 0 to Bitmap.Height-1 do
begin
  Row_c := Bitmap.ScanLine[j];
  for i:= 0 to bitmap.Width-1 do
  begin
    with Row_c[i] do
    begin
      rgbtRed:= data^;
      Inc(data);
      rgbtGreen := data^;
      Inc(data);
      rgbtBlue := data^;
      Inc(data);
    end;
  end;
end;

image1.Picture.Bitmap.Assign(bitmap); //image1 = TImage
bitmap.free;
Nun der dll noch mitteilen, dass ich bereit für das nächste Bild bin
Delphi-Quellcode:
setImage(image);
Jetzt wird die Callbackfunktion erneut aufgerufen.

Jetzt zur Frage:
1. Inwiefern kann ich durch Threads zur Optimierung beitragen?
Die Idee ist die, dass die TBitmap-Bearbeitung in einem eigenen Thread abläuft. Die Callbackfunktion beinhaltet also:

getImage(image, Pointer(data));
//Thread wird gestartet: Beschreibt TBitmap(Code: s.oben)
setImage(image);

Vorteil: Der Pointer auf die Bilddaten des nächsten Bildes liegt durchweg bereit. Hier wird also Ressource "DLL" und Ressource "Arbeitsspeicher" gleichzeitig genutzt.

2. Ist es sinnvoll mehrere Threads mit den Bearbeiten des TBitmaps zu beauftragen?
Soll heißen sobald Pointer auf Bilddaten vorliegt übergebe diesen an einen "Thread-Pool".
Vorteil: Mehrere TBitmaps werden gleichzeitig beschrieben.
Gretchenfrage: "Bremsen" sie sich nicht gegenseitig aus, da der "Thread-Pool" auf der gleichen Ressource - den Arbeitsspeicher - arbeitet?

Mir ist klar, dass es im Grunde geht. Nur ist nicht die Frage ob es nebenläufig zu bearbeiten geht, sondern ob dadurch ein Performancegewinn erzielt werden kann.

Gruß und danke vorab.

Apollonius 18. Jul 2009 19:30

Re: Optimierung durch Threads
 
Wenn du mehrere Prozessoren hast, solltest du mit Threads optimieren können. Gleichzeitiger Zugriff auf den Arbeitsspeicher ist nicht relevant, weil zumindest die unteren Level der Cache-Hierarchie auf jedem Prozessor einzeln vorhanden sind. Die Frage ist nur, ob die DLL mehrere Threads verträgt - möglicherweise wird durch SetImage der Data-Zeiger wieder ungültig.

Deine Arbeit mit dem Bitmap scheint sich ja auf ein reines Kopieren der Daten zu beschränken. Bist du dir bezüglich der Reihenfolge der Bytes (erst Rot, dann Grün, dann Blau) sicher? Zumindest unter Windows ist nämlich die umgekehrte Reihenfolge üblich.

sx2008 18. Jul 2009 19:38

Re: Optimierung durch Threads
 
Die Frage ist, wer hat den Speicherbereich reserviert?
Deine Anwendung oder die DLL?
Wenn es die DLL ist, dann wird das mit der Nebenläufigkeit wohl nicht klappen,
denn die DLL wird den Speicher entweder freigeben oder für's nächste Bild benützen.

Ansonsten sehe ich in deiner Schleife zum Kopieren noch Optimierungsmöglichkeiten:
Anstatt den Zeiger Row_c über Indizierung anzusprechen, wird der Zeiger derefernziert und dann erhöht.
Delphi-Quellcode:
..
  Row_c := Bitmap.ScanLine[j];
  for i:= 0 to bitmap.Width-1 do
  begin
    with Row_c^ do
    begin
      rgbtRed:= data^;
      Inc(data);
      rgbtGreen := data^;
      Inc(data);
      rgbtBlue := data^;
      Inc(data);
    end;
    Inc(Row_c);
  end;
Das ist aber noch nicht alles.
Es sieht so aus, als ob das Layout, also die Reihenfolge der Farben R,G,B im
Bitmap und im Datenblock gleich ist.
Folgende Optimierung vermeidet die innere Schleife komplett.
Falls es funktioniert, brauchst du keine Threads mehr.
Delphi-Quellcode:
var BytePerLine : integer;
bitmap := TBitmap.Create;
bitmap.PixelFormat := pf24Bit;
..
BytePerLine := bitmap.Width*sizeof(TRGBTriple) // *3
for j:= 0 to Bitmap.Height-1 do
begin
  Row_c := Bitmap.ScanLine[j];
  Move(data^, Row_c^,BytePerLine);
end;

Apollonius 18. Jul 2009 19:40

Re: Optimierung durch Threads
 
Zitat:

Zitat von sx2008
Es sieht so aus, als ob das Layout, also die Reihenfolge der Farben R,G,B im
Bitmap und im Datenblock gleich ist.

Das hatte ich auch erst gedacht, aber im TRGBTriple kommt Blau zuerst und Rot zuletzt.

uuulf 18. Jul 2009 20:32

Re: Optimierung durch Threads
 
Vielen Dank an euch beiden.

Zitat:

Gleichzeitiger Zugriff auf den Arbeitsspeicher ist nicht relevant, weil zumindest die unteren Level der Cache-Hierarchie auf jedem Prozessor einzeln vorhanden sind.
Aha, sowas hab ich im Studium nicht gelernt.

Zitat:

Die Frage ist nur, ob die DLL mehrere Threads verträgt - möglicherweise wird durch SetImage der Data-Zeiger wieder ungültig.
Es gibt noch eine Einstellung, dass zehn image-Zeiger in der DLL gepuffert werden, somit müsste ich also auf zehn Bilddaten zugreifen und dementsprechend bis zu zehn Threads anweisen können, die die Bilder bearbeiten. Aber richtig, ich weiß noch nicht, wann er den Speicher wieder freigibt, also vielleicht doch keine Threads - Probieren geht über Studieren...
Zitat:

Die Frage ist, wer hat den Speicherbereich reserviert?
Deine Anwendung oder die DLL?
Die DLL, aber sicher gibt es noch irgendwo ne Einstellung, wo ich den selbst reservieren kann.
Zitat:

Bist du dir bezüglich der Reihenfolge der Bytes (erst Rot, dann Grün, dann Blau) sicher?
Ja bin, ich. Aber gleich mehr dazu.
Zitat:

Es sieht so aus, als ob das Layout, also die Reihenfolge der Farben R,G,B im
Bitmap und im Datenblock gleich ist.

Das hatte ich auch erst gedacht, aber im TRGBTriple kommt Blau zuerst und Rot zuletzt.
Da kam natürlich die Frage auf, ob die Kamera auch BGR statt RGB unterstützt.....und sie unterstützt es. Ja super, vielen Dank!
Code habe ich dementsprechend angepasst und funzt! Was macht man nur ohne Euch... *grübel*

xZise 18. Jul 2009 22:19

Re: Optimierung durch Threads
 
Du müsstest halt gucken, ob "SetImage" data wieder zurücksetzt. Alternativ könntest du zumindest ein Thread einsetzen, damit die Hauptanwendung nicht einfriert?

MfG
xZise


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:59 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