Warum verwenden moderne Prozessoren nur wenige fortschrittliche Kerne anstelle vieler einfacher Kerne oder eine Hybridkombination aus beiden?

Ich verstehe, dass Speicher in modernen Computersystemen ein großer Engpass ist, aber kann ein System mit vielen einfachen Kernen für einige Aufgaben nicht effizienter sein als eines mit einer einstelligen Anzahl von erweiterten Kernen?

Soweit ich weiß, ist eine GPU eine extreme Version davon, aber gibt es nicht einen Mittelweg für bestimmte Aufgaben, die eine Dichte / Komplexität erfordern, die irgendwo zwischen den beiden Extremen liegt?

Ja, mehr Kerne und mehr Parallelität ist effizienter! Aber die Grenze der nützlichen Befehlsparallelität für allgemeinen Code hat die nützliche Anzahl von CPU-Kernen in den letzten Jahrzehnten auf eine so niedrige Zahl begrenzt, dass es keine große Sache war, alle diese Kerne zu "Hochleistungs" -Kernen zu machen. Mit immer mehr Bewusstsein für Parallelität sieht man in letzter Zeit a) breitere Kerne und b) viel mehr Kerne.. in der Tat in einem solchen Ausmaß, dass die modernste Architektur von Intel den Big-Little-Ansatz (Hybrid) verwendet, und ich bin sicher, AMD wird in diesem Jahrzehnt etwas Ähnliches annehmen.
Nützlicher Suchbegriff: Gesetz von Amdahl. Relevanz heute: Je mehr Ihrer Aufgabenlast von Natur aus seriell ist, desto geringer ist der Nutzen paralleler Kerne. Jede Ladung ist anders.
Warum Siliziumkosten verschwenden, wenn ich die gleiche Leistung mit einem Kern implementieren kann, der viel weniger Fläche verbraucht.
" Kann ein System mit vielen einfachen Kernen für einige Aufgaben nicht effizienter sein als eines mit einer einstelligen Anzahl fortgeschrittener Kerne ?" – Das ist der springende Punkt: Es kann für einige Aufgaben effizienter sein . Aber es ist für die meisten Aufgaben nicht effizienter , einschließlich der Aufgaben, die üblicherweise auf Mainstream-Computern ausgeführt werden.
Sie können viele einfache Kerne haben und Sie können alle Aufgaben parallel aufteilen (wenn und wann möglich), aber dann ist es an der Zeit, alle Ergebnisse wieder zusammenzufügen [sowie die neuen Eingaben an die Kerne zu verteilen]. Der (virtuell) unterteilte Speicher muss synchron bleiben. und die Leistung leidet. Die Kommunikation und Synchronisierung zwischen den Haupt-/Aux-Kernen wird zum Flaschenhals. Eine GPU profitiert von mehr/einfacheren Kernen, da die meisten ihrer Aufgaben gleich aussehen (für die GPUs spezialisierte Verarbeitungseinheiten haben). Für eine allgemeine CPU ist das kein häufiger Anwendungsfall.

Antworten (7)

  1. Das Programmieren für Parallelität ist schwierig, daher werden die meisten Dinge weitgehend sequentiell erledigt, was komplexere Prozessoren erfordert. Die Taktbegrenzung verhindert, dass die Prozessoren viel komplexer werden. Stattdessen haben wir mehrere komplexe Prozessoren, die hauptsächlich die gleichzeitige Ausführung unabhängiger Aufgaben oder die Aufteilung einer einzelnen Aufgabe in einige wenige gleichzeitige Threads ermöglichen, wenn dies wirklich offensichtlich und einfach ist So.

  2. Da das Programmieren für Parallelität schwierig ist, können Sie ziemlich genau vorhersagen, wann der zusätzliche Aufwand für massive Parallelität auf der Programmierseite investiert wird (dh wo sie tatsächlich benötigt wird). Dies macht es einfach, genau anzusprechen, wer sich tatsächlich die Mühe macht, mit vielen einfachen Kernen parallel zu arbeiten, weshalb Sie am Ende Allzweck-CPUs mit weniger komplexen Kernen und Spezial-GPUs mit einer großen Anzahl einfacherer Kerne erhalten.

  3. Die Entwicklung ist teuer, daher benötigen Sie einen ausreichend großen Markt, um die Entwicklung eines Mehrkernprozessors mit gemischter oder mittlerer Komplexität zu unterstützen.

Ja! So oft ja. Ich habe diese ausgezeichnete Antwort mit meiner Ansicht darüber ergänzt, was diese "mittleren" komplexen Manycore-Prozessoren heute sind.

Soweit ich weiß, ist eine GPU eine extreme Version davon, aber gibt es nicht einen Mittelweg für bestimmte Aufgaben, die eine Dichte / Komplexität erfordern, die irgendwo zwischen den beiden Extremen liegt?

Moderne GPUs sind dieser Mittelweg. Während frühere GPUs wirklich einfach waren „eine Anweisung, andere Daten, jeder wartet, bis der langsamste fertig ist, nächste Anweisung“ mit nur sehr begrenzten Befehlssätzen, sind moderne GPUs-Recheneinheiten weitaus allgemeiner und unabhängiger.

