![]() |
MultiThreading Bei mir ca. 40x Langsamer bei IntegerBerechnu
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo,Ich habe ein mein erstes Multithreading-TestProgramm geschrieben,& es ist vieeeeeeeeeeeel zu langsam.
Ich setzte den einmal die gleiche Rechenschleife in einen Thread ein & einmal in eine Procedore.Und in meinem Programm ist die Procedur 40x Schneller! Mir ist schon klar, das die erschaffung der Threads und so, die Sache so verlangsamt. Aber auch Multithreading kann ja heutzutage effizenter eingetzt werden! Was mache ich also bei meinem Programm, wo an den Thread eine Array übergeben wird und dann auch die Array zurück! Das Programm sieht wie folgt aus unit1=>Startet SteuerTread(Hier wird alles berechnet)=>Dieser verwaltet die NebenThreads1&2 die die Berechnungen durchführen Dies ist die Procedure und Rechenschleife, das gliche wird in den Threads berechnet!
Delphi-Quellcode:
Hier der Code von meiner Threadschleife:
procedure Counten(Var Feld1:TIntegerDynArray);
Var x,y:Integer; begin for y:=0 to 13 do for x:=0 to 156 do Feld1[x]:=Feld1[x]+1*2 div 2; x:=SumInt(Feld1); end;
Code:
NebenThread1 & 2 sind Identisch!
procedure TGeldStatistikThread.ThreadDone(Sender: TObject);
begin Dec(ThreadsRunning); Dec(Fi); Case ThreadsRunning of 0:begin ThreadsRunning:=5; with TThread1.Create(Feld) do OnTerminate := ThreadDone; with TThread2.Create(Feld) do OnTerminate := ThreadDone; end; 3:begin ThreadsRunning:=2; with TThread1.Create(Feld) do OnTerminate := ThreadDone; with TThread2.Create(Feld) do OnTerminate := ThreadDone; //Dec(Listenlaenge); if Fi<0 Then begin Synchronize(Label2); ThreadsRunning:=10; end; end; end; end;
Code:
unit UnitNebenThread1;
interface uses Classes,Types,math; type TNebenThread1 = class(TThread) private Fe:TIntegerDynArray; Liste:Integer; { Private declarations } protected procedure Execute; override; procedure Counten2(Var Feld1:TIntegerDynArray); virtual; abstract; public constructor Create(Var Feld:TIntegerDynArray); end; { TThreadCounter } TThread1 = class(TNebenThread1) protected procedure Counten2(Var Feld1:TIntegerDynArray); override; end; implementation uses unit1; constructor TNebenThread1.Create(Var Feld:TIntegerDynArray); begin Fe:=Feld; FreeOnTerminate := True; inherited Create(False); end; procedure TNebenThread1.Execute; begin Counten2(Fe){ Thread-Code hier einfügen } end; procedure TThread1.Counten2(Var Feld1:TIntegerDynArray); Var x,y:Integer; begin for y:=0 to 13 do for x:=0 to 156 do Feld1[x]:=Feld1[x]+1*2 div 2; x:=SumInt(Feld1); end; end. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Zitat:
Threads sind imho für rechenintensive Operationen gedacht, nicht für 1000 kleine Divisionen ... |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Ich habe in meinem Programm eine Schleife, mit mehreren Proceduren, die ca. soviel Rechenleistung brauchen, wie hier, da ich dies 1 Mio. mal durchlaufen lassen möchte, also den Thread immer &immer wiederhole, da muss es doch möglichkeiten geben, die sache zu beschleunigen?Oder anderes gefragt,wie kann ich solhe rechnungen effizent auf 2 Prozessoren verteilen?
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hi,
was bei dir hier die ganze Performance frisst ist mit sicherheit schon mal das synchronize. Synchronisation ist super komplex und aufwändig und sollte deswegen so selten wie möglich angewendet werden. In deinem Fall könnte das dummerweise sehr häufig passieren. Das du damit dann nur auf den Faktor 40 kommst kannst du noch als ok ansehen, ginge auch schlimmer! Zudem solltest du nur einen Thread pro CPU verwenden. Sonst hast du das Problem, dass sobald der Thread gewechselt wird die Daten vom Thread1 gespeichert werden müssen, die von Thread2 geladen und Thread2 dann gestartet werden muss. Natürlich ist auch die Zeitscheibe von Thread2 irgendwann vorbei, dann geht es so weiter (im Kreis). Hast du nur einen Thread, so entfällt die Verwaltung dieser Wechsel. Wie gesagt, versuche einfach so wenig wie möglich direkt zu zeichnen. Wenn es geht, dann lager die synchronized Sachen in einen eigenen Thread aus, der dann auch mit geringerer Priorität läuft. Und unterschätze nicht die Komplexität vom Threading, einfache Tests ist hier ein gefährlicher Begriff, es schleichen sich schnell schwer zu findende Fehler ein! Und überschätze andererseits nicht den Gewinn durch Threads (nicht nur dein Programm bekommt CPU Zeit und letztlich verteilt das BS wie es möchte). Gruß Der Unwissende |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hi,
Ich würde einen oder mehrere Threads für die Berechnung erstellen und diese so lange laufen lassen, bis sie beendet sind, so hast du den Rechenaufwand für die Erstellung der Threads nur einmal. Für eine Berechnung die 0,00.. sec dauert ist ein Thread eh überflüssig. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Zitat:
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Mehrere Threads machen unter Singleprozessorsystemen wenig Sinn. Die Parallelität ist nämlich nur eine Quasi-Parallelität für den Benutz, da jeder Thread nur eine kurze Zeit die CPU zugewiesen bekommt und das Reih um geht. Eine CPU kann eben nur eine berechnung zur gleichen Zeit ausführen, da geht kein Weg drann vorbei. Will ich also folgendes ausrechnen:
Code:
Und teile das bei einer CPU auf drei Threads auf, ist der Gewinn gleich null, weil alle drei Threads trotzdem nacheinander von der CPU bedient werden. Habe ich aber drei oder vier CPUs sieht die Sache schon wieder anderes aus. Lasse ich jeden Thread auf einer CPU laufen habe ich den beabsichtigten Gewinn. Wenn man davon ausgeht, dass die gestellte Aufgabe entsprechend komplex ist und den Overhead für die Verwaltung, sowohl von der Architektur als auch vom Betriebssystem (Die Prozessoren müssen ja irgendwie zusammenarbeiten.), dann nicht mehr ins Gewicht fällt. Dies gilt natürlcih nicht für Hardware zugriffe, wenn drei Thread auf die Festplatte schreiben, ist der Gewinn auch gleich null, weil die festplatte nur einen Schreib- / Lösearm hat und solche Zugriffe also von sich aus schon keine Parallelisierung zu lassen.
x := (a+b) * (c-d) / (e+f)
Threads benutzt man dewegen nur auf Singleprozessorsystemen, damit die Hauptanwendung noch reagiert und eine Interaktion mit dem Benutzer möglich ist. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
@Luckie: das stimmt so uneingeschränkt auch nicht (oder ich unterliege da jetzt einem Denkfehler): denn habe ich eine Anwendung mit 10 Threads, dann bekommt diese ja insgesamt mehr CPU-Zeit zugewiesen wie eine Anwendung mit einem, da ja die CPU Zeit mal abgesehen von der PRiorität der Threads gleich auf alle Threads verteilt wird. Also im Endeffekt doch ein Geschwindigkeitszuwachs :gruebel:
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hallo,
Habe das Beispiel mal auf meiner AMD X2 laufen lassen. Der Multithreading Test ist bei mir 80x langsamer. Wenn man aber zum Test die Berechnungdauer der procedure "Counten" vergrößert dann ist die Multithreading Test ~1.8x schneller. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Es gibt außerdem doch auch HTT-Prozessoren und die sind auch ein Singleprozessorsystem, aber trotzdem schneller bei mehreren Threads.
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hallo,
vorab ich Schliesse zu 100%, dass Synchronize in diesem Beispiel an der Verlangsamung Schuld ist, da es bei Beiden Zeitmessungen eingesetzt wird, MUSS die Verzögerung durch diesen Befehl bei beiden Zeitmessungen gleich sein! Die Problematik der Single,Dual Prozessoren & HTT möchte ich hier Bitte nicht besprechen!!!!!!!!!!!!!!!!!! Denn diese MultiThreading Anwendung ist bei Single & Mehr Cpu's langsamer!!! Mir geht es darum, wie kann ich diese Rechenintensive Integer Anwendung beschleunigen, dass ich auf einer SingleCore CPU langsamer bin, ist klar. Mir geht es darum, wenn ich Varibalen mehrmals übergeben muss,zwischen den Threads,wie kann ich das effizent tun, wenn der Thread immer wieder angesteuert wird! Meiner Meinung nach gute Ansetze: Zitat:
Zitat:
Zitat:
Zitat:
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Zitat:
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Solange Du zwischendurch kein langsames I/O machst, bringt doch mehr als ein Thread pro CPU rein gar nichts.
Ermittle also die Anzahl der CPUs, Teile deine Aufgabe in gleich große Häppchen, sodaß eben pro CPU ein Happen übrig bleibt, verteile die Aufgaben und lehne dich zurück. Bist Du Dir sicher, das die Berechnung hinreichend optimiert wurde? Meistens liegt das Performanceproblem nicht in der Menge der Daten, sondern im Design des Algorithmus. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
@ alzaimar
Gibt es dafür ein Beispiel,mit der Übergabe der Variablen? |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Zitat:
Und weil du das 14 mal (0..13) durchläufst, kannst du gleich statt der +1 eine +14 hinschreiben und dir die äußere Schleife ersparen. Das SumInt() kannst dabei auch gleich in deine Schleife integrieren. Synchronize: Synchronize stoppt den Thread und wartet auf den Hauptthread, bis der in der Messageloop "vorbeischaut". Das kann je nach umständen recht lange dauern. Dann doch lieber mit PostMessage() an das Formular eine eigene Botschaft schicken. So wird der Thread nicht ausgebremst. |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
@JbP
Es geht hier nicht um den Sinn Der Formel, Sie soll nur als Beispiel dienen und Rechenleistung kosten! Zum Zweiten mal!!!!!! Es kann nicht an Synchronize liegen, nehmt es raus aus dem Programm und ihr werdet es merken!!!!!!!!!!!!!!!!! |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hallo,
Zitat:
Also 'mal ganz langsam zum Mitschreiben:
Zitat:
Gruß xaromz |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
@xaromz
Richtig,xaromz Synchronize stellt hier kein Problem dar. Was WILL ich, ich will das 2 Threads, die in einer Schleife immer wieder aufgerufen werden,so zügig arbeiten, dass sich bei einem Dualcoresystem der Aufwand lohnt, siehe erster Beitrag und Titel, da dieses Beispiel auch bei Dualkern-Systemen Langsamer läuft! Ohne Frage ein Problem: Ein Thread lohnt sich erst, wenn die zu leistende Arbeit auch langwierig genug ist. Sonst frisst nämlich der Overhead die Ersparnis auf Multi-Prozessor-Systemen auf. Hier ist auch das Problem dieses Beispiels zu suchen. Meine Meinung ist ja, dass das ewige erstellen zu viel Zeit kostet, dass müsste man doch um gehen können? Meine Theorie war: Den Thread erstellen Dann ab in die Schleife Werte Übergeben, abarbeiten, Werte zurückgeben, Thread anhalten, Werte übergeben, Werte abarbeiten................. Schleife zu Ende, Thread schliessen |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Moin Thomas,
Zitat:
![]() Ich habe nämlich den "bösen" verdacht, dass dies nicht automatisch geschieht, so dass sich zwei Threads eine CPU teilen, wie auf einem Einzelprozessor-System. Wie mit der Funktion genau umzugehen ist, kann ich Dir allerdings leider auch nicht sagen. :? |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hallo,
Zitat:
Abgesehen davon habe ich mir jetz doch mal Deinen Quellcode angesehen. Ein Konzept konnte ich da leider ebenso wenig entdecken wie einen einheitlichen Stil. Deine Versuche, einen Thread zu erzeugen, der dann wieder eigene Thread erzeugt, und zwar nach einem wie auch immer gearteten Schlüssel, sind irgendwie komisch :gruebel: . Statt eines akademischen Aufbaus wäre eine konkrete Anwendung besser, dann kann Dir sicher auch geholfen werden. Gruß xaromz |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Liste der Anhänge anzeigen (Anzahl: 1)
:-D Hallo, habe die letzten Tage ein bisschen daran an meinem Thread-Problem gearbeitet, um zu Erfahren ob das Verwalten von Threads aufwendiger ist als das ständige neu erstellen.
So wollte ich probeweise die Schleife in den Thread verlegen. Leider schaffe ich auch den Spass nicht, ich wollte den Thread mit Suspend anhalten und mit Resume weilterlaufen lassen,doch leider klappt dies nicht!!! Die Änderungenen: So Starte ich die beiden Thread
Delphi-Quellcode:
So ist die deklaraion:
TThread1.Create(Feld);
TThread2.Create(Feld);
Delphi-Quellcode:
Thread1:TThread1;
Thread2:TThread2;
Delphi-Quellcode:
procedure TThread1.Counten2(Var Feld1:TIntegerDynArray);
Var x,y,z:Integer; begin i:=0; for z:=0 to 150 do begin for y:=0 to 13 do for x:=0 to 156 do Feld1[x]:=Feld1[x]+1*2 div 2; x:=SumInt(Feld1); Inc(i); Thread2.Resume; Form1.Label2.Caption:=IntToStr(i); Thread1.suspend; end; Form1.Label2.Caption:=IntToStr(i); end;
Delphi-Quellcode:
Bitte nicht über den Sinn oder Unsinn lappertieren dieser beiden Codes,ich möchte hiermit erst mal das anhalten und weitermachen zwischen 2 Threads üben.Leider wird das i im ersten Thread nicht höher als 1 gezählt!Und wenn ich es nach reume auslesen will passiert gar nix.
procedure TThread2.Counten2(Var Feld1:TIntegerDynArray);
Var x,y,z:Integer; begin Thread2.suspend; for z:=0 to 150 do begin for y:=0 to 13 do for x:=0 to 156 do Feld1[x]:=Feld1[x]+1*2 div 2; x:=SumInt(Feld1); Thread1.Resume; Thread2.suspend; end; end; |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Hi,
Und da gabs keine AV :gruebel:
Delphi-Quellcode:
IMHO muss das so aussehen
Thread2.Resume;
Delphi-Quellcode:
Und auf die Variablen Thread1 und Thread2 muss dann so zugegriffen werden:
Thread1 := TThread1.Create(Feld);
Thread2 := TThread2.Create(Feld);
Delphi-Quellcode:
@all Bitte korregieren, wenn ich Mist gebaut habe.
TGeldStatistikThread.Thread2.Resume;
|
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
@C.Schoch
Da ich immer zwischen den Beiden Threas wechsle, habe ich es in die Threads eingesetzt, aber wie bekomme ich in ausserhalb des Threads mit, wenn er angehalten ist & gleichzeitig den Thread2 Starte? |
Re: MultiThreading Bei mir ca. 40x Langsamer bei IntegerBere
Das ist auch nicht das Problem, das Problem liegt IMO daran das dein Thread2.Resume in Thread1 und genauso dein Threa1.Resume in Thread2 "ungehört verpufft", da der Windows gar nicht weis wem es das Resume zurufen soll.
[edit]Du kannst auf Suspended prüfen[/edit] [edit1]Ich glaube du solltest dir mal das Tutorial "Threads mit Delphi" von Luckie anschauen (mir hats was gebracht :wink: ) ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz