Wie läuft ein einzelner Thread auf mehreren Kernen?

61

Ich versuche auf hoher Ebene zu verstehen, wie einzelne Threads über mehrere Kerne laufen. Unten ist mein bestes Verständnis. Ich glaube jedoch nicht, dass es richtig ist.

Basierend auf meiner Lektüre von Hyper-Threading scheint das Betriebssystem die Anweisungen aller Threads so zu organisieren, dass sie nicht aufeinander warten. Dann organisiert das Front-End der CPU diese Anweisungen weiter, indem es einen Thread auf jeden Kern verteilt und unabhängige Anweisungen von jedem Thread auf alle offenen Zyklen verteilt.

Wenn es also nur einen einzigen Thread gibt, führt das Betriebssystem keine Optimierung durch. Das Front-End der CPU verteilt jedoch unabhängige Befehlssätze auf jeden Kern.

Laut https://stackoverflow.com/a/15936270 kann eine bestimmte Programmiersprache mehr oder weniger Threads erstellen, dies ist jedoch für die Entscheidung, was mit diesen Threads geschehen soll, unerheblich. Das Betriebssystem und die CPU übernehmen dies, und dies geschieht unabhängig von der verwendeten Programmiersprache.

Bildbeschreibung hier eingeben

Um dies zu verdeutlichen, frage ich nach einem einzelnen Thread, der auf mehreren Kernen ausgeführt wird, und nicht nach dem Ausführen mehrerer Threads auf einem einzelnen Kern.

Was stimmt mit meiner Zusammenfassung nicht? Wo und wie werden die Anweisungen eines Threads auf mehrere Kerne aufgeteilt? Ist die Programmiersprache wichtig? Ich weiß, dass dies ein breites Thema ist. Ich hoffe auf ein umfassendes Verständnis davon.

Evorlor
quelle
6
Ein Befehlssatz für einen einzelnen Softwarethread kann auf vielen Kernen ausgeführt werden, jedoch nicht gleichzeitig.
Kroltan
1
Sie mischen Softwarethreads (die den OS-Scheduler beinhalten) und Hardwarethreads oder HyperThreading (eine CPU-Funktion, mit der sich ein Kern wie zwei verhält).
Ugoren
2
Ich habe 20 Fahrer und 4 Lastwagen. Wie ist es möglich, dass ein Fahrer Pakete mit zwei LKWs ausliefern kann? Wie ist es möglich, dass ein LKW mehrere Fahrer haben kann? Die Antwort auf beide Fragen ist die gleiche. Abwechselnd.
Eric Lippert

Antworten:

84

Das Betriebssystem bietet Threads, die zur Ausführung berechtigt sind, Zeitscheiben für die CPU an.

Wenn es nur einen Kern gibt, plant das Betriebssystem, dass der am besten geeignete Thread für eine bestimmte Zeitspanne auf diesem Kern ausgeführt wird. Nach Ablauf einer Zeitscheibe oder wenn der laufende Thread auf E / A blockiert oder wenn der Prozessor durch externe Ereignisse unterbrochen wird, überprüft das Betriebssystem erneut, welcher Thread als nächstes ausgeführt werden soll (und es kann auch wieder denselben oder einen anderen Thread auswählen).

Die Berechtigung zum Ausführen besteht aus Variationen in Bezug auf Fairness, Priorität und Bereitschaft, und durch diese Methode erhalten verschiedene Threads Zeitscheiben, einige mehr als andere.

Wenn mehrere Kerne vorhanden sind (N), plant das Betriebssystem, dass die am besten geeigneten N Threads auf den Kernen ausgeführt werden.

Prozessoraffinität ist eine Überlegung zur Effizienz. Jedes Mal, wenn eine CPU einen anderen Thread ausführt als zuvor, verlangsamt sie sich etwas, da der Cache für den vorherigen Thread warm, für den neuen jedoch kalt ist. Das Ausführen desselben Threads auf demselben Prozessor über mehrere Zeitscheiben ist daher ein Effizienzvorteil.

Es steht dem Betriebssystem jedoch frei, Zeitscheiben für einen Thread auf verschiedenen CPUs anzubieten, und es könnte sich auf verschiedenen Zeitscheiben durch alle CPUs drehen. Es kann jedoch nicht, wie @ gnasher729 sagt , einen Thread auf mehreren CPUs gleichzeitig ausführen.

