AGB  ·  Datenschutz  ·  Impressum  







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

Thread will nicht synchron schwimmen?

Ein Thema von Edlmann · begonnen am 28. Okt 2011 · letzter Beitrag vom 3. Nov 2011
Antwort Antwort
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#1

AW: Thread will nicht synchron schwimmen?

  Alt 30. Okt 2011, 21:05
Der WorkerThread macht ein TParticleSystem(PSystem).Update; in dem z.B. ein Parts.Count und ein Parts.Items[x] vorkommt, und der MainThread macht ASystem.AddPartikels(OldX, OldY, Emit_SB.Position) das dazu führt, daß die Anzahl Parts sich ändert.

Das ist nur ein beispiel - und wegen dem Timer-Problem bist du evtl. noch im MainThread im Render (das auch ein Parts.Count verwendet) während der Timer schon den nächsten Thread angeworfen hat - dann krachts gleich wieder.

Gruß
Luggi
Touche, daran habe ich gar nicht gedacht...das Partikel hinzufügen sollte also auch über den Thread laufen. Soweit so gut.
Bloß fehlt mir der Ansatz, wie ich den Timer rausnehmen kann (generell, aber noch mehr im Spiel, da es eine starke Umstrukturierung fordert). Allerdings startet der Timer ja keinen Thread, sondern sagt nur dem schon laufendem Thread "Starte den nächsten Schritt" - an der Stelle sollte es also nicht krachen.
  Mit Zitat antworten Zitat
grl

Registriert seit: 5. Feb 2007
174 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Thread will nicht synchron schwimmen?

  Alt 31. Okt 2011, 10:42
...(generell, aber noch mehr im Spiel, da es eine starke Umstrukturierung fordert)
*grins* Also ich kenn kein Projekt, bei dem die Einführung von Multithreading KEINE starke Umstrukturierung erfordert.

Allerdings startet der Timer ja keinen Thread, sondern sagt nur dem schon laufendem Thread "Starte den nächsten Schritt" - an der Stelle sollte es also nicht krachen.
Naja - du stellst aber nicht sicher, daß während der Thread läuft nicht schon der nächste Timer daher kommt (was auch tatsächlich der Fall ist) - und das "kracht".

Außerdem - ich glaub da wiederhol ich mich - macht deine Implementation so generell keinen Sinn - denn ob du das in einen Thread auslagerst und dann drauf wartest oder es gleich im Hauptthread machst, macht (fast) keinen Unterschied - ganz sicher keinen in der Geschwindigkeit.

Jetzt wiederhol ich mich ganz sicher, aber:
Folgendes solltest du jetzt tun:
- überlege dir eine klare Trennung der Speicherbereiche. Daß du auf ASystem aus dem MainThread und aus dem WorkerThread zugreifst ohne das zu Synchronisieren (CriticalSection!) ist ein absolutes NoGo und wird nie funktionieren!!!
- Trenne klar, was welcher Thread machen muss und vermeide, daß einer auf den anderen warten muss - damit führst du das Konzept des Multithreading ad absurdum.
- Überlege dir klare Schnittstelle zwischen den beiden Teilen. z.B eine Liste der Partikel, aus der jeder Thread eines entnimmt, es bearbeitet (also berechnet/anzeigt) und es wieder zurückgibt. Das entnehmen und zurückgeben schützt zu mit einer CriticalSection. Damit ist sichergestellt, daß du nie zugleich auf eines zugreifst.
Alles andere ist (zumindest meiner Erfahrung nach) Murks - und da hast du nix davon.

Gruß
Luggi
  Mit Zitat antworten Zitat
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#3

AW: Thread will nicht synchron schwimmen?

  Alt 2. Nov 2011, 16:48
...(generell, aber noch mehr im Spiel, da es eine starke Umstrukturierung fordert)
*grins* Also ich kenn kein Projekt, bei dem die Einführung von Multithreading KEINE starke Umstrukturierung erfordert.

Naja - du stellst aber nicht sicher, daß während der Thread läuft nicht schon der nächste Timer daher kommt (was auch tatsächlich der Fall ist) - und das "kracht".

Außerdem - ich glaub da wiederhol ich mich - macht deine Implementation so generell keinen Sinn - denn ob du das in einen Thread auslagerst und dann drauf wartest oder es gleich im Hauptthread machst, macht (fast) keinen Unterschied - ganz sicher keinen in der Geschwindigkeit.