Es gab zuvor mehrere (wenn nicht viele) Versuche, dies zu tun – und abgesehen von der Nischennutzung scheiterten alle daran, dass sie weder in den Sweetspot unabhängiger Hochleistungs-CPUs noch in billige, stromsparende, massiv parallele, simplistische Shader-Einheiten fielen. Grundsätzlich müssen Sie sowohl mit Ihrer CPU-Zeit als auch mit Ihrer Speicherbandbreite effizient umgehen, und das bedeutet, dass Sie entweder wenige, aber leistungsstarke Kerne benötigen, die sich den Hauptspeicher teilen, aber über umfangreiche lokale Caches verfügen, oder Sie benötigen viele, aber zentral orchestrierte, einfachere Kerne. Es hat gezeigt, dass man wirklich nicht beides so einfach haben kann – das ist (meine Interpretation) der Grund, warum die Welt so lange gebraucht hat, um zu modernen GPUs zu gelangen, und warum nur zwei Unternehmen den GPGPU-Markt sehr klar dominieren, mit einem klaren Marktführer.

Beispiele für diese kommerziellen Misserfolge sind:

  • Intel Terascale
  • Intel Larrabee¹
  • Tilera tile64
  • IBM Kilocore

¹ Larrabee verwendete sehr leistungsfähige x86-Kerne in einem Manycore-Prozessor und war damit Mittelweg und nutzlos, übernommen von GPUs auf der einen Seite und klassischen Workstation/Server-CPUs auf der anderen Seite, obwohl man argumentieren könnte, dass sein Nachfolger, der Xeon Phi, dies getan hat ein besseres Schicksal, aber diese sind wirklich eher wie viele mächtige x86-64 einschließlich AVX-512 auf einem einzigen Chip, also ist es nicht der Mittelweg, auf den Sie hoffen. Die Serie wurde letztes Jahr eingestellt, hauptsächlich wegen mangelnder Nachfrage – GPUs auf der einen Seite, klassische x86-64 auf der anderen Seite sind einfach nützlicher und haben eine bessere Rechenleistung/Watt.

Die Tragschrauber der Siliziumwelt.
Ebenfalls zu beachten: GPUs leben meistens Seite an Seite mit CPUs mit diesen Hochleistungskernen. Sie bauen einfach keinen ganzen Computer aus GPUs, denn obwohl sie einige Dinge sehr schnell erledigen können, benötigen sie immer noch CPUs, um die Gesamtrichtung der Anwendung zu steuern.
@TimWescott ist auch sehr wahr, aber die Rolle von CPUs beim High-Performance-Computing basiert auf GPU-Flügeln – Rechenzentrums-GPUs, die mit den richtigen Netzwerkkarten gepaart sind, können beispielsweise Datenübertragungen direkt vom Netzwerk übernehmen, die GPU-Berechnung durchführen und das Ergebnis zurücksenden out – ohne Umschweife von der CPU (außer alles zu initialisieren). Dies passt gut zu Programmierparadigmen wie in TensorFlow und PyTorch, wo Ihre Berechnungsentwicklung in einer Skriptsprache erfolgt, die am Ende ein Datenflussdiagramm für die GPU kompiliert, sodass die CPU nicht an der eigentlichen Berechnung beteiligt ist.
Intels neue Chips könnten eine neue Verbesserung sein. Kombination aus komplexen Kernen und einfachen Kernen, um verschiedene Arten von Arbeit zu entlasten, anstatt einfach nur eine Anzahl derselben Kerne.
@Nelson ja, sie springen auf den kleinen BIG-Zug auf, den die High-End-Anwendungsprozessoren von Arm seit einem Jahrzehnt fahren. aber ich betrachte diese Ansätze im Grunde als identisch mit "ein paar kräftigen Prozessoren" und weit entfernt von "einem Meer identischer, kleiner Prozessoren"; es ist wirklich Nuance.

Ich möchte die Frame-Herausforderung weiter vorantreiben als die anderen Antworten hier. Bis Ende des 20. Jahrhunderts war paralleles Rechnen die Domäne spezialisierter Server und Supercomputer; Allzweck-Consumer-Computer basierten auf einem einzelnen Prozessorkern, der mit immer höheren Taktraten lief. Seitdem sind Mehrkernprozessoren zur Norm geworden, und die Anzahl der enthaltenen Kerne hat sich langsam erhöht.

Moderne Architekturen können enthalten (sogar auf einem einzelnen Chip):

  • Low-Power-CPU-Kerne
  • Hochleistungs-CPU-Kerne, die bei Nichtgebrauch abgeschaltet werden können
  • Parallele Recheneinheiten, die in einer GPU angeordnet sind