Hyperthreading ist eine Hardwaremethode, mit der ein einzelner erweiterter CPU-Kern die Ausführung von zwei oder mehr verschiedenen Threads gleichzeitig unterstützen kann. (Eine solche CPU kann zusätzliche Threads zu geringeren Kosten in Silizium-Immobilien als zusätzliche Voll-Cores anbieten.) Dieser erweiterte CPU-Core muss einen zusätzlichen Status für die anderen Threads unterstützen, wie z. B. CPU-Registerwerte, und hat auch einen Koordinationsstatus und ein entsprechendes Verhalten Ermöglicht die gemeinsame Nutzung von Funktionseinheiten innerhalb dieser CPU, ohne die Threads zusammenzuführen.

Hyperthreading ist zwar aus Hardware-Sicht eine technische Herausforderung, aus Sicht des Programmierers ist das Ausführungsmodell jedoch eher das von zusätzlichen CPU-Kernen als von etwas Komplexerem. Daher sieht das Betriebssystem zusätzliche CPU-Kerne, obwohl es einige neue Probleme mit der Prozessoraffinität gibt, da mehrere Hyperthread-Threads die Cache-Architektur eines CPU-Kerns gemeinsam nutzen.


Wir könnten naiv annehmen, dass zwei Threads, die auf einem Hyperthread-Core ausgeführt werden, jeweils halb so schnell laufen, wie sie es mit ihrem eigenen vollständigen Core tun würden. Dies ist jedoch nicht unbedingt der Fall, da die Ausführung eines einzelnen Threads mit Pufferzyklen voll ist und ein Teil davon vom anderen Thread mit Hyperthreading verwendet werden kann. Selbst während nicht lockerer Zyklen kann ein Thread andere Funktionseinheiten als der andere verwenden, so dass eine gleichzeitige Ausführung erfolgen kann. Die erweiterte CPU für Hyperthreading verfügt möglicherweise über einige weitere häufig verwendete Funktionseinheiten, um dies zu unterstützen.

Erik Eidt
quelle
3
"Das Ausführen desselben Threads auf demselben Prozessor über mehrere Zeitscheiben ist daher ein Effizienzvorteil." Müssten es nicht zusammenhängende Zeitscheiben sein? Andernfalls würden die Caches von anderen Threads gelöscht, oder? +1 für eine nette Erklärung.
jpmc26
2
@Luaan: HT ist oft gut, aber die Situation ist nicht so einfach, wie Sie es beschreiben. Die Bandbreite des Front-End-Problems (4 Ups pro Takt bei Intel, 6 Ups bei Ryzen) wird zu gleichen Teilen von den Threads genutzt (es sei denn, einer ist blockiert). Wenn das der Engpass ist, dann hilft HT, wie ich schon sagte, überhaupt nicht. Es ist nicht ungewöhnlich, dass Skylake in einer gut abgestimmten Schleife dem nahe kommt, wenn es eine Mischung aus Lasten, ALU und Speichern gibt ... Transistoren sind billig (und können nicht alle auf einmal schalten, oder die CPU würde schmelzen). Daher verfügen moderne x86-CPUs über mehr Ausführungsports, als das Front-End bereitstellen kann (wobei viele Ausführungseinheiten repliziert werden ...
Peter Cordes,
2
... an mehreren Ports) ... Dies scheint eine Verschwendung zu sein, aber oft wird in einer Schleife nur eine Art von ALU-Ausführungseinheit gleichzeitig verwendet. Wenn also Duplikate von allem vorhanden sind, werden mehrere ausgeführt, unabhängig davon, welche Art von Code ausgeführt wird Ports für seine Anweisungen. Der Grund, den Sie für die Nutzung von HT angegeben haben, ist nicht so häufig, da der meiste Code einige Lasten und / oder Speicher hat, die Front-End-Bandbreite beanspruchen, und das, was übrig bleibt, oft nicht ausreicht, um die Ausführungseinheiten zu sättigen.
Peter Cordes
2
@Luaan: Auch in Intel - CPUs der ganzzahlige und FP / Vektorausführungseinheiten teilen sich die gleichen Ausführungs Ports . Beispielsweise befinden sich die FP-FMA- / Mul- / Add-Einheiten an den Ports 0/1. Der Integer-Multiplikator befindet sich aber auch auf Port1, und einfache Integer-Ops können auf jedem der 4 Ausführungsports ausgeführt werden (Diagramm in meiner Antwort). Ein zweiter Thread, der die Bandbreite bei der Ausgabe erhöht, verlangsamt beide, auch wenn sie nicht um Ausführungseinheiten konkurrieren. Oft gibt es jedoch einen Netto-Durchsatzgewinn, wenn sie nicht zu stark um den Cache konkurrieren. Selbst gut abgestimmte Hochdurchsatz-Codes wie x264 / x265 (Video-Encoder) profitieren bei Skylake von HT zu etwa 15%.
Peter Cordes
3
@luaan Zusätzlich zu dem, was Peter gesagt hat, ist Ihre Behauptung, dass "das die ursprüngliche Begründung für HT war", falsch. Die ursprüngliche Begründung für HT war, dass die NetBurst-Mikroarchitektur die Pipeline so extrem verlängert hatte (um die Taktrate zu erhöhen), dass Verzweigungsfehlvorhersagen und andere Pipelineblasen die Leistung absolut beeinträchtigten . HT war eine von Intels Lösungen, um die Zeit zu minimieren, die die Ausführungseinheiten dieses großen, teuren Chips aufgrund von Blasen in der Pipeline im Leerlauf waren: In diese Löcher konnte Code aus anderen Threads eingefügt und ausgeführt werden.
Cody Grey
24