Jetzt wiederhol ich mich ganz sicher, aber:
Folgendes solltest du jetzt tun:
- überlege dir eine klare Trennung der Speicherbereiche. Daß du auf ASystem aus dem MainThread und aus dem WorkerThread zugreifst ohne das zu Synchronisieren (CriticalSection!) ist ein absolutes NoGo und wird nie funktionieren!!!
- Trenne klar, was welcher Thread machen muss und vermeide, daß einer auf den anderen warten muss - damit führst du das Konzept des Multithreading ad absurdum.
- Überlege dir klare Schnittstelle zwischen den beiden Teilen. z.B eine Liste der Partikel, aus der jeder Thread eines entnimmt, es bearbeitet (also berechnet/anzeigt) und es wieder zurückgibt. Das entnehmen und zurückgeben schützt zu mit einer CriticalSection. Damit ist sichergestellt, daß du nie zugleich auf eines zugreifst.
Alles andere ist (zumindest meiner Erfahrung nach) Murks - und da hast du nix davon.

Gruß
Luggi
1.) Hab ich mir leider schon gedacht dass das nicht einfach wird...
2.) Nur mal so dumm gefragt, wenn ich das ProcessMessages rauslass, dürfte doch der Timer nicht ein zweites Mal aufgerufen werden befor er fertig ist, oder denk ich da gerade falsch? Denn dann wird der VCL-Thread (der ja den nächsten Timer starten müsste) ja schlafen gelegt, bis das Partikelsystem einen Schritt weiter ist (und wenn das PSystem vor der Spiellogik fertig ist wird gar nicht erst gewartet) - Das war so mein Gedankengang hinter dieser Warteschleife...
3.) Trennung der Speicherbereiche - Wenn ich alle aufrufe auf das Partikelsystem über den Worker laufen lasse, ist das ja soweit getrennt und dann sind doch Criticalsections unnötig (oder bin ich da falsch?)
- Das Warten ist ja nur als Fallback da, damit eben für den Fall dass das Partikelsystem noch nicht fertig ist eben kurz gewartet wird (es ist ja nich so dass der VCL-Thread dann nichts zu tun hätte, das ist nur im Beispielprogramm so, mit der Spiellogik dürfte er länger beschäftigt sein als der Worker mit den Partikeln)
- Trennung etc: Nicht nötig wenn ich das schon vom Code her Trenne (nur ein Thread was überhaupt an meiner Partikelliste rumbastelt) oder nicht?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Thread will nicht synchron schwimmen?

  Alt 2. Nov 2011, 16:54
1.) Hab ich mir leider schon gedacht dass das nicht einfach wird...
2.) Nur mal so dumm gefragt, wenn ich das ProcessMessages rauslass, dürfte doch der Timer nicht ein zweites Mal aufgerufen werden befor er fertig ist, oder denk ich da gerade falsch? Denn dann wird der VCL-Thread (der ja den nächsten Timer starten müsste) ja schlafen gelegt, bis das Partikelsystem einen Schritt weiter ist (und wenn das PSystem vor der Spiellogik fertig ist wird gar nicht erst gewartet) - Das war so mein Gedankengang hinter dieser Warteschleife...
3.) Trennung der Speicherbereiche - Wenn ich alle aufrufe auf das Partikelsystem über den Worker laufen lasse, ist das ja soweit getrennt und dann sind doch Criticalsections unnötig (oder bin ich da falsch?)
- Das Warten ist ja nur als Fallback da, damit eben für den Fall dass das Partikelsystem noch nicht fertig ist eben kurz gewartet wird (es ist ja nich so dass der VCL-Thread dann nichts zu tun hätte, das ist nur im Beispielprogramm so, mit der Spiellogik dürfte er länger beschäftigt sein als der Worker mit den Partikeln)
- Trennung etc: Nicht nötig wenn ich das schon vom Code her Trenne (nur ein Thread was überhaupt an meiner Partikelliste rumbastelt) oder nicht?
Gerade das Arbeiten mit Threads nötigt einem erheblich mehr Sorgfalt ab als mit nur einem (dem MainThread).

Umsetzungen die auf der Annahme basieren "mit der Spiellogik dürfte er länger beschäftigt sein als der Worker mit den Partikeln" führen zwangsweise ins Aus (wenn nicht sofort, dann auf jeden Fall später).

Das was du machen möchtest solltest du komplett in Threads auslagern (Spiellogik, Partikel, etc.).
Der MainThread sollte nur die Anzeige regeln und die Benutzereingaben entgegennehmen.

EDIT:
BTW macht es keinen Sinn etwas in mehrere Threads auszulagern, wenn die Threads gleiche Ressourcen verwenden.

Beispiel:
Du benötigst (eine große Menge) Daten von mehreren Systemen, die über eine Leitung kommen.
Mehrere Threads werden das nicht beschleunigen können, eher wird der Thread-Overhead dieses verlangsamen