Nichtsdestotrotz ist eine Menge Software nur in der Lage, einen einzelnen Kern zu nutzen, so dass Allzweck-CPU-Kerne in absehbarer Zeit nicht verschwinden werden. Das liegt daran, dass Sie nur in bestimmten ausgewählten Fällen mehrere Kerne verwenden können:

  • Sie haben viele Daten, die Sie auf ähnliche Weise verarbeiten möchten. Dafür sind GPUs optimiert, da Grafikaufgaben oft viele Elemente haben, die die gleiche relativ einfache Verarbeitung benötigen. Es hat sich beim maschinellen Lernen als nützlich erwiesen.
  • Sie haben mehrere Aufgaben, die weitgehend unabhängig voneinander sind. Das Ausführen mehrerer Programme auf einem Desktop-Betriebssystem klingt so, als würde es in diese Kategorie fallen, aber die meisten Programme verbringen ohnehin viel Zeit damit, auf externe Eingaben zu warten, sodass sie sich einfach die Zeit auf demselben Prozessor teilen können. Innerhalb eines einzelnen Programms ist es oft sehr komplex, festzustellen, welche Anweisungen parallel (oder außerhalb der Reihenfolge) ausgeführt werden können , und Aufgaben sicher zu synchronisieren.

Einige Aufgaben eignen sich für Parallelität, andere nicht. Im Allgemeinen können Aufgaben, die dazu neigen, sich zu wiederholen und viel Zeit in Schleifen zu verbringen, in kleinere Unteraufgaben aufgeteilt werden, die vom Host gemarshallt werden. Aufgaben, die mit vielen Zweigen tendenziell „fadenhaft“ sind, lassen sich nicht so einfach auflösen.

Grafik und KI sind Beispiele, die in parallele Aufgaben aufgeteilt werden können. TCP/IP, nicht so sehr.

Der Punkt ist, es gibt einen Platz für beide.

Angesichts der Tatsache, dass TCP/IP von Natur aus in einzelne Verbindungen zerlegt werden kann, würde ich sagen, dass TCP/IP tatsächlich ziemlich gut parallelisiert werden kann. Auf einem Webserver können Sie nicht nur die TCP-Header-Arbeit usw. parallelisieren, sondern auch die Komprimierung/Dekomprimierung und die Verschlüsselung/Entschlüsselung. Es sei denn, Sie sprechen von einer sehr kleinen Anzahl von Verbindungen mit hohem Durchsatz. In diesem Fall stimme ich zu (aber das ist nicht der typische Anwendungsfall für Server).
Meine Erfahrung damit ist das Mischen von TCP/IP mit der Medienverarbeitung auf einer VLIW-Architektur. Hat nicht so gut geklappt. gen2 verwendete einen hybriden VLIW + ARM-Ansatz.
Ein VLIW erfordert eine sehr kleine Parallelität auf Befehlsebene, um gut zu funktionieren. @ablight spricht von Parallelität auf Thread-Ebene, die über mehrere TCP-Verbindungen verfügbar ist, wodurch mehrere Kerne nützlich werden, wie in der Frage gefragt wird. Aber TCP/IP selbst ist so leicht, dass Sie keinen ganzen Kern pro Verbindung benötigen. Wenn Sie also nicht viel andere Arbeit zu erledigen haben (wie Verschlüsselung/Entschlüsselung und (De-)Komprimierung), ist es nichts, was Sie brauchen oder wollen ein SPARC Niagara oder Xeon Phi für. Dennoch verteilen mehrere Verbindungen den Durchsatz problemlos auf die Kerne.

Ähm, GPUs sind nicht „eine extreme Version eines Systems mit vielen einfachen Kernen“. Beispielsweise ist in einer Nvidia-GPU jeder SM (Streaming Multiprocessor) ein stark multithreaded Prozessor. Der Datenpfad besteht aus 16 IIRC-Spuren, die jeweils 32-Bit-Gleitkommaberechnungen ausführen können. Das Multi-Threading-Scheduling einer GPU ist viel ausgefeilter als das Scheduling für eine MT-CPU und ist wohl vergleichbar mit dem eines OOO-ILP-Schedulers.

Der große Unterschied besteht darin, dass eine OOO-CPU in jedem Zyklus viele verschiedene Scheduling-Entscheidungen treffen muss, die sich auf die nächsten 1-3 Zyklen auswirken. Weitgehend unterschiedliche Planungsentscheidungen für jede Anweisung. Wohingegen die Scheduling-Entscheidung der GPU für diesen Satz von 16 ALUs gilt, die im Raum breit sind, typischerweise auch 2 bis 4 Zyklen tief in der Zeit. Anstatt eine abhängige Anweisung 1 oder 2 Zyklen später zu planen, kann in einer GPU die nächste abhängige Anweisung aus demselben Thread nur viele Zyklen später eintreffen – in einigen GPUs nicht früher als 40 Zyklen!!!! Zwischen den GPU-Zeitplänen gruppieren Operationen andere Threads. Allerdings haben immer mehr auch die massiv parallelen Workloads einer GPU nicht genug Parallelität,