Es gibt keinen einzigen Thread, der gleichzeitig auf mehreren Kernen ausgeführt wird.

Dies bedeutet jedoch nicht, dass Anweisungen von einem Thread nicht parallel ausgeführt werden können. Es gibt Mechanismen, die als Anweisungs-Pipelining und Out-of-Order-Ausführung bezeichnet werden und dies ermöglichen. Jeder Kern verfügt über eine Menge redundanter Ressourcen, die nicht von einfachen Befehlen verwendet werden, sodass mehrere solcher Befehle zusammen ausgeführt werden können (solange der nächste nicht vom vorherigen Ergebnis abhängt). Dies geschieht jedoch immer noch in einem einzelnen Kern.

Hyper-Threading ist eine extreme Variante dieser Idee, bei der ein Kern nicht nur Befehle von einem Thread parallel ausführt, sondern Befehle von zwei verschiedenen Threads mischt, um die Ressourcennutzung noch weiter zu optimieren.

Verwandte Wikipedia-Einträge: Instruction Pipelining , Out-of-Order-Ausführung .

Frax
quelle
3
Sie können nicht gleichzeitig laufen, aber sie können parallel laufen? Ist das nicht dasselbe?
Evorlor
10
@Evorlor Entscheidend ist hier der Unterschied zwischen einem Kern und einer Ausführungseinheit. Ein einzelner Thread kann nur auf einem Kern ausgeführt werden, aber ein Prozessor kann mithilfe einer dynamischen Analyse herausfinden, welche Anweisungen, die von einem Kern ausgeführt werden, nicht voneinander abhängen, und diese gleichzeitig auf verschiedenen Ausführungseinheiten ausführen. Ein Kern kann mehrere Ausführungseinheiten haben.
user1937198
3
@Evorlor: Eine außer Betrieb befindliche CPU kann die Parallelität auf Befehlsebene innerhalb des Befehlsstroms eines einzelnen Threads finden und ausnutzen . ZB sind die Anweisungen, die einen Schleifenzähler aktualisieren, häufig unabhängig von den anderen Aufgaben einer Schleife. Oder in einer a[i] = b[i] + c[i]Schleife ist jede Iteration unabhängig, sodass das Laden, Hinzufügen und Speichern von Daten aus verschiedenen Iterationen gleichzeitig erfolgen kann. Es muss die Illusion bewahrt werden, dass die Anweisungen in der Programmreihenfolge ausgeführt werden, aber zum Beispiel verzögert ein Speicher, der im Cache fehlt, den Thread nicht (bis der Speicherplatz im Speicherpuffer erschöpft ist).
Peter Cordes
3
@ user1937198: Der Ausdruck "dynamische Analyse" würde besser zu einem JIT-Compiler passen. Nicht ordnungsgemäße CPUs analysieren nicht wirklich . Es ist eher wie ein gieriger Algorithmus, der alle Befehle ausführt, die dekodiert und ausgegeben wurden und deren Eingaben bereitstehen. (Das Fenster für die Neuordnung außerhalb der Reihenfolge wird durch einige wenige Mikroarchitekturressourcen begrenzt. Beispielsweise hat Intel Sandybridge eine Größe des Neuordnungspuffers von 168 Uops. Siehe auch experimentelles Messen der ROB-Größe. ) Alle Geräte sind mit Hardware-Zustandsautomaten ausgestattet, um 4 Ups pro Takt zu verarbeiten.
Peter Cordes
3
@Luaan Ja, es war eine interessante Idee, aber AOT-Compiler sind immer noch nicht schlau genug, um sie voll auszunutzen. Auch Linus Torvalds (und andere) haben argumentiert, dass das Freilegen eines Großteils der Interna der Pipeline eine große Einschränkung für zukünftige Entwürfe darstellt. Sie können zB die Pipeline-Breite nicht wirklich erhöhen, ohne die ISA zu ändern. Oder Sie erstellen eine CPU, die Abhängigkeiten auf die übliche Weise nachverfolgt, und geben möglicherweise zwei VLIW-Gruppen parallel aus. Dann haben Sie den CPU-Komplexitätsvorteil von EPIC verloren, haben aber immer noch die Nachteile (Bandbreitenverlust, wenn der Compiler nicht auffüllen kann) ein Wort).
Peter Cordes
22

