Autor |
Beitrag |
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Sa 20.06.15 23:16
Hallo,
in der Rechenaufgabe 3*5+7*11 könnt man ja die Aufgabe 3*5 und 7*11 getrennten Threads übergeben, die würden dann auf einem Multicore-Prozessor parallel ausgeführt. Der Hauptthread wartet auf die beiden Unter-Threads und führt dann die Addition aus. Das wäre die schnellste Möglichkeit für die Berechnung - wenn nicht die Threadverwaltung wäre!!!!!
Meine Frage also: Hat jemand einen Richtwert, eine Faustformel oder so, ab welcher "Größe" zweier Teilaufgaben (3*5 und 7*11 im Beispiel) eine Aufteilung auf Threads zu einem Geschwindigkeitsgewinn führt?
(Für Google fehlten mir irgendwie die Suchworte.) Falls niemand antwortet, mache ich vermutlich Ende der Woche mal systematische Versuche und poste die Ergebnisse hier.
Viele Grüße
GuaAck
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 21.06.15 07:43
Ein wenig mehr muss es schon sein, damit die Threads einen Geschwindigkeitsvorteil bringen, das weißt du ja wohl schon.
Grob geschätzt wird es in den meisten Fällen nicht viel bringen weniger als 200 Millisekunden Ausführungszeit in einen eigenen Thread zu packen. (Aber der Wert ist natürlich vom Prozessor und von den Aufgaben abhängig, die der Thread ausführt. Das ist kein empirischer Wert, sondern eine Schätzung von mir.)
Anders sieht es aus, wenn der Thread die ganze Zeit läuft und viele einzelne kleine Aufgaben einfach der Reihe nach abarbeitet, da machen ggf. auch kleinere Aufgaben Sinn.
Geht es um einen konkreten Fall? Da ließe sich eher etwas Konkretes sagen.
|
|
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Di 23.06.15 23:33
Hallo,
falls es interessiert (und Jaenicke interessiert es bestimmt), ich habe mal ein paar Versuche gemacht. Vorab: Bei einer 4 GHz-CPU lohnt es, parallel zu lösende Teilaufgaben, die je 30 Mikrosekunden oder länger dauern, in Threads unterzubringen, damit sie von mehreren Kernen der CPU parallel verarbeitet werden können.
Zu meinem Test (Zwei primitive Zufallszahlen-Generatoren):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| FOR i := 1 TO anz_schleifena DO BEGIN FOR j := 1 TO anz_schleifeni DO Seed1 := (a * Seed1 + C) MOD m; FOR j := 1 TO anz_schleifeni DO Seed2 := (a * Seed2 + C) MOD m; summe := (summe + Seed1 + Seed2) MOD m; END; |
Ich habe immer gesetzt "anz_schleifeni*anz_schleifena=10^8", somit ist die Rechenarbeit immer fast gleich. Rechenzeit ohne Aufteilung auf Threads ist tatsächlich immer gleich. Die Summenbildung fällt nicht ins Gewicht.
Die beiden inneren Schleifen kann man offensichtlich parallel bearbeiten. Dafür habe ich zum Vergleich zwei Threads erzeugt, die genau die innere Schleife enthalten. Die Threads starte ich per Event, warte auf die Fertigmeldung über eine Zähl-Semaphore und bilde dann die Summe.
Bei anz_schleifeni > 10000 ergibt sich damit etwa die halbe Rechenzeit gegenüber dem dargestellten Code.
Bei anz_schleifeni = 1000 wird etwa 70 % der Rechenzeit des dargestelten Codes gebraucht, bei 100 schon mehr als das Doppelte!
Ohne Threads braucht mein Rechner für 10^8 Durchläufe 6,3 s, die einmalige Berechnung eines Seedx (incl. FOR..) also so etwa 30 ns; in einer Schleife bis 1000 sind das also die 30 us.
Wer will, mein Testprogramm als ZIP im Anhang.
Viele Grüße
GuaAck
Einloggen, um Attachments anzusehen!
|
|
Horst_H
Beiträge: 1653
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 25.06.15 09:55
Hallo,
die Daten von GuaAck passen bei mir mit Win7.
Egal, ob Turbo-Delphi ( kein SpinEdit ) oder Lazarus 1.4 ( uses windows, ).
Nur ist der 3.5 Ghz i4330 etwas schneller.Nur Hauptthread in 5.3 s.Die Haswell-CPU dividiert halt gern
Gruß Horst
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Do 25.06.15 16:52
Und dann ist da noch eine harte Grenze: wenn du nicht wenigstens eine Timeslice voll machst, hast du definitiv mehr Overhead, denn früher kann dein Event einfach nicht zurückkommen.
Wie lang so eine Timeslice nun ist, ist unter Windows allerdings nicht konstant. Es waren mal 20ms, mit schnelleren CPUs hat sich das aber geändert und mittlerweile kann das je nach HAL irgendwas aus 3ms, 5ms oder 180ms sein. Oder auch 10ms oder 15ms, wenn die Performance-Optionen auf "Vordergrundanwendungen" stehen.
Wenn du kontinuierlich Daten verarbeiten willst, macht es deswegen durchaus Sinn so zu zielen, dass du knapp vor Ende einer Timeslice fertig bist und keine Zeit in Waitlocks verheizt.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 25.06.15 17:56
CPU: i7-3610QM, 2.3GHz
Hauptthread --- 2 Threads
64Bit
87822
3,27 ------------ 1,66
-
32Bit
87822
9,58 ------------ 4,91
-------------------------------------------
Zitat:
The term "quantum" is a unitless measure of time for each time slice that a thread will run until a "context switch" occurs and another thread (either within the same program or from within another program) is selected to run. This prevents a CPU-bound process from monopolizing the processor. Currently in Windows, 3 quantums are equal to either 10 milliseconds (single processor) or 15 milliseconds (multiple-processor Pentium). This depends on the hardware abstraction layer (HAL) selected for your computer. Original Equipment Manufacturer (OEM) HALs may have a different value. Time slices that are fixed at 36 quantums are currently used when background services are selected (as you might choose in a typical server installation).
The situation become more complex when you enable the Foreground Applications option. This introduces the "variable quantum" concept. In this case, background tasks receive a different quantum than the quantums received by the foreground tasks. Also, both sets of quantums are shorter than a thread would receive on a computer set for background services. Currently, a background process receives a quantum of 3 and a foreground process receives a quantum of 9. Therefore, you can calculate the length of time the thread will run before its timer expires.
support.microsoft.co...259025?wa=wsignin1.0
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 25.06.15 21:01
GuaAck hat folgendes geschrieben : | Hallo,
in der Rechenaufgabe 3*5+7*11 könnt man ja die Aufgabe 3*5 und 7*11 getrennten Threads übergeben, die würden dann auf einem Multicore-Prozessor parallel ausgeführt. Der Hauptthread wartet auf die beiden Unter-Threads und führt dann die Addition aus. Das wäre die schnellste Möglichkeit für die Berechnung - wenn nicht die Threadverwaltung wäre!!!!! |
Stimmt so übrigens auch nicht ganz
Moderne Prozessoren, wie z.B. Haswell, können durchaus mehrere Operationen pro Takt auf einem Kern gleichzeitig erledigen, solange sie unabhängig sind. Deine Rechnung "3*5+7*11" würde also in fünf Takten durchlaufen: 2-4 Zyklen für die Multiplikationen (ob eine oder zwei Multiplikationen: egal, dauert gleich lange) und ein Zyklus für die Addition der beiden Ergebnisse. Interessant fand ich da die Vorträge von Eric Brumer: channel9.msdn.com/Ev...Speakers/eric-brumer insbesondere den hier: channel9.msdn.com/Events/Build/2014/4-587
Zum Thema: Schön, dass ihr es ausprobiert habet. Ich persönlich hätte gedacht, dass ein Thread mehr einmaligen Overhead hat. Aber die 30µs sind eine interessante Größe die ich mir mal merken werde
Mangels exe/Delphi kann ich leider keine Werte beisteuern
|
|
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Do 25.06.15 21:45
Danke an alle,
jfheins: Das wusste ich nicht. Mein Kleinstbeispiel sollte ja nur das Prinzip verdeutlichen.
Das mit den Timeslices passt hier m. E. nicht ganz. Das wird wohl zutreffen, wenn die CPU voll ist. Wenn meine beiden 30 us-Aufgaben erledigt sind, dann hat die CPU frei. (Und ein paar Kerne sind ohnehin noch geparkt.) Warum sollte Windows dann nicht mal die Events verteilen?
Aber der Tipp ist sehr hilfreich. In einer anderen Anwendung, in der ich alle 8 Kerne zu 90 % auslaste, war mir das Zeitverhalten an einer Stelle nicht plausibel, das könnte an den Timeslices liegen.
Nun lasst es aber zu dieser Frage gut sein. Lieber soll jemand eine neue Frage stellen zu dem Thema.
Viele Grüße
GuaAck
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 25.06.15 22:01
Nur nebenbei zum Testprogramm: Delphi-Quelltext 1:
| sema := createsemaphore(NIL, initial_wert, 2, pansichar('Sema_Rechne_' + inttostr(getcurrentthreadid MOD 10000))); | An der Zeile sieht man gut warum so viele beim Umstieg von Delphi 7 usw. auf Delphi 2009 und höher Probleme hatten.
Das passt nicht zusammen.
Richtig wäre eine dieser Varianten: Delphi-Quelltext 1: 2: 3:
| sema := CreateSemaphore(nil, initial_wert, 2, PChar('Sema_Rechne_' + IntToStr(GetCurrentThreadId MOD 10000))); sema := CreateSemaphoreA(nil, initial_wert, 2, PAnsiChar('Sema_Rechne_' + IntToStr(GetCurrentThreadId MOD 10000))); sema := CreateSemaphoreW(nil, initial_wert, 2, PWideChar('Sema_Rechne_' + IntToStr(GetCurrentThreadId MOD 10000))); | Die Mischung aus der Standard-Variante von CreateSemaphore mit einem speziellen Parameterwert für die Ansi-Variante (der Cast auf PAnsiChar) verträgt sich nicht. Denn ab Delphi 2009 erwartet diese Standard-Variante einen PWideChar...
Für diesen Beitrag haben gedankt: GuaAck
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 25.06.15 22:43
Einloggen, um Attachments anzusehen!
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 25.06.15 22:55
CPU: i5-3230M, 2.6GHz
Hauptthread --- 2 Threads (alle Starteinstellung)
Hathors Programme
64Bit
3,22 ------------ 1,72
32Bit
9,27 ------------ 5,12
Mit Delphi 7 übersetzt
9,58 ------------ 5,42
Mit Delphi 5 übersetzt
9,41 ------------ 5,38
Für mich erstaunlich, wie schnell das bei 64bit ist.
Beste Grüße
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Fr 26.06.15 06:42
Vielleicht darf ich noch anmerken, daß sich die Multiplikation mehrstelliger Zahlen (reicht, wenn ein Faktor mehrstellig ist) ihrerseits parallelisieren und mithin an mehrere Threads verteilen läßt. Wenn man es darauf anlegt, lassen sich sehr viele Algorithmen bis zum Gehtnichtmehr ziselieren und parallelisieren. Das kann sogar sinnvoll sein, nämlich dann, wenn man diese Simultaneität bzw. Parallelisierbarkeit demonstrieren möchte.
|
|
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Sa 27.06.15 19:06
Hallo Jaenicke,
das mit Pchar usw. ist für mich sehr hilfreich, bei mir war es busher eher Zufall, welchen PChar ich jeweils genommen habe.
Gru0
GuaAck
|
|
|