Das heißt, der größte Unterschied zwischen CPU- und GPU-SM besteht darin, dass der SM die Kosten der Steuerlogik über viele Lockstep-Elemente pro Thread/Warp und viele unabhängige Steuerfluss-Threads/Warps innerhalb desselben Prozessors amortisiert.

Außerdem hat eine GPU natürlich mehrere dieser Verarbeitungselemente. Viel mehr in einem einzigen Chip als CPUs.

Insgesamt haben GPUs ein viel geringeres Verhältnis von Steuerlogik zu Rechen-/ALU-Logik als CPUs. Die GPU-Steuerungslogik ist ziemlich ausgefeilt, aber ihre Kosten werden über mehr ALUs verteilt und amortisiert – weil in einer GPU viele der ALUs fast genau dasselbe zur gleichen Zeit tun.

Aber ich gehe nicht auf Ihre Frage ein, oder? Sie haben gefragt: „Warum nicht viele einfache Prozessoren statt der großen komplizierten Einzelprozessoren …“?

Der Name für „viele unabhängige Prozessoren“ ist MIMD. Multiple Instruction Multiple Data”. Nun, eine GPU ist MIMD – aber jeder ihrer unabhängigen Prozessoren ist SIMD-Lockstep und MT-Multithreading.

Ich denke, Sie fragen nach "vielen unabhängigen einfachen Prozessoren". Ein MIMD, dessen unabhängige Prozessoren, sagen wir, 32 oder 64 Bit breit, nicht multithreaded, nicht suoerscakar und nicht OOO sind. Ich nenne das gerne MIMD(1), während eine GPU ein MIMD(SIMD(16x2)*MT(…)) ist.

Also: Hier schlägt eine GPU eine MIMD-1 – die MIMD-1 hat proportional mindestens 16x mehr Steuerlogik als die einfache GPU MIMd(SIMD(32)), selbst unter der Annahme, dass die GPZu-Kerne nicht MT oder ILP sind . Das heißt, die GPU verschwendet nur 1/16 so viel Fläche und Energie für die Steuerlogik wie das MIMD-1.

—-

Aber auch hier fragen Sie nicht, warum eine GPU eine massiv parallele MIMD-1 schlägt. Sie fragen, warum eine massiv parallele Maschine mit einfachen MIMD-1-Verarbeitungselementen eine Maschine nicht schlägt, deren Verarbeitungselemente viel komplizierter sind. Vielleicht 16 oder 1024x komplizierter, so dass Sie nur 1/16 - 1/1024 haben können, wenn die Prozessoren. Sagen wir „nur“ 8 CPUs pro Chip, im Vergleich zu vielleicht 128 oder sogar 8K MIMD-1s im selben Chip.

Nun, das MPP-MIMD-1 würde die Maschine mit viel komplizierteren Kernen schlagen – für genau die gleichen Workloads, die die GPU die MIMD-1-Maschine schlägt. Das MIMD-1 wird also herausgedrückt.

Und für andere Workloads … nun, wenn es nicht genug Parallelität gibt, um alle einfachen MIMD-1-Prozessoren zu verwenden, wird es von den großen CPUs geschlagen. Und selbst wenn es genügend Parallelität gibt, aber die unregelmäßige Art, die GPUs nicht gut können – nun, dann verbringen die MIMD-1-Kerne wahrscheinlich viel Zeit damit, auf Speicher zu warten.

Wenn Sie außerdem 16-mal mehr MIMD-1-Prozessoren als große CPUs haben, haben Sie 16-mal mehr Drähte zum Speicher. Was den vermeintlichen 16-fachen Vorteil auffrisst.

Beispielsweise würde ein MIMD-1-MPP eine weniger parallele Maschine mit großer CPU in einer Arbeitslast mit genügend Parallelität schlagen, wenn Speicher frei wäre, 1-Zyklus-Latenz und wenn Speicherkabel nichts kosten würden. Oder äquivalent, wenn jeder der MIMD-1 nur auf den privaten Speicher zugreift. Wenn Logikgatter viel größer als Drähte wären … aber wenn Verdrahtungsfläche und Leistung die eigentliche Logik dominieren, verlieren die MIMD-1s immer mehr an Boden zugunsten weniger paralleler größerer CPUs.

—-

Es mag immer noch einen Platz für MIMD-1-MPPs geben – aber er wird zwischen GPUs und großen Nicht-GPU-CPUs eingeklemmt.

—-

So viel zu den schlechten Nachrichten. Nun zu den guten Nachrichten:

Programmierer ziehen es vor, über völlig unabhängige MIMD-CPUs nachzudenken, anstatt über komplexe Kompromisse zwischen MIMD und SIMD und MT nachzudenken.

Tatsächlich bestand das historische GPU-Programmiermodell darin, jeden der Lockstep-Lane-Threads innerhalb eines Control-Flow-Warp als unabhängiges MIMD-1 zu behandeln.