Zusammenfassung: Das Auffinden und Ausnutzen der (Befehls-) Parallelität in einem Single-Threaded-Programm erfolgt rein hardwaremäßig durch den CPU-Kern, auf dem es ausgeführt wird. Und nur über ein Fenster von ein paar hundert Anweisungen, keine groß angelegte Nachbestellung.

Single-Threaded-Programme profitieren nicht von Multi-Core-CPUs, außer dass andere Dinge auf den anderen Kernen ausgeführt werden können, anstatt Zeit für die Single-Threaded-Aufgabe zu verlieren.


Das Betriebssystem organisiert die Anweisungen aller Threads so, dass sie nicht aufeinander warten.

Das Betriebssystem schaut NICHT in die Befehlsströme von Threads. Es werden nur Threads für Kerne geplant.

Tatsächlich führt jeder Kern die Scheduler-Funktion des Betriebssystems aus, wenn er herausfinden muss, was als Nächstes zu tun ist. Scheduling ist ein verteilter Algorithmus. Stellen Sie sich zum besseren Verständnis von Mehrkern-Rechnern vor, dass jeder Kern den Kernel separat ausführt. Genau wie ein Multithread-Programm ist der Kernel so geschrieben, dass sein Code auf einem Kern sicher mit seinem Code auf anderen Kernen interagieren kann, um gemeinsam genutzte Datenstrukturen zu aktualisieren (wie die Liste der ausführbaren Threads).

Auf jeden Fall hilft das Betriebssystem Multithread-Prozessen dabei, die Parallelität auf Thread-Ebene auszunutzen, die durch manuelles Schreiben eines Multithread-Programms explizit verfügbar gemacht werden muss . (Oder durch einen automatisch parallelisierenden Compiler mit OpenMP oder so).

Dann organisiert das Front-End der CPU diese Anweisungen weiter, indem es einen Thread auf jeden Kern verteilt und unabhängige Anweisungen von jedem Thread auf alle offenen Zyklen verteilt.

Ein CPU-Kern führt nur einen Befehlsstrom aus, wenn er nicht angehalten wird (schläft bis zum nächsten Interrupt, z. B. Timer-Interrupt). Oft ist das ein Thread, aber es kann auch ein Kernel-Interrupt-Handler oder ein anderer Kernel-Code sein, wenn der Kernel sich dazu entschlossen hat, etwas anderes zu tun, als nach der Behandlung und dem Interrupt oder Systemaufruf nur zum vorherigen Thread zurückzukehren.

Bei HyperThreading oder anderen SMT-Designs verhält sich ein physischer CPU-Kern wie mehrere "logische" Kerne. Aus Sicht des Betriebssystems besteht der einzige Unterschied zwischen einer Quad-Core-mit-Hyperthreading (4c8t) -CPU und einer einfachen 8-Core-Maschine (8c8t) darin, dass ein HT-fähiges Betriebssystem versucht, Threads so zu planen, dass sie physische Kerne trennen, damit sie nicht " nicht miteinander konkurrieren. Ein Betriebssystem, das sich mit Hyperthreading nicht auskannte, konnte nur 8 Kerne erkennen (sofern Sie HT nicht im BIOS deaktivieren, würde es nur 4 erkennen).


