Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Hallo Zusammen,
Ich habe ein Programm geschrieben in dem ich "Arbeiten" auf Threads aufteile, die Threads synchronisieren hier und da via Critical Sections.
Um die CPU optimal aus zu lasten erzeuge ich Pro Kern einen Thread.
Unter Linux scalliert dies auch recht Brauchbar: Bei der Verdoppelung der Threads von 2 auf 4 verringert sich die Rechenzeit von 7s auf 3s. Auf meinem Privaten Windows Rechner ebenfalls. (Beide CPU's haben 4-Cores)
Starte ich das selbe Programm nun aber auf der Arbeit dann benötigt die Berechnung egal wie viele Threads > 1 immer 9s (im Single Tread Mode 3-4s), hier habe ich einen Intel I7 mit 8 Kernen. Habe auch schon versucht sämmtliche Wartebereiche der Critical Sections zu deaktivieren, bringt alles nichts, sobald ich die mehreren Threads aktiviere bricht die Performance immer auf 9s ein (selbst wenn ich andere Aufgaben wähle die im Single Thread mode andere Zeiten haben). Die Berechneten Ergebnisse sind immer korrekt.
Ich weis das ist recht nah an Glaskugel lesen, aber habt ihr ne idee woran das liegen kann ?
Allgemein an Windows kann es nicht liegen, auf dem Privaten Rechner funktioniert es ja. Ich Tippe darauf dass mein Arbeits PC irgend ein Tool / Gruppenrichtlinie hat, bei der dieser Effekt eintritt. So ist z.B. Bereits bekannt, dass der "TOpenDialog" bei mir auf Arbeit teilweise bis zu 30s beim öffnen Braucht, weil der Virenscanner da wohl immer erst alle möglichen Anfragen beim Anzeigen der Netzlaufwerke prüft ...
Komischerweise funktioniert mein Race Condition Beispiel ( https://corpsman.de/index.php?doc=beisp ... _condition ) auch auf der Arbeit wie erwartet. Daher habe ich Aktuell noch die Hoffnung, dass es evtl. doch an meiner Implementierung liegt, aber auch hier dann die Frage warum geht es bei 2 von 3 Rechnern und beim 3. nicht
Ich habe ein Programm geschrieben in dem ich "Arbeiten" auf Threads aufteile, die Threads synchronisieren hier und da via Critical Sections.
Um die CPU optimal aus zu lasten erzeuge ich Pro Kern einen Thread.
Unter Linux scalliert dies auch recht Brauchbar: Bei der Verdoppelung der Threads von 2 auf 4 verringert sich die Rechenzeit von 7s auf 3s. Auf meinem Privaten Windows Rechner ebenfalls. (Beide CPU's haben 4-Cores)
Starte ich das selbe Programm nun aber auf der Arbeit dann benötigt die Berechnung egal wie viele Threads > 1 immer 9s (im Single Tread Mode 3-4s), hier habe ich einen Intel I7 mit 8 Kernen. Habe auch schon versucht sämmtliche Wartebereiche der Critical Sections zu deaktivieren, bringt alles nichts, sobald ich die mehreren Threads aktiviere bricht die Performance immer auf 9s ein (selbst wenn ich andere Aufgaben wähle die im Single Thread mode andere Zeiten haben). Die Berechneten Ergebnisse sind immer korrekt.
Ich weis das ist recht nah an Glaskugel lesen, aber habt ihr ne idee woran das liegen kann ?
Allgemein an Windows kann es nicht liegen, auf dem Privaten Rechner funktioniert es ja. Ich Tippe darauf dass mein Arbeits PC irgend ein Tool / Gruppenrichtlinie hat, bei der dieser Effekt eintritt. So ist z.B. Bereits bekannt, dass der "TOpenDialog" bei mir auf Arbeit teilweise bis zu 30s beim öffnen Braucht, weil der Virenscanner da wohl immer erst alle möglichen Anfragen beim Anzeigen der Netzlaufwerke prüft ...
Komischerweise funktioniert mein Race Condition Beispiel ( https://corpsman.de/index.php?doc=beisp ... _condition ) auch auf der Arbeit wie erwartet. Daher habe ich Aktuell noch die Hoffnung, dass es evtl. doch an meiner Implementierung liegt, aber auch hier dann die Frage warum geht es bei 2 von 3 Rechnern und beim 3. nicht
--
Just try it
Just try it
- af0815
- Lazarusforum e. V.
- Beiträge: 6209
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Schon mal probiert die Executionzeit des jeweiligen Thread zu messen. Damit klar wird, ist es innerhalb des Threads oder ausserhalb.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Moin,
wenn es ein Intel der aktuellen Generation ist, könnte es an der Nutzung von Performance- bzw. Effizienz-Cores liegen.
Bei ST Anwendungen wird gerne mal der Performance-Core angesteuert.
Wenn dann noch AV dazwischen geht und auf einem "kleinen" Kern landet, eventuell weil nur 2 Performance-Cores vorhanden sind, könnte das der Grund sein.
Ist aber auch nur aus meiner Glaskugel
Grüße
wenn es ein Intel der aktuellen Generation ist, könnte es an der Nutzung von Performance- bzw. Effizienz-Cores liegen.
Bei ST Anwendungen wird gerne mal der Performance-Core angesteuert.
Wenn dann noch AV dazwischen geht und auf einem "kleinen" Kern landet, eventuell weil nur 2 Performance-Cores vorhanden sind, könnte das der Grund sein.
Ist aber auch nur aus meiner Glaskugel
Grüße
-
- Lazarusforum e. V.
- Beiträge: 3158
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Das könnte man doch lösen, indem die Threads oder der ganze Prozess auf die Performance-Cores gepinnt werden?schoschy hat geschrieben: ↑Fr 18. Nov 2022, 07:44wenn es ein Intel der aktuellen Generation ist, könnte es an der Nutzung von Performance- bzw. Effizienz-Cores liegen.
Bei ST Anwendungen wird gerne mal der Performance-Core angesteuert.
Wenn dann noch AV dazwischen geht und auf einem "kleinen" Kern landet, eventuell weil nur 2 Performance-Cores vorhanden sind, könnte das der Grund sein.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
ok das mit den Performance Cores habe ich jetzt nicht direkt verstanden, aber das Zeitmessen da hätte ich echt auch drauf kommen können . Das baue ich übers we mal ein, testen werde ich es erst am Mo auf arbeit können ...
--
Just try it
Just try it
-
- Beiträge: 830
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Wie ist die volle Bezeichnung deines Prozessors?
Mit Performance Cores ist gemeint, dass es relativ aktuelle Intel Prozessoren gibt, bei denen nicht alle Cores gleichwertig sind, sondern in sogenannte Performance und Efficency Cores unterteilt sind. Letztere sind dabei etwas behaglicher als die ersteren, damit mehr Energie gespart werden kann. Wenn du nun blind so viele Threads wie Cores erzeugst, kann es sein, dass die Threads, die auf den Efficency Cores laufen, den Rest dann ausbremsen. Um zu entscheiden, ob das überhaupt zutreffen kann, ist es jedoch wichtig deinen genauen Prozessor zu wissen.
FPC Compiler Entwickler
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Also ich hab nu das ganze mal auf meinem ArbeitsPC laufen lassen:
Das Bedeutet, dass die einzelnen Threads alle jeweils 1s gebraucht haben (also wohl doch alles gut ist) und dann weitere 8s im Haupthread verplempert wurden um deren Ergebnisse zusammen zu führen -> ich also an der Falschen Stelle gesucht habe...
Lasse ich den exakt selben Code im Single Thread laufen
Zur Frage nach meiner CPU sagt mir windows folgendes:
Interessant ist der Hintere Teil: 9s(1s 1s 1s 1s)Gen 5, 1315 survivors = 44%, genetic diversity = 40, time to calculate = 9s(1s 1s 1s 1s)
Das Bedeutet, dass die einzelnen Threads alle jeweils 1s gebraucht haben (also wohl doch alles gut ist) und dann weitere 8s im Haupthread verplempert wurden um deren Ergebnisse zusammen zu führen -> ich also an der Falschen Stelle gesucht habe...
Lasse ich den exakt selben Code im Single Thread laufen
Sieht man, dass das Zusammenführen der Thread Ergebnisse in unter 1s gemacht wird (hier sogar "0s")Gen 4, 1168 survivors = 39%, genetic diversity = 40, time to calculate = 2s(2s)
Zur Frage nach meiner CPU sagt mir windows folgendes:
Möge die Suche beginnen und danke für den DenkanstoßCaption DeviceID MaxClockSpeed Name NumberOfCores Status
Intel64 Family 6 Model 140 Stepping 1 CPU0 2995 11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz 4 OK
--
Just try it
Just try it
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
So meine Zeitmessungen zeigen Ergebnisse und nun kann ich euch auch endlich mal ein bischen Code Zeigen:
Mein Code sieht im Prinzip so aus:
Der Code meiner Threads ist dabei recht simpel:
=> Anscheinend ist es wohl so, dass mein "warten" auf alle Threads nicht ideal ist, bzw auf meinem Arbeits PC katastrophal, auf Linux und meinem Privaten Windows Rechner ja wohl kein Thema..
Hat einer nen Vorschlag wie man das "richtig" besser macht ?
=> der Task der lang dauert sind in dem Fall die 7s = WaittimeGen 3, 1167 survivors = 39%, genetic diversity = 40, time to calculate = 9s(1s 1s 2s 1s[W=7s])
Mein Code sieht im Prinzip so aus:
Code: Alles auswählen
// multithreaded loop: index 0 is reserved, start at 1
// 1. die ganzen Threads mit den "Teilaufgaben" starten
i := IndivCalcDelta + 1;
For indivIndex := 0 To high(fIndivThreads) Do Begin
assert(fIndivThreads[indivIndex].IsStateIdle());
fIndivThreads[indivIndex].StartWork(i, min(i + IndivCalcDelta, p.population), SimStep);
i := i + IndivCalcDelta + 1;
End;
// 2. Der Main Thread übernimmt natürlich auch einen Teil der muss ja eh warten auf die anderen Threads
Start := GetTickCount64;
For indivIndex := 1 To IndivCalcDelta Do Begin // Das Element 0 wird ignoriert !
If (peeps[indivIndex]^.alive) Then Begin
simStepOneIndiv(peeps[indivIndex], simStep);
End;
End;
delta := delta + (GetTickCount64 - Start);
// Warten darauf, dass alle threads "fertig" sind ---------------- Hier gehen die 7s kaputt
Start := GetTickCount64();
b1 := true;
While b1 Do Begin
b1 := false;
For i := 0 To high(fIndivThreads) Do Begin
If Not fIndivThreads[i].IsStateIdle() Then Begin
CheckSynchronize(1);
b1 := true;
End;
End;
End;
waittime := waittime + (GetTickCount64 - start); // ---------- Ende hier gehen die 7s Kaputt
//..
//Ausgabe Waittime als W= und
Code: Alles auswählen
Procedure TThreadIndivs.Execute;
Var
indivIndex: Integer;
Begin
While Not Terminated Do Begin
Case fState Of
isIdle: Begin
sleep(1);
End;
isRunning: Begin
fWorkingStartTime := GetTickCount64;
// Mache die Arbeit
For indivIndex := FFirstindex To FLastIndex Do Begin
If (peeps[indivIndex]^.alive) Then Begin
simStepOneIndiv(peeps[indivIndex], fsimStep);
End;
End;
fWorkingDelta := fWorkingDelta + (GetTickCount64() - fWorkingStartTime);
fState := isIdle; // Arbeit getan, dann wieder zurück in Idle
End;
End;
End;
End;
Function TThreadIndivs.IsStateIdle: Boolean;
Begin
result := fState = IsIdle;
End;
Function TThreadIndivs.StartWork(FirstIndex, LastIndex, simStep: integer
): Boolean;
Begin
result := IsStateIdle();
If Not Result Then exit;
FFirstindex := FirstIndex;
FLastIndex := LastIndex;
fsimStep := simStep;
fState := isRunning;
End;
Hat einer nen Vorschlag wie man das "richtig" besser macht ?
--
Just try it
Just try it
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Also ich hab die WarteRoutine noch mal genauer vermessen.
So ist es schon mal deutlich schneller Anstatt 9s nur noch 5s, da der Single Thread aber dennoch nur 3s Braucht, bin ich im MultiThread immer noch 2s Langsamer als wie wenn ich es Single Threaded rechnen lasse
Dieses Warten an der Stelle dauert Minimal 0ms, maxilam 15 ms, da es aber Pro Durchlauf 300mal gemacht werden muss ergibt sich 4,5s = (300*0.015s) Warten...
[Edit]
Hier mal geschaut wie häufig welches warten vorkommt:
81 Mal 15ms
135 Mal 16ms => 3.375 Sekunden, zumindest meine Zeitmessungen scheinen alle zu stimmen.
Und So wie es aussieht arbeitet Windows in 16ms Zeitrastern, wenn ich das Gleiche auf meinem LINUX System mache, wird sich dann wahrscheinlich Zeigen, dass Linux da "feiner" auflöst, ...
Code: Alles auswählen
b1 := true;
While b1 Do Begin
b1 := false;
For i := 0 To high(fIndivThreads) Do Begin
If Not fIndivThreads[i].IsStateIdle() Then Begin
CheckSynchronize(0); // -- 1 -> 0
b1 := true;
End;
End;
End;
Dieses Warten an der Stelle dauert Minimal 0ms, maxilam 15 ms, da es aber Pro Durchlauf 300mal gemacht werden muss ergibt sich 4,5s = (300*0.015s) Warten...
[Edit]
Hier mal geschaut wie häufig welches warten vorkommt:
84 Mal ohne WartenGen 5, 1285 survivors = 43%, genetic diversity = 40, time to calculate = 4s(1s 1s 2s 1s[W=3s 0 16])
0: 84, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 81, 16: 135
81 Mal 15ms
135 Mal 16ms => 3.375 Sekunden, zumindest meine Zeitmessungen scheinen alle zu stimmen.
Und So wie es aussieht arbeitet Windows in 16ms Zeitrastern, wenn ich das Gleiche auf meinem LINUX System mache, wird sich dann wahrscheinlich Zeigen, dass Linux da "feiner" auflöst, ...
--
Just try it
Just try it
-
- Lazarusforum e. V.
- Beiträge: 3158
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Zumindest wird das für GetTickCount(64) unter Windows immer wieder kolportiert. Ggf. trifft das auch auf den Thread-Scheduler zu, sodass sobald ein Thread von der CPU genommen wird so lange bis zur nächsten Ausführung warten musst.
Die Ursache könnte also darin liegen, dass unter Windows immer das Betriebssystem für kritische Abschnitte aufgerufen wird, während unter Linux z.B. Futexe zum Einsatz kommen. Delphi hat für sehr kurze exklusive programminterne Sperren die Klasse TMonitor, die einen Spinlock implementiert und es leider noch nicht nach Free Pascal geschafft hat
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- corpsman
- Lazarusforum e. V.
- Beiträge: 1498
- Registriert: Sa 28. Feb 2009, 08:54
- OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
- CPU-Target: 64Bit
- Wohnort: Stuttgart
- Kontaktdaten:
Re: Multithreaded Programm verhällt sich auf Windows nicht immer wie erwartet..
Ok, also Ende vom Lied, Windows kriegt das einfach nicht hin..
Bzw. ich sollte schaun, dass ich meine Arbeit anders Organisiere, so dass ich weniger "Synchronisierungspunkte" habe als bisher, denn wenn mein Task ca. 8ms dauert, das warten auf die anderen Threads aber meistens 16ms ist das einfach unsinnig..
=> Eigentlich schade, aber so wie es aussieht macht das OS Paralellität in diesem Fall zu nichte ..
Bzw. ich sollte schaun, dass ich meine Arbeit anders Organisiere, so dass ich weniger "Synchronisierungspunkte" habe als bisher, denn wenn mein Task ca. 8ms dauert, das warten auf die anderen Threads aber meistens 16ms ist das einfach unsinnig..
=> Eigentlich schade, aber so wie es aussieht macht das OS Paralellität in diesem Fall zu nichte ..
--
Just try it
Just try it