Umgekehrt ist ein anderes Programmiermodell, mit dem sich Menschen wohl zu fühlen scheinen, ein einzelner Steuerungsthread - aber mit parallelen Datenoperationen, wie dem Betrieb in beliebigen Arrays. Im Grunde ein Vektorprozessor. Aber auch hier mögen Menschen beliebige Vektoren und Arrays und müssen sich nicht um die Abstimmung auf eine unterschiedliche Anzahl von Vektorelementen usw. kümmern.

In vielerlei Hinsicht ist eine GPU nur eine Möglichkeit, MIMD-1-Code zu nehmen und ihn in einer weniger teuren Mikroarchitektur auszuführen, die die Steuerlogik zwischen ansonsten unabhängigen Verarbeitungselementen teilt.

Das heißt, die gute Nachricht ist, dass Ihr Modell „viele einfache Prozessoren“ in einigen Bereichen gewinnt – aber als Software- oder Programmiermodellkonzept – eines, das wir effizienter entweder durch eine GPU oder weniger parallele, aber mehr ILP/MLP-Mikroarchitekturen implementiert haben.

Hier gibt es viele gute Informationen, aber die Antwort hat zu wenig Struktur, um meiner Meinung nach gut verständlich zu sein. Ich schlage vor, Sie verbringen einige Zeit damit, es Korrektur zu lesen/umzugestalten. Ich denke, es überspringt auch ein wenig die Rolle von Compilern. Tatsächlich denken Entwickler, die in klassischen Sprachen wie C geschult sind, manchmal nicht parallel. Aber in diesen Fällen gibt es Compiler, die sich darum kümmern. Die Ausbildung von Millionen von Entwicklern ist ein schwierigeres Problem als die Optimierung von Compilern. CPUs bekommen immer mehr Parallelität (Intracore und Intercore), weil sich Compiler verbessern.
Oh, interessanter Punkt zu Draht- und Logikgattergrößen. Ist das einer der Gründe, warum Designs wie UltraSPARC T1 Niagara im Jahr 2005 für einige Workloads realisierbar und nützlich waren? Oder einfach nur, dass seine 8 Kerne eine gute Zahl waren, was die Verbindungen betrifft, und nach heutigen Maßstäben eine ziemlich bescheidene Kernzahl sind. Aber damals im Jahr 2005 mussten sie einfach sein, um so viele auf einem Chip unterzubringen? (Und sie zu Barrel-Prozessoren zu machen, um die Latenz zu verbergen, war eine Möglichkeit, aus einfacheren Prozessoren einen anständigen Durchsatz über viele Threads zu erzielen, da die ganze Idee darin bestand, sich auf Threading zu konzentrieren.)
@PeterCordes: Mir war nicht klar, dass Niagara für irgendetwas gut ist. :-). OK, ich bin ein bisschen bissig, teilweise nur, um die Niagara-Leute meiner Bekanntschaft zu zwicken. Mein Punkt zur Gate- versus Wire-Skalierung ist AFAIK eher auf den Unterschied zwischen den 1960er und 1980er Jahren und heute anwendbar. Müsste ich nachprüfen, aber ich glaube nicht, dass sich das Verhältnis seit 2005 so dramatisch verändert hat. Obwohl die Trends weitergehen, hat sich in der Prozesstechnik in den letzten Jahren alles verlangsamt.
Ah, okay. Ich wusste, dass Drahtwiderstand und Ausbreitungsverzögerung eine immer größere Herausforderung darstellen, wenn Prozesse schrumpfen, z. B. realworldtech.com/shrinking-cpu/4 aus dem Jahr 2004, da der Widerstand mit der Fläche/Länge skaliert, also steigt, wenn alles gleichmäßig schrumpft, obwohl die Drähte kürzer sind . (Ich habe auch keine direkten Beweise dafür, dass Niagara für irgendetwas gut ist, aber ich gehe davon aus, dass es zumindest für die Workloads, für die es speziell entwickelt wurde, in Ordnung war, wenn nicht für viel mehr. : P CPUs, die interessante Beispiele abgeben, sind oft Beispiele für "niemals gehen full <xyz>", wie Alpha mit seinem fehlenden Byte Load/Store :P)
@tobalt: du hast recht, meine antwort ist eher ein schimpfen. Ich bin es leid, dass Leute sagen, dass GPUs Beispiele für viele einfache Prozessoren sind. Ich nehme an, das und einige andere sind eine so einfache Aussage oder eine nützlichere Zusammenfassung. Dem werde ich mich in meiner reichlichen Freizeit widmen.
Ich habe nur einen Verbesserungsvorschlag gemacht. Wenn es aus Zeitgründen nicht möglich ist, dann lese ich viel lieber einen tieferen und weniger strukturierten Text als eine einfache triviale Antwort, also lassen Sie es bitte. 😊 Schließlich können interessierte Leser es mehrmals lesen oder die fehlenden Bits durch eigene Recherchen ergänzen.

