![]() |
Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Hallo, ich versuche gerade mehrere Dateien zu bearbeiten. Um das ganze zu beschleunigen, versuche ich es mit Threads zu machen. Es bringt aber nur ca 1sek. Bei der Auslastung wurde auch nur ein CPU beansprucht (die andere nur ein wenig)
Delphi-Quellcode:
type
TThreadParams = packed record // Number: Integer; Dat: string; end; PThreadParams = ^TThreadParams; function Umwandler(pDateiname: Pointer): Integer; begin ... Umwandlung end; procedure TForm1.Button7Click(Sender: TObject); var DateienLst: TSearchRec; id: Cardinal; ExitCode : Cardinal; tp : TThreadParams; threadhandle: THandle; begin if FindFirst(Directory + '*.txt', faAnyFile and not faDirectory, DateienLst) = 0 then try repeat tp.Dat:= Directory+DateienLst.Name; threadhandle:= system.BeginThread(nil,0,@Umwandler,@tp,0,id); WaitForSingleObject(threadhandle, INFINITE); GetExitCodeThread(threadhandle, ExitCode); case ExitCode of IDYES: Writeln('Benutzer hat "Ja" angeklickt.'); IDNO: Writeln('Benutzer hat "Nein" angeklickt.'); end; CloseHandle(threadhandle); until FindNext(DateienLst) <> 0; finally SysUtils.FindClose(DateienLst); end; end; |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Wenn du alles nur in einem Thread machst und den Hauptthrad auch noch anhältst ist das kein Wunder.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Danke für die schnelle Antwort !
Wird durch die Schleife nicht direkt ein neues Thread aufgemacht ? |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Wenn ich das anhalten aus der Schleife hole wirds auch nicht schneller.
Delphi-Quellcode:
procedure TForm1.Button7Click(Sender: TObject);
var DateienLst: TSearchRec; id: Cardinal; ExitCode : Cardinal; tp : TThreadParams; threadhandle: THandle; begin if FindFirst(Directory + '*.txt', faAnyFile and not faDirectory, DateienLst) = 0 then try repeat tp.Dat:= Directory+DateienLst.Name; threadhandle:= system.BeginThread(nil,0,@Umwandler,@tp,0,id); until FindNext(DateienLst) <> 0; WaitForSingleObject(threadhandle, INFINITE); GetExitCodeThread(threadhandle, ExitCode); case ExitCode of IDYES: Writeln('Benutzer hat "Ja" angeklickt.'); IDNO: Writeln('Benutzer hat "Nein" angeklickt.'); end; CloseHandle(threadhandle); finally SysUtils.FindClose(DateienLst); end; end; |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Und das funktioniert mit einer Threadhandle ?
Gruß K-H |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Es dürfte auch nur das Threadhandle vom letzten Thread geschlossen werden.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Also wäre hier ein Array von Threadhandles sinnvoll ?
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Darf ich dir einen Rat geben? Lass lieber die Finger von Threads bis du weißt, was du tust.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
Eine bestehende Struktur auf Threads umzubauen ist meist ein extrem schwieriges Unterfangen - Threads zu verwenden muss nämlich schon im grundlegenden Design der Software berücksichtigt werden. Luggi |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ich verstehe auch nicht ganz, was du zu erreichen suchst oder dir erhoffst. Ist das "umwandeln" wirklich so aufwändig? Wenn ja, und das mehr oder minder gleichzeitig geschehen soll, würde ich dem Thread doch einmal mit auf den Weg geben, wie der Dateiname lauten soll und ihn dann das komplette Umwandeln, Anlegen der Datei, Reinschreiben und schließen übernehmen lassen.
Und: Wozu die WinAPI-Funktionen? Ich finde die Delphi-Klasse TThread viel sympathischer :love: |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ok, werde ich machen, kennt ihr ein paar gute Links zu dem Thema ?
Einen hab ich grad gefunden ![]() @Der schöne Günther, das habe ich ja alles gemacht in der Funktion Umwandler |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ja, genau dieses Tutorial ist auch das einzige, was ich wirklich gelesen habe :lol:
Trotzdem bin ich kurz danach auf ![]() Ich weiß nicht, was genau in deiner Threadfunktion vor sich geht, aber da Datei-Operationen auf Prozessbasis stattfinden könnte ich mir irgendwie vorstellen, dass der zweite Thread bsp. solange blockiert, bis der erste seine Datei zuende geschrieben hat. Welche Funktionen für die Dateioperationen benutzt du und in welcher Reihenfolge? |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Hallo,
eine Sache ist bei Dateioperationen grundsätzlich zu beachten: meist ist der Dateizugriff der Flaschenhals; mit parallelen Zugriffen bremst man eine Festplatte (zumindest eine klassische) eher aus als das die Gesamtoperation beschleunigt wird. Will sagen: Bevor Du Dein Programm parallelisierst, schau erst mal, wo genau die Zeit liegen bleibt. Gruß xaromz |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Also die Funktion Umwandler sieht so aus:
Delphi-Quellcode:
Ob es TProcess in Delphi gibt weiß ich nicht genau.
function Umwandler(pDateiname: Pointer): Integer;
var AProcess: TProcess; begin AProcess := TProcess.Create(nil); try AProcess.Executable := ExtractFilePath(application.ExeName)+'Umwandler.exe'; AProcess.Parameters.Add(PThreadParams(pDateiname)^.Dat); AProcess.Options := AProcess.Options + [poWaitOnExit, poNoConsole]; AProcess.Execute; finally AProcess.Free; end; end; Danke für die Antworten. |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ich bin verwirrt. Ich dachte, es geht um Threads? Entweder ist es für mich noch zu früh am Morgen, oder...
Du machst eine Reihe von Threads auf, wartest im Hauptprogramm auf die Beendigung des Threads, den du zuletzt aufgemacht hast. Der muss überhaupt nicht zwingend der letzte sein, wenn der zu Ende ist, können noch gut zehn andere laufen, obwohl sie früher gestartet wurden. Die Threads selber erstellen einen komplett neuen Prozess (!), und warten wiederum auf die Beendigung dieses. Wozu überhaupt die Threads? Du kannst diese PRozesse doch genauso gut im Hauptthread deines Programms starten lassen. Dass die Threads hier keinen Geschwindigkeitsvorteil bringen ist doch klar ;-) - Wenn es vorher schon auf mehrere Prozesse hinauslief, dann waren es vorher so oder so auch schon mehrere Threads. mfg |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Am sinnvollsten wäre alle Programme zu starten und dann zu warten bis die alle fertig sind. Das war es dann auch schon.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
Ein Lesekopf kann nicht gleichzeitig an mehreren Stellen sein. Da summieren sich die Positionierungszeiten... Wenn man regelmässig so etwas machen muss, ist bessere Hardware (SSD) oder mehrere HDDs erforderlich. Ausserdem weist man Threads verschiedenen Cores zu - wenn man welche hat... |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
1. Hinweis: Festplatten sind nicht Thread-fähig.
2. Hinweis: Um Thread-Programmierung richtig zu machen, braucht man einiges an Erfahrung. Unser Hirn kann einfach keine Parallel-Kodierung leisten. Deshalb, such dir ein gutes Beispiel. Wobei die meisten Beispiele ziemlich kümmerlich sind. |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Naja und im übrigen - wie es auch in der SQLite Docu verlinkt ist -
![]() Mavarik |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Schau dir die OmniThreadLib mal bitte an.
Mit der kann man einfacher Multithreaded programmieren. Mit einer Collection (hier die Dateinamen rein) und dem ForEach wäre dir gelaube ich ganz gut geholfen. ![]() |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Hey danke nochmal für die vielen Antworten, ich hab es jetzt mal (trotz allen bedenken) mit einem Thread-Objekt (noch etwas unfertig) gemacht. Das ganze wird so in einem Bruchteil erledigt. Hier mal der Code.
Wie gesagt noch nicht ganz fertig... Wie kann man die Zeit von dem ganzen Ablauf Messen ? Vorher habe ich das mit dem QueryPerformanceCounter gemacht in der ButtonClick Prozedur. Aber die Threads verfälchen das ganze doch ? Schneller ist es aufjedenfall, das sehe ich schon allein wie schnell der Output da ist.
Delphi-Quellcode:
type
TMyThread1 = class (TThread) private protected procedure Execute; override; public FDateienname: String; end; { MyThread1 } procedure TMyThread1.Execute; var AProcess: TProcess; begin AProcess := TProcess.Create(nil); try AProcess.Executable := ExtractFilePath(application.ExeName)+'Umwandler.exe'; AProcess.Parameters.Add(FDateienname); AProcess.Options := AProcess.Options + [poWaitOnExit, poNoConsole]; AProcess.Execute; finally AProcess.Free; end; end; procedure TForm1.Button8Click(Sender: TObject); var DateienLst: TSearchRec; Thread1: TMyThread1; begin if FindFirst(Directory + '*.txt', faAnyFile and not faDirectory, DateienLst) = 0 then try repeat Thread1:= TMyThread1.Create(True); Thread1.FDateienname:= Directory+DateienLst.Name; Thread1.Resume; until FindNext(DateienLst) <> 0; Thread1.FreeOnTerminate := True //?? finally SysUtils.FindClose(DateienLst); end; end; |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ja, der Unterschied ist jetzt, dass du nicht mehr auf Beendigung der Threads wartest. :-D
Ich weiß nicht, ob du das wirklich wolltest? |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Nein wollte ich nicht. Aber anders ist die erste Version immer abgestürzt....
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Das FreeOnTerminate gehört in die Schleife, sonst gilt es nur für die als letztes erzeugte Thread-Instanz.
Zitat:
Daß du nicht auf das Ende der jeweiligen Threads wartest, wurde ja schon gesagt. |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Stand nicht irgend wann mal in einer Delphi Docu, dass mehr als 16 Thread es langsammer machen?
Mavarik |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ja, und da steht auch drin, dass man mindestens 90MHz auf seiner CPU haben sollte wenn seine Form transparent machen möchte.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Das mit den 16 Threads hab ich auch vor kurzem irgendwo gelesen...
Ahh hier war es ![]() " Auf einem Ein-Prozessor-System stellen 16 aktive Threads die praktikable Obergrenze dar. " |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
D.h. für viele Fälle sollte man nicht mehr nehmen, es kann aber auch im Einzelfall schon bei weniger Threads zu Verlangsamung kommen. Mann sollte es mit dem Eigenen Anwendungsfall testen. |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ich höre öfter mal 1-1,5 mal Anzahl Kerne als Grenzwert, das hängt aber sicher von der Aufgabe und dem System ab.
Das Optimum ist da nur heuristisch zu ermitteln. Für jede Datei einen Thread zu Erstellen ist aber höchstwahrscheinlich der falsche Weg. Anstelle von der Anzahl der Ressourcen (Kerne, evtl. Platten/Partitionen), welche die "ideale" Anzahl von Threads bestimmen, lässt du die Anzahl der Aufgaben diese Entscheidung treffen, die damit nichts zu tun hat und vermutlich auch noch vom arglosen User vorgegeben wird. Zu viele Threads kosten Zeit für die Erstellung (wenn du keinen Pool benutzt), Zeit für die Threadwechsel und nicht zu vergessen: das Dateisystem (und das Gesamtsystem allgemein) wird auch nicht gerade effizienter, je mehr Threads darauf herumhacken. |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Gibt es einen Weg die Dauer des gesamten Vorgangs zu messen ?
Delphi-Quellcode:
Der Wert der hier raus kommt deckt sich ja nicht mit der Gesamtdauer, da die Threads ja unabhängig laufen oder ?
procedure TForm1.Button8Click(Sender: TObject);
var DateienLst: TSearchRec; Thread1: TMyThread1; //Zeittest freq: Int64; startTime: Int64; endTime: Int64; begin QueryPerformanceFrequency(freq); QueryPerformanceCounter(startTime); if FindFirst(Directory + '*.txt', faAnyFile and not faDirectory, DateienLst) = 0 then try repeat Thread1:= TMyThread1.Create(True); Thread1.FreeOnTerminate := True; Thread1.FDateienname:= Directory+DateienLst.Name; Thread1.Resume; until FindNext(DateienLst) <> 0; finally SysUtils.FindClose(DateienLst); end; QueryPerformanceCounter(endTime); ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + 'ms'); end; |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
PS: Üblicherweise reserviert Windows glaube ich eine Stack-Größe von ca 1MB pro Thread. Wenn du jetzt 100 Threads aufmachst, kostet dich das natürlich auch 100 Megabyte und mehr. Nicht, dass das heute noch jemanden stören würde, aber vor ein paar Jahren hat man das sicherlich gemerkt, wenn man mal eben 200 Threads aufgemacht hat... |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
Hast du alle diese Threads untersucht, ob diese auch aktiv sind? :roll: Zitat:
![]() ![]() |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Zitat:
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
Ok danke das werde ich mal versuchen.
|
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
für was eigentlich threads?
Starte halt deine Prozesse ohne poWaitOnExit und prüfe später ab,ob sie beendend sind. ![]() ![]() |
AW: Kein wirklicher Geschwindigkeitsvorteil durch Threads?
So hat sich doch gelohnt, also vorher waren es ca. 27sek jetzt sind es ca. 15sek. Also fast doppelt so schnell und beide Kerne sind bei voller Last für die Zeit.
Den Zeittest habe ich so gemacht:
Delphi-Quellcode:
Um die Threads zu beschränken habe ich hier diese nützliche Unit mal benutzt (
[...]
private { private declarations } procedure CountDown(Sender: TObject); public { public declarations } end; [...] { TForm1 } var GThreadCount: Integer = 0; Gfreq: Int64; GstartTime: Int64; GendTime: Int64; procedure TForm1.CountDown(Sender: TObject); //Aktion am Ende eines Threads begin Dec(GThreadCount); if ThreadCount = 0 then begin QueryPerformanceCounter(GendTime); ShowMessage('Die Routine benötigte etwa ' + IntToStr((GendTime - GstartTime) * 1000 div Gfreq) + 'ms'); end; end; procedure TForm1.Button1Click(Sender: TObject); var DateienLst: TSearchRec; Thread1: TMyThread1; begin QueryPerformanceFrequency(Gfreq); QueryPerformanceCounter(GstartTime); GThreadCount:= 0; if FindFirst(Directory + '*.txt', faAnyFile and not faDirectory, DateienLst) = 0 then try repeat Inc(GThreadCount); Thread1:= TMyThread1.Create(True); Thread1.FreeOnTerminate := True; Thread1.FDateienname:= Directory+DateienLst.Name; Thread1.OnTerminate:= @CountDown;// Prozedur die beim beenden des Threads ausgeführt wird Thread1.Resume; until FindNext(DateienLst) <> 0; finally SysUtils.FindClose(DateienLst); end; end; ![]() @creed steiger Danke für den Hinweis, ich weiß aber nicht wo ich den ExitStatus abfragen soll damit ich ihn für den Zeittest benutzen kann und kann man die Anzahl auch irgenwie begrenzen der Prozesse, ohne alzu großen Aufwand? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 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-2025 by Thomas Breitkreuz