oder

Du willst umfangreiche Berechnungen durchführen. Hast du aber mehr Berechnungs-Threads als CPU-Kerne laufen, dann wird auch das langsamer anstatt schneller

aber

Du willst:
- eine Liste aller Dateien von der Festplatte sammeln (1 Thread)
- Daten von einem externen Server holen (1 Thread) - Zwischenspeicherung im RAM! sonst stören wir den Datei-Suchen-Thread
- umfangreiche Berechnungen durchführen (1 Thread pro CPU)

das wird dann mit Threads schneller, als wenn du das in einem Thread (z.B. MainThread) nacheinander abarbeiten würdest.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 2. Nov 2011 um 17:05 Uhr)
  Mit Zitat antworten Zitat
Edlmann

Registriert seit: 19. Nov 2010
212 Beiträge
 
#5

AW: Thread will nicht synchron schwimmen?

  Alt 2. Nov 2011, 17:46
Gerade das Arbeiten mit Threads nötigt einem erheblich mehr Sorgfalt ab als mit nur einem (dem MainThread).

Umsetzungen die auf der Annahme basieren "mit der Spiellogik dürfte er länger beschäftigt sein als der Worker mit den Partikeln" führen zwangsweise ins Aus (wenn nicht sofort, dann auf jeden Fall später).

Das was du machen möchtest solltest du komplett in Threads auslagern (Spiellogik, Partikel, etc.).
Der MainThread sollte nur die Anzeige regeln und die Benutzereingaben entgegennehmen.

EDIT:
BTW macht es keinen Sinn etwas in mehrere Threads auszulagern, wenn die Threads gleiche Ressourcen verwenden.

Beispiel:
Du benötigst (eine große Menge) Daten von mehreren Systemen, die über eine Leitung kommen.
Mehrere Threads werden das nicht beschleunigen können, eher wird der Thread-Overhead dieses verlangsamen

oder

Du willst umfangreiche Berechnungen durchführen. Hast du aber mehr Berechnungs-Threads als CPU-Kerne laufen, dann wird auch das langsamer anstatt schneller

aber

Du willst:
- eine Liste aller Dateien von der Festplatte sammeln (1 Thread)
- Daten von einem externen Server holen (1 Thread) - Zwischenspeicherung im RAM! sonst stören wir den Datei-Suchen-Thread
- umfangreiche Berechnungen durchführen (1 Thread pro CPU)

das wird dann mit Threads schneller, als wenn du das in einem Thread (z.B. MainThread) nacheinander abarbeiten würdest.
Soweit hab ich das Prinzip hinter den Threads schon verstanden - In der Anwendung in der ich die Threads zum laufen bekommen möchte handelt es sich wie schon gesagt um ein Spiel, was die Festplatte nur am Anfang zum Laden der Texturen beansprucht und (noch ) auf keine Downloads aus dem Internet oder so warten muss. Dadurch ist der einzige Bottleneck die CPU, da das Spiel im Moment noch als Single-Thread-Anwendung läuft beansprucht es nur einen Kern, diesen aber zu 100% - meines Verständnis nach ein typisches Szenario in dem Multi-Threading aushelfen würde

Und nur das Partikelsystem auszulagern ist auch nicht der Plan auf Dauer, das war mehr so als Versuch gedacht überhaupt mal etwas mit Threads zu machen - Mein Hauptproblem ist jedoch die vernünftige Synchronisation der Threads. Nicht die Implementierung der Threads selbst, sondern nur wie ich es hinbekomme dass mein Workerthread und der VCL-Thread (später vllt auch mehr Threads) im Gleichtakt laufen. Und da haperts halt ziemlich. Was ist dafür der Richtige Ansatz? Eigentlich doch einen Thread einmal zu erstellen und ihm dann immer neue Aufgaben zuzuteilen oder nicht? Und um diese zu synchronisieren lässt es sich doch nicht wirklich vermeiden dass der eine Thread auf den anderen wartet, sonst läuft der eine ja schneller als der andere...
  Mit Zitat antworten Zitat
grl

Registriert seit: 5. Feb 2007
174 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Thread will nicht synchron schwimmen?

  Alt 3. Nov 2011, 12:12
Sorry, war grad unterwegs, daher gibts erst jetzt eine Antwort.

Erst mal: Ich denke, es gibt noch einen weiteren Grund für Threads: und zwar einfach Abläufe sauber gegeneinander abzuschotten. Das erhöht meiner Meinung nach die Stabilität und die Transparenz (wenn auch zum Preis eines höheren Implementationsaufwandes und der Gefahr, vor lauter Threads unnötig Ressourcen im Overhead zu verpulvern!)