Algorithmen, Beweise, Denkprozesse sind in der Regel eine Liste von Dingen, die der Reihe nach zu erledigen sind. Das menschliche Gehirn mag ein massiv paralleler Prozessor sein, aber die Dinge, die es parallel tut, sind nicht so sehr bewusste Denkprozesse, sondern erworbene Fähigkeiten. Infolgedessen sind die Beschreibungen dessen, was ein Computer tun sollte, tendenziell vergleichsweise linear strukturiert, und Computerbefehlssätze sind in aufeinanderfolgenden Schritten strukturiert und nicht in einer Reihe von Aufgaben, die mit einer gewissen gegenseitigen Abhängigkeit ausgeführt werden müssen. Superskalare Architekturen parallelisieren tatsächlich einige Dinge, während sie gegenseitige Abhängigkeiten herausfinden, und bei der ursprünglichen MIPS-Architektur ("Mikroprozessor ohne Interlocking Pipeline Stages") hatte der Compiler diese Abhängigkeiten bereits herausgefunden und Operationen entsprechend geplant.

Aber das ist auf einer sehr kleinen und sehr niedrigen Ebene. Es stellt sich heraus, dass die Sequentialität das Rechnen, das Nachdenken über das Rechnen und das Programmieren sehr stark durchdringt, und Versuche einer massiven Parallelität, die einigermaßen natürlich in der Architektur ("Datenflussarchitektur") und / oder der Programmierung ("Occam") zum Ausdruck kommt, nicht wirklich erfolgreich waren und einige massiv parallelisierbar waren Systeme wie künstliche neuronale Netze erhalten ihre Programmierung eher durch Handzeichen und „Lernen“ als durch explizite Anweisungen.

Das ursprüngliche MIPS R2000 war skalar, aber ja, es war Pipeline-fähig und hatte Ladeverzögerungs-Slots, die der Compiler mit etwas (vielleicht nur einem NOP) füllen musste, und Verzweigungsverzögerungs-Slots. Ein Beispiel für das Auslagern der Aufgabe, echte Parallelität auf Befehlsebene zu finden (anstatt nur Lade- und Verzweigungslatenzen mit anderen Dingen zu überlappen), wären VLIW-Architekturen, bei denen ein "Befehlswort" tatsächlich mehrere Befehle enthält, die die CPU ausführt, ohne sie auf Konflikte zu prüfen gegenseitig. Itanium ist ein bemerkenswertes Beispiel. Compiler konnten meiner Meinung nach nie so gut abschneiden wie erhofft.
realworldtech.com/ev8-mckinley/5 enthält einige Analysen der Itanium-Mikroarchitektur der 2. Generation, McKinley, mit ihrer Dual-Bundle-Pipeline (6 "Anweisungen" breit).

TL:DR: Ja, aber nicht für die meisten Aufgaben. Aus diesem Grund besteht die aktuelle Iteration dieser Idee aus Hybrid-CPUs mit etwas Leistung, einigen Effizienzkernen, jetzt, wo wir Transistorbudgets haben, um so viele Kerne auf eine Consumer-Laptop-/Desktop-CPU zu werfen.

Aber kann ein System mit vielen einfachen Kernen für einige Aufgaben nicht effizienter sein als eines mit einer einstelligen Anzahl fortgeschrittener Kerne?

"Für einige Aufgaben" ist der Haken. Sie sind viel schlechter für viele andere Aufgaben, die nicht parallelisiert wurden oder werden können. Beim Durchschleifen eines mittelgroßen Arrays zum Beispiel lohnt es sich oft nicht, mit anderen CPU-Kernen über die Erledigung eines Teils der Arbeit zu sprechen, da die damit verbundene Latenz vergleichbar mit der Zeit ist, die es dauern würde, nur die Arbeit in einem einzelnen Thread zu erledigen.

Und ein Prozessor mit vielen einfachen CPUs ist schlechter als GPUs für Aufgaben, die hochparallel sind und nicht viel datenabhängige Verzweigung haben. Das heißt, wo eine hohe Latenz toleriert werden kann, um den hohen Durchsatz pro Leistung und pro Die-Fläche zu erreichen, den GPUs bieten können. Wie andere Antworten gezeigt haben, ist der Mittelweg zwischen durchsatzoptimierten GPUs und latenzoptimierten CPUs in Bezug auf die kommerzielle Nachfrage nicht sehr groß. (Zeug wie CPU SIMD ist für die meisten Dinge gut genug , obwohl die Energieeffizienz immer wichtiger wird und es Platz für Hybrid- CPUs mit einigen Effizienzkernen gibt.)

Die Leistung pro Thread ist sehr wichtig für Dinge, die nicht peinlich parallel sind. (Und auch, weil die Speicherbandbreite / der Cache-Fußabdruck für viele Arbeitslasten mit der Anzahl der Threads skaliert wird, gibt es also eine Untergrenze dafür, wie einfach / klein Sie jeden Kern ohne eine völlig andere Architektur wie eine GPU machen möchten.)