Der Begriff " Front-End" bezieht sich auf den Teil eines CPU-Kerns, der Maschinencode abruft, die Anweisungen decodiert und sie in den Teil des Kerns außerhalb der Reihenfolge ausgibt . Jeder Kern hat ein eigenes Front-End und ist Teil des gesamten Kerns. Anweisungen, die er abruft, sind das, was die CPU gerade ausführt.

Innerhalb des nicht in der richtigen Reihenfolge befindlichen Teils des Kerns werden Anweisungen (oder Uops) an Ausführungsports gesendet, wenn ihre Eingabeoperanden bereit sind und es einen freien Ausführungsport gibt. Dies muss nicht in der Programmreihenfolge geschehen. Auf diese Weise kann eine OOO-CPU die Parallelität auf Befehlsebene innerhalb eines einzelnen Threads ausnutzen .

Wenn Sie in Ihrer Idee "core" durch "execution unit" ersetzen, sind Sie fast richtig. Ja, die CPU verteilt parallel unabhängige Befehle / Ups an Ausführungseinheiten. (Aber es gibt eine Terminologie-Verwechslung, da Sie "Front-End" gesagt haben, wenn es wirklich der Befehlsplaner der CPU, auch Reservation Station genannt, ist, der Befehle auswählt, die zur Ausführung bereit sind).

Bei der Ausführung außerhalb der Reihenfolge wird ILP nur auf sehr lokaler Ebene gefunden, nur bis zu ein paar hundert Anweisungen, nicht zwischen zwei unabhängigen Schleifen (sofern diese nicht kurz sind).


Zum Beispiel das asm-Äquivalent dazu

int i=0,j=0;
do {
    i++;
    j++;
} while(42);

läuft ungefähr so ​​schnell wie die gleiche Schleife und erhöht nur einen Zähler auf Intel Haswell. i++hängt nur vom vorherigen Wert von ab i, während j++nur vom vorherigen Wert von abhängt j, sodass die beiden Abhängigkeitsketten parallel ausgeführt werden können, ohne die Illusion zu unterbrechen , dass alles in der Programmreihenfolge ausgeführt wird.

Auf x86 würde die Schleife ungefähr so ​​aussehen:

top_of_loop:
    inc eax
    inc edx
    jmp .loop

