Ich bin immer dem Konzept gefolgt, dass Multithreading nur auf Systemen mit mehreren Prozessoren implementiert werden kann, auf denen jedem Thread mehr als ein Prozessor zugewiesen werden kann und jeder Thread gleichzeitig ausgeführt werden kann. In diesem Fall gibt es keine Zeitplanung, da jedem Thread separate Ressourcen zugewiesen sind. Aber ich habe es immer wieder irgendwo gelesen, dass ich Multithreading auch auf Einzelprozessorsystemen durchführen kann. Ist es richtig? und wenn ja, was ist dann der Unterschied zwischen Einzelprozessor- und Mehrprozessorsystemen?
c
windows
multithreading
winapi
Ayse
quelle
quelle
Antworten:
Natürlich kann dies auf einem Einzelprozessorsystem durchgeführt werden, und tatsächlich ist es auf diese Weise viel einfacher. Es funktioniert genauso wie das Ausführen mehrerer Prozesse - der Kernel setzt über einen Timer-Interrupt oder einen ähnlichen Mechanismus einen aus, speichert seinen Maschinenzustand und ersetzt diesen durch den zuvor gespeicherten Zustand eines anderen - der einzige Unterschied besteht darin, dass zwei Threads desselben Prozesses teilen sich denselben virtuellen Speicherplatz, wodurch der Taskwechsel wesentlich effizienter wird.
Multithreading auf Multiprozessorsystemen ist tatsächlich viel schwieriger, da Sie Probleme beim gleichzeitigen Zugriff auf den Speicher von mehreren CPUs / Kernen haben und all die unangenehmen Probleme bei der Speichersynchronisierung, die sich daraus ergeben.
quelle
Ja, Sie können Multithreading auf einem einzelnen Prozessorsystem ausführen.
In einem Multiprozessorsystem werden mehrere Threads gleichzeitig auf verschiedenen Kernen ausgeführt. Beispiel: Wenn zwei Threads und zwei Kerne vorhanden sind, wird jeder Thread auf einem einzelnen Kern ausgeführt.
In einem Einzelprozessorsystem werden mehrere Threads nacheinander ausgeführt oder warten, bis ein Thread beendet ist oder vom Betriebssystem vorbelegt wird, abhängig von der Thread-Priorität und der Betriebssystemrichtlinie. Die ausgeführten Threads geben jedoch die Illusion, dass sie gleichzeitig ausgeführt werden , relativ zur erforderlichen Anwendungsantwortzeit der User Space-Anwendung.
Zeitvergleich (Beispiel):
Wenn zwei Threads jeweils 10us benötigen, um ausgeführt zu werden, beträgt die Nettozeit auf einem 2-Prozessor-System 10us
Wenn zwei Threads jeweils 10us benötigen, um ausgeführt zu werden, beträgt die Nettozeit auf einem 1-Prozessor-System 20us
quelle
Sie können mehr als vier aktive Threads in einem Quad-Core-System haben. Es gibt eine Zeitplanung, es sei denn, Sie können garantieren, dass Prozesse nicht versuchen, mehr Threads zu erstellen als Prozessoren.
Ja, Sie können mehrere Threads auf einem Single-Core-Computer haben.
Der Unterschied zwischen Einzelprozessor- und Multiprozessorsystemen besteht darin, dass ein Multiprozessorsystem tatsächlich mehr als eine Sache gleichzeitig ausführen kann. Es kann N Dinge gleichzeitig tun, wobei N die Anzahl der Prozessorkerne ist. Ein Einzelprozessorkern kann jeweils nur eine Aufgabe ausführen. Wie WhozCraig in seinem Kommentar sagte, ist es der Unterschied zwischen tatsächlicher und wahrgenommener Parallelität.
quelle
Ja, das kannst du total. Vor langer Zeit (Win 95?) Sind wir vom kooperativen Multitasking zum Multithreading übergegangen, weil immer jemand den kooperativen Teil vermasselt hat. Jedes Programm auf Ihrem Computer hat mindestens einen Thread. Möglicherweise mehr. Und die CPU wechselt immer wieder ein paar Millionen Mal pro Sekunde zwischen all diesen Threads. Wenn keiner von ihnen etwas zu tun hat, kann es sogar für einige Zeit inaktiv werden.
Multicore-Systeme bedeuten nur, dass zwei oder mehr dieser Threads parallel ausgeführt werden.
Es bringt Ihnen jedoch viel weniger dazu. Mit Multithreading auf einem Single Core-Computer können Sie lediglich Multitasking simulieren.
Mulitasking reicht aus, um zu verhindern, dass der GUI-Thread aufgrund eines langwierigen Vorgangs blockiert. Die Implementierung ist jedoch im Allgemeinen kompliziert, es sei denn, Sie haben Hilfe vom Compiler oder Langauge (wie C # async ... warten). Infolgedessen verwendeten viele GUI-Programmierer nur Multithreading und Invoking, um Multitasking zu fälschen. Wenn dieser Code auf einem oder mehreren Kernen ausgeführt wird, spielt dies keine Rolle.
Am wichtigsten ist, dass Multitasking NICHT für CPU-gebundene Operationen geeignet ist. 95% aller Async-Probleme sind jedoch nicht an die CPU gebunden. Sie sind netzwerk- oder festplattengebunden. Auf einem Singlecore-Computer hilft Multithreading auch nicht bei CPU-gebundenen Dingen. Wenn Sie zwei Threads haben, die beide 100% CPU-Zeit benötigen (dasselbe Programm oder ein anderes), aber nur einen Kern, um sie auszuführen, muss die CPU nur zwischen der Ausführung beider Threads mit 49% wechseln und die verbleibenden 2% für alle verwenden andere Threads, die nur wenig tun.
Schließlich können nur sehr wenige Probleme tatsächlich mit Multithreading behandelt werden. Versuchen Sie einfach, die Fibonacci-Sequenz (ein Thread für jedes Paar) zu multithreaden, ohne sie langsamer, speicherintensiver und komplexer zu machen.
tl; dr; Sie benötigen Multithreading und einen Multicore-Computer für CPU-gebundene Probleme. Die meisten asynchronen Probleme sind nicht an die CPU gebunden. Multitasking ist weit genug. Und Sie können mithilfe von Threads auch auf einem Single-Core-Computer Multitasking durchführen.
quelle
Hier ist ein sehr vereinfachtes Beispiel. Es ist eigentlich ein Prototyp für ein Programm, das ich erstelle. Es ist eine Implementierung von kooperativem Multitasking in einem einzigen Thread.
main
setzt einfach dasquit
Flag auf false, füllt ein Array von Funktionszeigern (die Aufgaben) und ruft dann aufloop
.loop
Verwendungensetjmp
einen Rückkehrpunkt für einen nicht-lokalen Sprung (einen Sprung einzustellen aus der Funktion zurück zu einer vorherigen Position in der Ausführung) , und dann gehen die erste Aufgabe (Funktion) zu nennen.Jede Aufgabe endet mit
yield()
. Das heißt, keine der Aufgaben funktioniert tatsächlichreturn
. Sie enthalten nicht nur keinereturn;
Anweisung (was in Ordnung wäre, da es sich umvoid
Funktionen handelt, dh Prozeduren), sondern sie würdenreturn
auch dann nicht die Anweisung erreichen , wenn sie vorhanden wäre, dayield
sie zumsetjmp
Aufruf zurückspringen und diesmal eine 1 für dieif
Anweisung ergeben inloop
. Die von der Anweisung gesteuerteif
Anweisung wählt eine andere Aufgabe aus, bevor sie erneut in diewhile
Schleife eintritt .Daher wird jede Aufgabenfunktion mehrmals ausgeführt, was dem Dispatcher (der
if(setjmp...
Anweisung) ergibt, der eine neue auszuführende Aufgabe auswählt.#include <stdio.h> #include <setjmp.h> jmp_buf dispatch; int ntasks; void (*task[10])(void); int quit; void yield(void) { longjmp(dispatch, 1); } void loop() { static int i = 0; if(setjmp(dispatch)) i = (i+1) % ntasks; while(!quit) task[i](); } int acc = 0; void a(void) { if (acc > 10) quit = 1; printf("A\n"); yield(); } void b(void) { acc *= 2; printf("B\n"); yield(); } void c(void) { acc += 1; printf("C\n"); yield(); } int main() { quit = 0; ntasks = 3; task[0] = a; task[1] = b; task[2] = c; loop(); return 0; }
Der Unterschied zwischen diesem Beispiel und einem Multitasking-Computersystem mit einem Prozessor besteht darin, dass der reale Prozessor das Unterbrechen einer Aufgabe während der Ausführung und die spätere Wiederaufnahme an derselben Stelle unterstützt. Dies ist in einer C-Simulation mit Aufgaben als Einzelfunktionen nicht wirklich möglich. Die Aufgaben könnten jedoch aus einer Folge von C-Funktionen bestehen, die jeweils dem Dispatcher nachgeben (möglicherweise ein Array von Funktionszeigern oder eine verknüpfte Liste).
quelle
yield()
. Daher muss jeder Thread abgeschlossen werden, bevor er Yield aufruft. Es gibt also keine Möglichkeit, mehr als einen Live-Thread gleichzeitig zu haben und nicht zwischen ihnen zu wechseln. Sie können die Dinge also viel einfacher machen, indem Sie einfach die Aufgaben zurückgeben lassen (anstatt Yield aufzurufen) undsetjmp
/longjmp
überhaupt nicht verwenden .In einem Multithread-Prozess auf einem einzelnen Prozessor kann der Prozessor Ausführungsressourcen zwischen Threads wechseln, was zu einer gleichzeitigen Ausführung führt. Parallelität zeigt an, dass mehr als ein Thread Fortschritte macht, die Threads jedoch nicht gleichzeitig ausgeführt werden. Das Wechseln zwischen Threads erfolgt schnell genug, sodass die Threads möglicherweise gleichzeitig ausgeführt werden.
In demselben Multithread-Prozess in einer Multiprozessor-Umgebung mit gemeinsamem Speicher kann jeder Thread im Prozess gleichzeitig auf einem separaten Prozessor ausgeführt werden, was zu einer parallelen Ausführung führt, was eine echte gleichzeitige Ausführung darstellt. Wenn die Anzahl der Threads in einem Prozess kleiner oder gleich der Anzahl der verfügbaren Prozessoren ist, stellt das Thread-Unterstützungssystem des Betriebssystems sicher, dass jeder Thread auf einem anderen Prozessor ausgeführt wird. Beispielsweise kann in einer Matrixmultiplikation, die mit vier Threads programmiert ist und auf einem System mit zwei Dual-Core-Prozessoren ausgeführt wird, jeder Software-Thread gleichzeitig auf den vier Prozessorkernen ausgeführt werden, um gleichzeitig eine Zeile des Ergebnisses zu berechnen.
quelle