Ein System mit weniger großen Kernen kann SMT (Simultaneous Multi-Threading , z. B. Hyperthreading) verwenden , um diese großen Kerne wie doppelt so viele kleinere Kerne aussehen zu lassen. (Oder 4x oder 8x, zum Beispiel in IBM POWER-CPUs.) Dies ist nicht so energieeffizient wie tatsächlich mehr kleinere Kerne, liegt aber in der gleichen Größenordnung. Und natürlich macht es eine einfache Kontextumschaltung des Betriebssystems möglich, beliebig viele Software-Threads auf einem Kern auszuführen, während das Gegenteil nicht möglich ist: Es gibt keine einfache Möglichkeit, viele einfache Kerne zu verwenden, um einen Thread schnell auszuführen.

Es gibt abnehmende Renditen. Das Gegenteil dieser Frage: Warum nicht einen großen CPU-Kern bauen? hat

Siehe auch: Moderne Mikroprozessoren Ein 90-Minuten-Leitfaden! hat einen Abschnitt über SMT und Multi-Core und ist eine hervorragende Hintergrundlektüre zu CPU-Designeinschränkungen wie Leistung.


Das Erstellen großer Cache-kohärenter Systeme ist schwierig, daher ist es schwierig, auf eine große Anzahl von CPU-Kernen zu skalieren. Die größten Xeon- und Epyc-Chips packen 56 oder 64 physische Kerne auf einen Chip.

Vergleichen Sie dies mit Xeon Phi- Rechenkarten, worüber Sie sich schon gewundert haben: AVX-512 wird an stromsparende Silvermont-Kerne angeschraubt und erreicht bis zu 72 Kerne pro Karte mit etwas Speicher mit hoher Bandbreite. (Und 4-Wege-SMT, um ALU- und Speicherlatenz zu verbergen, sodass tatsächlich 4-mal so viele Threads unterstützt werden.)