Haswell verfügt über 4 ganzzahlige Ausführungsports und alle haben Addierereinheiten, sodass ein Durchsatz von bis zu 4 incBefehlen pro Takt möglich ist, wenn alle unabhängig sind. (Bei Latenz = 1 benötigen Sie nur 4 Register, um den Durchsatz zu maximieren, indem Sie 4 incAnweisungen im Flug halten. Vergleichen Sie dies mit Vektor-FP-MUL oder FMA: Bei Latenz = 5 Durchsatz = 0,5 sind 10 Vektorspeicher erforderlich, um 10 FMAs im Flug zu halten Um den Durchsatz zu maximieren, kann jeder Vektor 256 b groß sein und 8 Gleitkommazahlen mit einfacher Genauigkeit enthalten.

Der genommene Zweig ist auch ein Engpass: Eine Schleife benötigt immer mindestens einen ganzen Takt pro Iteration, da der Durchsatz des genommenen Zweigs auf 1 pro Takt begrenzt ist. Ich könnte eine weitere Anweisung in die Schleife einfügen, ohne die Leistung zu verringern, es sei denn, sie liest / schreibt ebenfalls eaxoder würde edxin diesem Fall die Abhängigkeitskette verlängern. Das Einfügen von zwei weiteren Befehlen in die Schleife (oder eines komplexen Multi-UOP-Befehls) würde zu einem Engpass am Front-End führen, da nur vier UOPs pro Takt in den Kern außerhalb der Reihenfolge ausgegeben werden können. (In diesen SO-Fragen und Antworten finden Sie einige Details dazu, was bei Schleifen passiert, die kein Vielfaches von 4 Uops sind: Der Schleifenpuffer und der Uop-Cache machen die Dinge interessant.)


In komplexeren Fällen muss zum Ermitteln der Parallelität ein größeres Fenster mit Anweisungen angezeigt werden . (zB gibt es eine Folge von 10 Anweisungen, die alle voneinander abhängen, dann einige unabhängige).

Die Kapazität des Nachbestellungspuffers ist einer der Faktoren, die die Fenstergröße außerhalb der Reihenfolge begrenzen. Bei Intel Haswell sind es 192 Uops. (Und Sie können es sogar experimentell messen , zusammen mit der Kapazität zum Umbenennen von Registern (Größe der Registerdatei).) CPU-Kerne mit geringem Stromverbrauch wie ARM haben viel kleinere ROB-Größen, wenn sie überhaupt nicht in der richtigen Reihenfolge ausgeführt werden.

Beachten Sie auch, dass CPUs sowohl in Pipelines als auch außer Betrieb sein müssen. Es muss also Anweisungen weit vor der Ausführung abrufen und dekodieren, vorzugsweise mit genügend Durchsatz, um die Puffer nach dem Fehlen von Abrufzyklen aufzufüllen. Zweige sind schwierig, weil wir nicht einmal wissen, wohin wir sie holen sollen, wenn wir nicht wissen, in welche Richtung ein Zweig gegangen ist. Aus diesem Grund ist die Verzweigungsvorhersage so wichtig. (Und warum moderne CPUs spekulative Ausführung verwenden: Sie raten, in welche Richtung ein Zweig gehen wird, und beginnen mit dem Abrufen / Dekodieren / Ausführen dieses Befehlsstroms. Wenn eine falsche Vorhersage erkannt wird, kehren sie zum letzten bekannten Zustand zurück und werden von dort ausgeführt.)

Wenn Sie mehr über CPU-Interna erfahren möchten, finden Sie im Stackoverflow x86-Tag-Wiki einige Links , einschließlich des Microarch-Handbuchs von Agner Fog und detaillierter Beschreibungen von David Kanter mit Diagrammen von Intel- und AMD-CPUs. Nach seiner Beschreibung der Intel Haswell-Mikroarchitektur ist dies das endgültige Diagramm der gesamten Pipeline eines Haswell-Kerns (nicht des gesamten Chips).

Dies ist ein Blockdiagramm eines einzelnen CPU-Kerns . Bei einer Quad-Core-CPU befinden sich 4 davon auf einem Chip, von denen jeder über einen eigenen L1 / L2-Cache verfügt (gemeinsam genutzter L3-Cache, Speichercontroller und PCIe-Verbindungen zu den Systemgeräten).

Haswell volle Pipeline

Ich weiß, das ist überwältigend kompliziert. In Kanters Artikel werden auch Teile davon gezeigt, um beispielsweise getrennt von den Ausführungseinheiten oder den Caches über das Frontend zu sprechen.

Peter Cordes
quelle
2
"Das Auffinden und Ausnutzen der (Befehls-) Parallelität in einem Singlethread-Programm erfolgt ausschließlich in Hardware" Beachten Sie, dass dies nur für herkömmliche ISAs gilt, nicht für VLIWs, in denen ILP vollständig vom Compiler oder Programmierer bestimmt wird, oder für die Zusammenarbeit zwischen Hardware und Software.
Hadi Brais
1
@ user7813604: ja. Hyperthreading kann einen einzelnen Thread nicht parallelisieren. Das Gegenteil ist der Fall: Es werden mehrere Threads auf einem Kern ausgeführt, wodurch die Leistung pro Thread verringert und der Gesamtdurchsatz erhöht wird.
Peter Cordes
1
@ user7813604: Der springende Punkt bei ILP besteht darin, herauszufinden, welche Anweisungen parallel ausgeführt werden können, und dabei die Illusion aufrechtzuerhalten, dass jede Anweisung in der richtigen Reihenfolge ausgeführt wurde, wobei jede Anweisung beendet wird, bevor die nächste beginnt. Eine skalare Pipeline-CPU muss unter Umständen aufgrund von Abhängigkeiten blockieren, wenn die Latenz höher als 1 ist. Für superskalare CPUs ist dies jedoch ein noch größeres Problem.
Peter Cordes
1
@ user7813604: ja, meine antwort verwendet das buchstäblich als beispiel. Haswell kann zum Beispiel bis zu 4 incBefehle in demselben Taktzyklus auf seine 4 Ganzzahl-ALU-Ausführungseinheiten ausführen.
Peter Cordes
1
@ user7813604: Ja, ILP gibt an, wie viel parallel ausgeführt werden kann . Eine echte CPU kann ILP nur eingeschränkt finden und ausnutzen, indem sie es tatsächlich parallel in einem einzigen Kern ausführt, z. B. bis zu 4-fach superskalar in Intel. Diese Antwort versucht dies anhand von Beispielen zu erklären.
Peter Cordes