Und nur das Partikelsystem auszulagern ist auch nicht der Plan auf Dauer, das war mehr so als Versuch gedacht überhaupt mal etwas mit Threads zu machen - Mein Hauptproblem ist jedoch die vernünftige Synchronisation der Threads. Nicht die Implementierung der Threads selbst, sondern nur wie ich es hinbekomme dass mein Workerthread und der VCL-Thread (später vllt auch mehr Threads) im Gleichtakt laufen. Und da haperts halt ziemlich. Was ist dafür der Richtige Ansatz? Eigentlich doch einen Thread einmal zu erstellen und ihm dann immer neue Aufgaben zuzuteilen oder nicht? Und um diese zu synchronisieren lässt es sich doch nicht wirklich vermeiden dass der eine Thread auf den anderen wartet, sonst läuft der eine ja schneller als der andere...
Ich denke, da liegt der Wurm in deinem Konzept: Zu wollen, daß die im Gleichtakt laufen und Multithreading ist ein Widerspruch in sich.

Ich versuchs mal an einem Projekt von mir zu erklären:

Ich hab eine Applikation, die Daten von einem Messgerät aufzeichnet, über die Aufzeichnung einige Filter drüberrechnet und das ganze dann als Kurve auf den Schirm malt.
Da hab ich mehrere Threads:
1.) die Kommunikation: Dieser Thread holt die Daten vom Messgerät, kontrolliert ob die Übertragung korrekt war, kümmert sich sonst darum daß die Wertereihe neu angefordert wird und legt dann die übertragenen Werte in einen Puffer. Außerdem hat der Thread einen Puffer, in dem an das Gerät zu übergebende Befehle drinstehen. Die werden dann vom Thread je nach freier Zeit, Zustand des Geräts und noch ein paar anderen Einflüssen versandt.

2.) Den Filter und Speicher Thread: der schaut regelmässig, ob im Puffer vom Kommunikationsthread was drin ist. Wenn ja, übernimmt er diese Wertereihe, macht die für die Filter notwendigen Berechungen und noch ein paar andere Sachen und schreibt sie in eine Datenbank.

3.) Den Anzeige-Berechnungs-Thread: Der weiß, welcher Bereich gerade auf dem Schirm angezeigt wird, holt sich die entsprechenden Basiswerte aus der Datenbank, rechnet da die für die Anzeige notwendigen Dinge und legt das Ergebnis als Werte-Paar (X und Y Wert) wieder in einen Puffer.

und 4.) der Mainthread, der die Daten aus dem Anzeige-Berechnungs-Thread-Puffer holt und anzeigt - was aber, da es fertig gerechnete X/Y-Paare sind, extrem schnell geht.

Untereinander kommunizieren diese Threads über Messages und über die Puffer. Die Puffer sind alle über Critical sections geschützt.
Dabei ist wichtig, daß die Threads nie auf die anderen Warten. Der Kommunikations-Thread muss nur seine Puffer lesen und schreiben und wenn da nix ist, was zu tun ist, dann wartet er ein bischen und versuchts wieder. Damit ist aber jederzeit sichergestellt, daß das Messgerät seine Daten loswird, wenn es welche zu senden hat.
Der Anzeige-Berechnungs-Thread z.B. bekommt vom Mainthread nur mitgeteilt, welcher Bereich gerade angezeigt werden soll und rechnet dann so lang ein Paar nach dem anderen, bis er alle Berechnet hat - unabhängig vom Mainthread und der Anzeige - außer es kommt vom Mainthread eine Änderung des Anzeigebereichs - dann fängt er von vorne an und vergisst die alte Aufgabe.
Der Mainthread wiederum schaut im Puffer des Anzeige-Berechnungs-Threads nach, ob da was ist, was er anzeigen kann und tut das dann. Dazu wird dem Mainthread vom Anzeige-Berechnungs-Thread eine Message geschickt, wenn einige Punkte gerechnet sind, damit er sie anzeigt. Wenn der Mainthread auf diese Message nicht gleich reagiert (weil er z.B. grad ein Einstellungsfenster darstellt) dann ist das für den Anzeige-Berechnungs-Thread eigentlich komplett egal - er rechnet einfach fröhlich weiter und füllt den Puffer weiter. Wenn der Mainthread dann wieder Zeit zur Anzeige hat, dann hat er eben mehrere Punkte zum anzeigen.

War das jetzt zu kompliziert? Ich hoffe nicht.

Gruß
Luggi
  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 23:43 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