Sie haben diese Linie 2018 wegen mangelnder Nachfrage eingestellt. Dieser Artikelsagt, es habe "nie einen kommerziellen Erfolg auf dem Markt gesehen". Sie konnten keine großen Beschleunigungen erzielen, wenn Sie vorhandene Binärdateien darauf ausführen. Code musste im Allgemeinen kompiliert werden, um AVX-512 nutzen zu können. (Ich denke, Intels Toolchain sollte in der Lage sein, einige Schleifen automatisch zu parallelisieren, sodass Quelländerungen möglicherweise weniger notwendig oder kleiner waren als bei der Verwendung von GPUs). Und AVX-512BW wurde weggelassen, also war es nicht gut für hochwertige Videocodierung (x264/x265 im Gegensatz zu Hardware mit fester Funktion); Ich denke, in erster Linie gut für FP-Arbeit, was bedeutet, dass es mit GPUs konkurrierte. (Einer der Gründe könnte darin liegen, dass an einer von Grund auf neuen Architektur für „Exascale“-Computing gearbeitet wurde, nachdem man gesehen hatte, wie sich die Computerlandschaft seit dem Start des Larrabee-Projekts Mitte der 2000er Jahre entwickelt hat;


Hybride / heterogene CPUs: teils schneller, teils effizienter Kern

Die neueste Iteration Ihrer Idee besteht darin, eine Mischung von Kernen zu haben, sodass Sie immer noch ein paar schnelle Kerne für serielle / latenzempfindliche Dinge haben können.

Ein Teil des Codes ist nur etwas parallel oder hat einige verschiedene Threads, die separate Aufgaben ausführen, die einzeln seriell sind. (Nicht wirklich eine Aufgabe auf viele Threads verteilen.)

ARM macht das schon seit einiger Zeit (genannt big.LITTLE), und Intels neues Alder-Lake-Design mit einer Mischung aus Performance-Kernen (Golden Cove) und Efficiency-Kernen (Gracemont) ist genau das: Fügen Sie einige relativ kleine, durchsatzoptimierte Kerne hinzu Kerne, die nicht so weit in die abnehmenden Erträge vordringen, wenn sie mehr Leistung aufwenden, um den Durchsatz pro Thread zu erhöhen.

Wenn Sie also "leichte" Arbeiten ausführen, bei denen ein E-Core ausreicht, um mit etwas Schritt zu halten, das nicht schneller erledigt werden kann (wie das Abspielen eines Videos oder das Tippen / Klicken auf einer Webseite), muss nur dieser kleine Core dies tun eingeschaltet werden.

Oder wenn Sie Zahlenverarbeitung / Videocodierung / was auch immer mit viel Parallelität auf Thread-Ebene durchführen, erhalten Sie mit 4 E-Kernen für den Bereich eines P-Kerns mehr Gesamtdurchsatz. Aber Sie haben immer noch einige P-Kerne für Aufgaben, die nicht parallelisiert sind (oder einfach nicht waren). (Ich habe ausführlicher über Alder Lake auf superuser.com geschrieben .)

Sogar die E-Kerne auf Alder Lake führen eine ziemlich breite superskalare Out-of-Order-Exec aus und können einen recht guten Durchsatz für Code haben, bei dem die Parallelität auf Befehlsebene für die CPU leicht zu finden ist. (Auf ARM big.LITTLE sind die kleinen Kerne oft in der richtigen Reihenfolge, aber immer noch 3-breiter Superskalar mit Sachen wie Hit-under-Miss-Caches, um eine gewisse Parallelität auf Speicherebene zu finden, z. B. Cortex-A53)

Für die meisten Systeme für allgemeine Workloads ist es wirtschaftlich nicht tragbar, keine latenzoptimierten Kerne mit hoher Single-Thread-Leistung zu haben. Viele Aufgaben lassen sich nicht einfach parallelisieren oder waren es einfach nicht , weil das viel mehr Programmieraufwand bedeutet. (Obwohl Low-End-Smartphones manchmal nur Low-End-Kerne verwenden; die Leute hätten lieber ein billiges und langsames als gar kein Telefon, und die Energieeffizienz ist sogar noch wichtiger als bei Laptops.)


Frühere CPUs mit vielen kleinen Kernen:

Ich habe bereits Xeon Phi erwähnt, aber Jahre zuvor war ein weiteres interessantes Beispiel Sun UltraSPARC T1 , auch bekannt als Niagara, das 2005 veröffentlicht wurde.

Es war eine 8-Kern-CPU (oder 4- oder 6-Kern für andere Modelle), zu einer Zeit, als x86-CPUs gerade erst damit begannen, Dual -Core wie Athlon X2 einzuführen . Sie versuchten nicht einmal, eine hohe Leistung pro Thread anzustreben, was damals für die meisten interaktiven Anwendungen unerlässlich war. Stattdessen zielten sie auf Server-/Datenbank-Workloads mit vielen Verbindungen ab, sodass es schon damals eine Menge Parallelität auf Thread-Ebene für Software gab.

Jeder Kern hatte eine ziemlich einfache Pipeline und war ein "Fass" -Prozessor, der zwischen bis zu 4 nicht blockierten logischen Kernen, auch bekannt als Hardware-Threads, rotierte. (Im Grunde wie 4-Wege-SMT, aber in der Reihenfolge, sodass sich Anweisungen aus separaten Threads niemals in einer Ausführungseinheit vermischen.) Wenn Sie die Kerne klein und einfach halten, wird der Sperraufwand geringer, denke ich.

32 logische Kerne waren im Jahr 2005 eine riesige Menge. (Und spätere Generationen waren Multi-Socket-fähig und ermöglichten das 2- oder 4-fache in einem ganzen System). Der Wiki-Artikel erwähnt, dass ohne spezielle Compiler-Optionen (zur automatischen Parallelisierung, nehme ich an) viel Leistung für Workloads übrig blieb, die noch nicht parallelisiert waren, wie oder MySQL (damals im Jahr 2005 und IDK, gzipwenn sie sprachen über eine einzelne große Abfrage oder was). Das ist also der Nachteil vieler schwacher Kerne, besonders wenn Sie sich wirklich darauf einlassen, wie es Sun getan hat, indem Sie es mit nicht viel Cache gemacht haben und abhängig vom Barrel-Prozessor sind, um die Latenz zu verbergen.

Fußnote 1 : Ein Teil davon war, dass der größte Teil des x86-Marktes für Maschinen war, die Windows ausführen würden, und bis Windows XP waren die Mainstream-Versionen kein SMP-fähiges IIRC. Server waren jedoch lange Zeit Multi- Socket- Server und erreichten SMP, indem sie mehrere physische CPU-Pakete in separaten Sockets hatten. Aber in erster Linie lag es daran, dass die Transistorbudgets immer noch an einem Punkt waren, an dem mehr Cache und breitere/tiefere OoO-Execs immer noch erhebliche Gewinne lieferten.


Die Parallelisierung vieler Aufgaben ist schwierig

Die Kommunikation zwischen den Kernen wird immer ziemlich teuer sein (zumindest mit hoher Latenz), da die Entfernungen von Natur aus groß sind und wegen der Out-of-Order-Exec, um den Speicher und die L3-Cache-Latenz zu verbergen. Ein Kern kann spekulativ seine eigenen Aktionen sehen, aber Geschäfte können nicht spekulativ für andere Kerne sichtbar gemacht werden, da Sie sie sonst zurücksetzen müssten, wenn Sie eine falsche Vorhersage für einen Zweig erkennen. (Was im Hinblick auf die Beibehaltung eines konsistenten Punkts, zu dem ein Rollback durchgeführt werden kann, völlig unpraktisch ist und den Zweck eines separaten Kerns zunichte machen würde.)

Die Inter-Core-Kommunikation erfordert also mindestens die Latenz des Verbindungs- und Cache-Kohärenzprotokolls sowie die Latenz des Speicherpuffers und des Out-of-Order-Exec-Fensters. (Und die Speicherordnungsbarrieren, die normalerweise involviert sind, schränken die Ausführung außerhalb der Reihenfolge etwas ein.)

"..CPU SIMD macht es gut genug für die meisten Dinge.." - Erwähnenswert ist, dass der derzeit schnellste Supercomputer den A64FX-Prozessor verwendet, keine Beschleuniger. Das ist Arm SVE mit einer enormen Menge an Speicherbandbreite.