Parallele Prozessoren und Mehrkernprozessoren

Lerne, warum Prozessoren parallel wurden und wie heutige Rechner Arbeit gleichzeitig auf viele Einheiten verteilen. Vergleiche Befehls-, Daten-, Thread- und Anfrageparallelität, klassifiziere Rechner anhand der flynnschen Taxonomie und berechne die Grenzen des Speedups mit dem amdahlschen Gesetz, dem gustafsonschen Gesetz und dem Roofline-Modell. Sieh anhand durchgerechneter Beispiele, die du von Hand überprüfen kannst, wie SIMD- und Vektorbefehle, GPUs, Mehrkernchips mit kohärenten Caches, Cluster und Warehouse-Scale Computer parallele Hardware für schnelleres oder kostengünstigeres Rechnen nutzen.

MittelEinheit 6 von 6 in Kurs: Rechnerarchitektur – Prozessoren, Speicher und RISC-V

Was du lernst

  1. Erkläre, warum Prozessoren parallel wurden, unterscheide Befehls-, Daten-, Thread- und Anfrageparallelität, klassifiziere Rechner anhand der flynnschen Taxonomie und beschreibe, wie Hardware-Multithreading einen Prozessorkern auslastet.
    • Erkläre den Übergang zu parallelen Rechnern und benenne die Arten der Parallelität
      Stelle den Zusammenhang zwischen der Power Wall und dem Übergang zu Mehrkernchips her und erkenne Befehls-, Daten-, Thread- und Anfrageparallelität in realen Programmen.
    • Klassifiziere parallele Hardware anhand der flynnschen Taxonomie
      Ordne einen Rechner anhand der Anzahl seiner Befehls- und Datenströme SISD, SIMD, MISD oder MIMD zu und erkläre den SPMD-Programmierstil.
    • Laste einen Prozessorkern mit Hardware-Multithreading aus
      Erkläre, wie feingranulares, grobgranulares und simultanes Multithreading Wartezeiten verdecken und wie sich Hardwarethreads von zusätzlichen Kernen unterscheiden.
  2. Berechne Speedup und Effizienz, wende das amdahlsche und das gustafsonsche Gesetz an, berücksichtige Lastungleichgewicht und Parallelisierungsaufwand und untersuche mit dem Roofline-Modell, ob die Rechenleistung oder die Speicherbandbreite ein Programm begrenzt.
    • Berechne Speedup und Effizienz mit dem amdahlschen Gesetz
      Definiere Speedup und Effizienz, wende das amdahlsche Gesetz in beide Richtungen an und erkläre, warum der sequenzielle Anteil den Speedup eines Problems mit fester Größe begrenzt.
    • Unterscheide starke und schwache Skalierung und berücksichtige den Parallelisierungsaufwand
      Vergleiche den Speedup bei fester und bei wachsender Problemgröße, wende das gustafsonsche Gesetz an und schätze die Auswirkungen von Lastungleichgewicht, Kommunikation und Synchronisation ab.
    • Bestimme mit dem Roofline-Modell eine obere Schranke für die Rechenleistung
      Berechne die arithmetische Intensität, lies aus einem Roofline-Diagramm ab, ob ein Kernel durch die Speicherbandbreite oder die Spitzenrechenleistung begrenzt wird, und wähle entsprechende Optimierungen.
  3. Verwende SIMD-Befehle und Vektorarchitekturen zur Verarbeitung von Arrays, erkläre den auf Durchsatz ausgelegten Aufbau einer GPU und schreibe und analysiere einen einfachen GPU-Kernel.
    • Verarbeite mit SIMD-Befehlen mehrere Datenelemente gleichzeitig
      Ermittle die Anzahl der Lanes eines SIMD-Registers, vektorisiere einfache Schleifen und erkenne die Datenanordnungen, Verzweigungen und Abhängigkeiten, die den SIMD-Speedup begrenzen.
    • Erkläre, wie Vektorarchitekturen Schleifen ausführen
      Beschreibe Vektorregister, Vektorlänge, Strip-Mining, Lanes und Zugriff mit fester Schrittweite am Beispiel der RISC-V-Vektorerweiterung.
    • Beschreibe, wie eine GPU für hohen Durchsatz aufgebaut ist
      Erkläre Streaming Multiprocessors, Warps und SIMT-Ausführung, die Verdeckung von Speicherlatenz durch GPUs, Kontrollflussdivergenz, Coalescing bei Speicherzugriffen und den Aufwand für Datentransfers. Vergleiche GPUs mit CPUs und domänenspezifischen Beschleunigern.
    • Schreibe und analysiere einen einfachen GPU-Kernel
      Ordne mithilfe der Hierarchie aus Grid, Block und Thread Daten den Threads zu, organisiere die Arbeit von Host und Gerät und synchronisiere innerhalb eines Blocks.
  4. Beschreibe Multiprozessoren mit gemeinsamem Speicher und die Aufteilung der Arbeit auf Threads, erkläre die Garantien der Cachekohärenz, verfolge Snooping- und Verzeichnisprotokolle und vermeide False Sharing.
    • Beschreibe Multiprozessoren mit gemeinsamem Speicher und verteile Arbeit auf die Kerne
      Erkläre einen gemeinsamen Adressraum, gleichförmigen und nicht gleichförmigen Speicherzugriff, den Cacheaufbau eines Mehrkernchips sowie die Aufteilung und Zusammenführung von Arbeit durch Threads.
    • Erkläre das Cachekohärenzproblem und die Garantien der Kohärenz
      Zeige, wie private Caches veraltete Daten liefern können, nenne die Bedingungen für ein kohärentes Speichersystem und unterscheide Kohärenz von Konsistenz und von Code ohne Race Conditions.
    • Verfolge ein Snooping-Protokoll mit MSI- und MESI-Zuständen
      Verfolge die Zustände von Cacheblöcken und Bustransaktionen bei einer Folge von Lese- und Schreibzugriffen und erkläre, welchen Aufwand der Exclusive-Zustand spart.
    • Erkläre Verzeichnisprotokolle und vermeide False Sharing
      Beschreibe, wie ein Kohärenzverzeichnis Mitnutzer erfasst, schätze seinen Speicherbedarf ab und erkenne, miss und behebe False Sharing.
  5. Beschreibe Cluster mit Nachrichtenaustausch und vergleiche Verbindungsnetzwerke anhand von Bandbreite und Kosten. Erkläre anschließend, wie Warehouse-Scale Computer Internetdienste bereitstellen, und berücksichtige dabei Kosten, Energie und Ausfälle.
    • Beschreibe Cluster mit Nachrichtenaustausch und vergleiche Verbindungsnetzwerke
      Erkläre, wie Knoten mit privaten Speichern durch Nachrichten zusammenarbeiten, und vergleiche Netzwerktopologien anhand von Gesamtbandbreite, Bisektionsbandbreite und Kosten.
    • Erkläre, wie Warehouse-Scale Computer Dienste in großem Maßstab bereitstellen
      Beschreibe den Aufbau eines Warehouse-Scale Computers und untersuche sein Netzwerk, seinen Energieverbrauch und seine Ausfälle anhand einfacher Rechnungen.

Mehrkernprozessoren einfach erklärt

5 Kapitel

1

Parallele Arbeit finden und klassifizieren

Parallele Hardware kann Befehle, Arrayelemente, Threads oder unabhängige Anfragen bearbeiten. Die passende Wahl hängt davon ab, wo ein Programm Arbeit enthält, die gleichzeitig ausgeführt werden kann. Stelle den Zusammenhang zwischen dieser Arbeit und den Leistungsgrenzen her, die zum Einsatz mehrerer Kerne auf Chips führten, und klassifiziere anschließend die Hardware anhand ihrer Befehlsströme. Hardware-Multithreading bietet eine weitere Möglichkeit, einen Kern auszulasten, indem es während Wartezeiten nutzbare Befehle findet.

1.1 Warum Chips die Arbeit heute aufteilen

Parallele Rechner führen Operationen gleichzeitig aus. Sie können die Latenz, also die Dauer einer Aufgabe, senken oder den Durchsatz, die Anzahl der pro Sekunde abgeschlossenen Aufgaben, erhöhen. Diese Ziele führen zu unterschiedlichen Arten der Arbeitsaufteilung.

Die Power Wall

Früher machte eine höhere Taktfrequenz jede Prozessorgeneration schneller. Die dynamische Leistungsaufnahme folgt näherungsweise P≈CV2f: Kapazität mal Spannung zum Quadrat mal Schaltfrequenz. Die Spannung geht in diesem Produkt doppelt ein. Senkt man Spannung und Frequenz jeweils um 15 %, ergibt sich 0,852×0,85=0,614125 der ursprünglichen dynamischen Leistungsaufnahme, also etwa 61 %.

Die Spannung ließ sich nicht weiter ausreichend senken, um höhere Taktfrequenzen auszugleichen. Leckströme und Wärme machten eine weitere Frequenzsteigerung zu aufwendig. Diese Power Wall führte die Branche Mitte der 2000er-Jahre zu Mehrkernchips. Ein Mehrkernchip vereint mehrere Prozessorkerne auf einem Chip; ein Multiprozessorsystem besitzt mindestens zwei Prozessoren. Einfachere Kerne können pro Joule insgesamt mehr Arbeit leisten, sofern genügend Arbeit zur Aufteilung vorhanden ist.

Vier Arten paralleler Arbeit
ArtWas läuft gleichzeitig?Beispiel
Befehlsparallelität (ILP)Befehle aus einem BefehlsstromEine Pipeline überlappt die Stufen aufeinanderfolgender Befehle.
Datenparallelität (DLP)Dieselbe Operation auf vielen ElementenEntsprechende Elemente zweier Arrays addieren.
Threadparallelität (TLP)Mehrere BefehlsfolgenMehrere Threads bearbeiten unterschiedliche Bildbereiche.
AnfrageparallelitätUnabhängige AufgabenServer beantworten gleichzeitig Anfragen vieler Nutzer.

ILP wird hauptsächlich von Hardware und Compilern erkannt. Pipelining, Mehrfachausgabe und Ausführung außerhalb der Programmreihenfolge überlappen Befehle und bewahren dabei die vorgeschriebenen Ergebnisse des Programms. Abhängigkeiten und Sprünge begrenzen die mögliche Überlappung.

DLP tritt auf, wenn viele Elemente dieselbe Berechnung benötigen. SIMD-Befehle, Vektorprozessoren und GPUs nutzen diese Regelmäßigkeit. Für TLP muss die Arbeit durch Code, eine Bibliothek oder einen Compiler auf Threads aufgeteilt werden. Ein Thread besitzt einen eigenen Befehlszähler, eigene Register und einen eigenen Stack; Threads eines Prozesses teilen sich dessen Adressraum. Getrennte Prozesse haben getrennte Adressräume.

Arbeit auf Anfrageebene benötigt wenig Zusammenarbeit zwischen den Aufgaben. Zusätzliche Server können die Kapazität daher nahezu proportional zu den hinzugefügten Ressourcen erhöhen. Auch mehrere unabhängige Programme auf einem Laptop nutzen sonst untätige Kerne und erhöhen den Gesamtdurchsatz, selbst wenn keines dieser Programme intern parallelisiert ist.

Nebenläufige Aufgaben und gleichzeitige Ausführung

Nebenläufigkeit bedeutet, dass Aufgaben während sich überschneidender Zeiträume Fortschritte machen. Ein Kern kann dies erreichen, indem er zwischen ihnen wechselt. Parallelität bedeutet, dass Operationen auf getrennter Hardware zum selben Zeitpunkt ausgeführt werden. Ein Einkernsystem kann mehrere Programme gleichzeitig in Bearbeitung halten, ohne ihre Befehle gleichzeitig auszuführen.

Ein Programm mit einem sequenziellen Thread verteilt sich nicht allein deshalb auf acht Kerne, weil diese vorhanden sind. Die zusätzlichen Kerne können andere Arbeit ausführen; um dieses Programm zu beschleunigen, muss es jedoch parallele Arbeit enthalten. Auch nach der Aufteilung begrenzt ein verbleibender sequenzieller Anteil den Gewinn.

Wichtige Erkenntnisse

  • Parallele Hardware kann die Latenz einer Aufgabe senken oder den Gesamtdurchsatz erhöhen.
  • Die dynamische Leistungsaufnahme hängt von der Spannung zum Quadrat und der Frequenz ab.
  • ILP, DLP, TLP und Anfrageparallelität erschließen unterschiedliche Arten von Arbeit.
  • Nebenläufigkeit kann Zeitaufteilung nutzen; Parallelität führt Operationen gleichzeitig aus.

1.2 Befehls- und Datenströme zählen

Ein Prozessor kann viele Recheneinheiten enthalten, ohne vielen unabhängigen Befehlsströmen zu folgen. Die flynnsche Taxonomie klassifiziert Hardware anhand ihrer Befehls- und Datenströme. Daher wird zunächst festgelegt, welche Ebene des Rechners beschrieben wird.

Die vier Hardwareklassen
KlasseBefehlsströmeDatenströmeBedeutung
SISDEinerEinerEin Prozessor folgt einem gewöhnlichen Befehlsstrom.
SIMDEinerMehrereEin Befehl wendet eine Operation auf mehrere Datenelemente an.
MISDMehrereEinerVerschiedene Befehlsströme bearbeiten einen Datenstrom.
MIMDMehrereMehrereProzessoren holen unabhängig voneinander Befehle und bearbeiten Daten.

Ein herkömmlicher Einkernprozessor ist SISD, auch wenn seine Pipeline mehrere Befehle überlappt. Superskalare Befehlsausgabe erzeugt für sich genommen weder unabhängige Befehlszähler noch macht sie den Kern zu MIMD-Hardware.

Ein SIMD-Befehl könnte acht Paare von 32-Bit-Gleitkommazahlen in einem 256-Bit-Register addieren. Er besitzt acht Lanes für die Berechnung, die aber einem Befehl folgen. Zu den SIMD-Erweiterungen mit fester Breite gehören x86 SSE und AVX sowie Arm Neon; auch Vektorarchitekturen fallen in die SIMD-Klasse. Regelmäßige Arrayberechnungen eignen sich gut, weil viele Elemente dieselbe Operation benötigen.

MIMD-Prozessoren wählen ihre Befehle unabhängig voneinander. Mehrkernchips, Multiprozessoren mit gemeinsamem Speicher und Cluster gehören zu dieser Klasse. Die Kerne können unterschiedliche Programme ausführen oder Kopien desselben Programms, die zu unterschiedlichen Zeiten verschiedene Verzweigungen erreichen.

MISD vervollständigt die 2 × 2-Klassifikation. Es gibt wenige eindeutige praktische Beispiele. Manche fehlertoleranten Systeme und Verarbeitungspipelines werden so beschrieben, ihre Klassifikation hängt aber davon ab, wie ihre Ströme definiert werden.

Ein Programm kann dennoch viele Befehlsströme haben

SPMD, ein Programm für mehrere Datenbereiche, ist ein Programmierstil. Jede Arbeitseinheit führt eine Kopie desselben Programms aus und wählt anhand ihrer ID ihren Datenanteil. Die Arbeitseinheiten besitzen unabhängige Ausführungszustände, sodass SPMD üblicherweise auf MIMD-Hardware läuft.

Wenn vier Kerne 4.000 Werte summieren, bearbeitet der Kern mit der ID i die Indizes 1000i bis 1000i+999. Kern 0 bearbeitet 0 bis 999; Kern 3 bearbeitet 3000 bis 3999. Jeder erzeugt eine Teilsumme, und diese vier Summen werden zusammengeführt. Der gemeinsame Programmtext verlangt nicht, dass alle vier Kerne im selben Taktzyklus denselben Befehl ausgeben.

Jede Ebene gesondert klassifizieren

Betrachte eine CPU mit acht Kernen, deren Threads AVX-Befehle nutzen. Über die Kerne hinweg ist sie MIMD: Die Kerne schreiten unabhängig voneinander voran. Innerhalb einer AVX-Operation ist sie SIMD: Ein Befehl steuert mehrere Lanes. Würde man alle Recheneinheiten zusammenzählen, bliebe diese Struktur verborgen.

Ebenso ist ein Cluster, auf dem Kopien eines wissenschaftlichen Programms laufen, MIMD-Hardware mit SPMD-Software. Seine Knoten kommunizieren über Nachrichten. Eine GPU kombiniert viele unabhängig eingeplante Threadgruppen mit einer SIMD-ähnlichen Ausführung innerhalb jeder Gruppe; NVIDIA nennt diese threadbasierte Ausführungsart SIMT.

Um eine Beschreibung zu klassifizieren, frag dich, wer den nächsten Befehl auswählt. Frag dann, ob dieser Befehl ein Datenelement oder mehrere verarbeitet. Die Anzahl der Quelldateien, installierten Programme oder Recheneinheiten allein kann diese beiden Fragen nicht beantworten.

Wichtige Erkenntnisse

  • Die flynnsche Taxonomie zählt Befehlsströme und Datenströme.
  • Pipelining innerhalb eines Befehlsstroms bleibt SISD.
  • Bei SIMD teilen sich Lanes die Befehlssteuerung; MIMD besitzt unabhängige Befehlsströme.
  • SPMD ist ein Programmierstil, der üblicherweise auf MIMD-Hardware läuft.
  • Ein Rechner kann über seine Kerne hinweg MIMD und innerhalb jedes Kerns SIMD sein.

1.3 Freie Taktzyklen mit einem anderen Thread nutzen

Ein Cache-Fehlzugriff kann einen Kern Hunderte Taktzyklen warten lassen. Hardware-Multithreading hält die Ausführungszustände mehrerer Threads in einem Kern vor, sodass während dieser Wartezeit nutzbare Befehle eines anderen Threads ausgeführt werden können.

Was wird vervielfacht und was gemeinsam genutzt?

Jeder Hardwarethread besitzt einen eigenen Befehlszähler und Registerzustand. Die Threads teilen sich die Ausführungseinheiten und Caches des Kerns sowie den Zugang zur Speicherbandbreite. Da die Zustände in der Hardware vorliegen, ist ein Wechsel viel schneller als das Sichern und Wiederherstellen eines Betriebssystemprozesses, was Tausende Taktzyklen kosten kann. Die Hardware kann in einem Taktzyklus oder weniger wechseln.

Das Betriebssystem sieht jeden Hardwarethread als logischen Prozessor. Acht physische Kerne mit zwei Hardwarethreads pro Kern stellen 16 logische Prozessoren bereit. Diese Zahl beschreibt verfügbare Threadkontexte und keine 16 vollständigen physischen Kerne.

Drei Planungsverfahren
VerfahrenWann wählt der Kern einen anderen Thread?Wichtigster Zielkonflikt
FeingranularIn jedem Taktzyklus; wartende Threads werden übersprungenVerdeckt kurze und lange Wartezeiten, aber jeder Thread wartet zwischen seinen Einsätzen.
GrobgranularBei einer langen Wartezeit, etwa einem Fehlzugriff im Cache der letzten EbeneLässt einen Thread lange laufen, aber Wechsel und erneutes Füllen der Pipeline kosten Zeit.
Simultanes Multithreading (SMT)Mehrere Threads können im selben Taktzyklus Befehle ausgebenFüllt ungenutzte Ausgabeplätze und teilt dabei die Ressourcen des Kerns.

Die feingranulare Planung kann reihum zwischen bereiten Threads wechseln, selbst wenn der vorherige Thread fortfahren könnte. Die grobgranulare Planung führt diesen Thread weiter aus, bis eine kostspielige Wartezeit einen Wechsel rechtfertigt. SMT nutzt einen Kern mit Mehrfachausgabe und dynamischer Befehlsplanung: Befehle verschiedener Threads können in einem Taktzyklus unterschiedliche freie Ausgabeplätze belegen. Registerumbenennung hält ihre Zustände getrennt. Intels Hyper-Threading ist eine SMT-Implementierung; einige IBM-POWER-Prozessoren unterstützen acht Hardwarethreads pro Kern.

Latenzverdeckung durchrechnen

Angenommen, ein Thread rechnet 20 Taktzyklen lang und wartet dann 200 Taktzyklen auf den Speicher. Sein Zyklus dauert 220 Taktzyklen. Allein belegt seine nutzbare Arbeit 20/220≈0,091, also 9,1 % der Zeit.

Mit vier Threads, frei versetzter Arbeit und ohne Wechselkosten oder zusätzliche Konkurrenz kann nutzbare Arbeit 4×20/220≈0,364, also 36,4 % der Zeit belegen. Der Kern hat weiterhin Lücken, weil vier Rechenphasen von jeweils 20 Taktzyklen die Wartezeiten nicht abdecken können.

Elf Threads liefern insgesamt 220 Taktzyklen Rechenarbeit. Während einer 200 Taktzyklen wartet, können die anderen zehn jeweils 20 Taktzyklen rechnen. Dieser ideale Ablauf hält den Kern ausgelastet. Die tatsächliche Rechenleistung hängt auch davon ab, ob die Threads um Speicher und Ausführungsressourcen konkurrieren.

Durchsatz und Abschlusszeit eines Threads

Multithreading erhöht vor allem den Durchsatz. Ein bestimmter Thread kann länger brauchen, weil andere Threads Taktzyklen und Cacheplatz nutzen, die er sonst erhalten würde. Zwei Hardwarethreads, die sich eine Recheneinheit teilen, können nicht beide die Kapazität eines zweiten vollständigen Kerns hinzugewinnen.

Wenn beide Threads bereits dieselben vollständig ausgelasteten Ausführungseinheiten beanspruchen, hat SMT wenig freie Kapazität zu füllen. Wartet einer, während der andere ausführen kann, ist die gemeinsame Nutzung hilfreich. GPUs verdecken Latenz in größerem Maßstab, indem sie für ihre Scheduler viele Threadgruppen bereithalten.

Wichtige Erkenntnisse

  • Hardwarethreads vervielfachen den Ausführungszustand und teilen sich zugleich die Ressourcen eines Kerns.
  • Feingranularer Wechsel erfolgt in jedem Taktzyklus; grobgranularer Wechsel reagiert auf lange Wartezeiten.
  • SMT kann in einem Taktzyklus Befehle verschiedener Threads ausgeben.
  • Die Anzahl logischer Prozessoren umfasst Hardwarethreadkontexte.
  • Latenzverdeckung benötigt bereite Arbeit und kann durch Konkurrenz um Ressourcen begrenzt werden.
  • Ein höherer Durchsatz muss die Laufzeit eines einzelnen Threads nicht verkürzen.
2

Den nutzbaren parallelen Speedup abschätzen

Zusätzliche Prozessoren teilen nur die Arbeit auf, die parallel ausgeführt werden kann, und verursachen eigene Kosten. Beginne mit der Gesamtlaufzeit und dem sequenziellen Anteil und unterscheide dann, ob eine feste Aufgabe schneller abgeschlossen oder eine größere Aufgabe in derselben Zeit gelöst wird. Lastverteilung und Koordination erklären weitere Verluste. Das Roofline-Modell ergänzt eine andere Grenze: ob der Speicher die verfügbaren Recheneinheiten schnell genug versorgen kann.

2.1 Gewinn und Obergrenze berechnen

Ein paralleler Rechner ist nützlich, wenn er die Gesamtlaufzeit verändert. Der Speedup vergleicht den besten sequenziellen Lauf mit dem parallelen Lauf; die Effizienz setzt diesen Gewinn ins Verhältnis zur Anzahl der verwendeten Prozessoren.

Mit der gemessenen Zeit beginnen

Für p Prozessoren gilt S(p)=T1/Tp und E(p)=S(p)/p. Eine sequenzielle Aufgabe von 100 s, die auf acht Kernen in 16 s abgeschlossen wird, hat den Speedup 100/16=6,25. Ihre Effizienz beträgt 6,25/8=0,78125, also etwa 78 %. Miss für beide Läufe die Gesamtlaufzeit und verwende dieselbe feste Aufgabe.

Zeit in verbesserten und unveränderten Anteil aufteilen

Im amdahlschen Gesetz ist f der Anteil der ursprünglichen Ausführungszeit, den eine Verbesserung beschleunigt. Es ist ein Zeitanteil und kein Anteil der Quellcodezeilen. Wird dieser Teil s-mal so schnell, gilt

Tnew=Told((1−f)+f/s),S=1(1−f)+f/s.

Der unveränderte Teil benötigt weiterhin seine volle ursprüngliche Zeit. Für eine ideale parallele Aufteilung auf p Prozessoren setze s=p. Dieses Modell schließt den Aufwand für Kommunikation, Lastungleichgewicht und Synchronisation aus; diese Kosten können die gemessene Zeit verlängern.

Bei 90 % paralleler Zeit und zehn Prozessoren beträgt die normierte Zeit 0,1+0,9/10=0,19. Der Speedup ist 1/0,19≈5,26 und die Effizienz etwa 53 %. Bei 100 Prozessoren beträgt die Zeit 0,1+0,009=0,109 und der Speedup etwa 9,17. Eine Verzehnfachung der Prozessorzahl hat den Speedup nicht verdoppelt.

Die Grenze vor dem Kauf weiterer Prozessoren bestimmen

Mit wachsender Prozessorzahl nähert sich die parallele Zeit der Null. Der sequenzielle Anteil bleibt bestehen und ergibt die Obergrenze Smax=1/(1−f). Ein sequenzieller Anteil von 10 % begrenzt den idealen Speedup auf 10; ein Anteil von 5 % begrenzt ihn auf 20. Endliche Prozessorzahlen nähern sich diesen Obergrenzen von unten.

Das amdahlsche Gesetz bewertet auch eine einzelne schnellere Befehlsklasse. Wenn die Multiplikation 30 % eines Laufs beansprucht und viermal so schnell wird, beträgt die normierte Zeit 0,7+0,3/4=0,775. Das gesamte Programm ist nur 1/0,775≈1,29-mal so schnell.

Von einem Zielwert rückwärts rechnen

Für einen Speedup von 90 auf 100 Prozessoren schreibe 1/90=(1−f)+f/100=1−0,99f. Daher gilt f=(1−1/90)/0,99≈0,99888. Nur etwa 0,11 % der ursprünglichen Zeit dürfen sequenziell bleiben. Ein Ziel nahe der Prozessorzahl verlangt einen sehr kleinen unveränderten Anteil.

Ein gemessener Speedup kann manchmal die Prozessorzahl übersteigen. Durch Aufteilung einer großen Arbeitsmenge passt möglicherweise jeder Teil in den Cache, sodass die Kosten pro Operation sinken. Dieser superlineare Speedup verändert eine Voraussetzung des einfachen Modells: Die parallele Arbeit ist nicht mehr bloß die ursprüngliche Arbeit, die in gleiche Anteile geteilt wird. Prüfe Algorithmus, Datengröße und Cacheverhalten, bevor du eine solche Messung deutest.

Wichtige Erkenntnisse

  • Der Speedup ist die sequenzielle Zeit geteilt durch die parallele Zeit; die Effizienz ist der Speedup geteilt durch die Prozessorzahl.
  • Amdahls Anteil bezieht sich auf die ursprüngliche Ausführungszeit.
  • Nur der verbesserte Anteil wird durch den Beschleunigungsfaktor geteilt.
  • Der sequenzielle Anteil legt die Speedup-Obergrenze bei fester Arbeitslast fest.
  • Cacheeffekte können die Kosten der Arbeit verändern und einen gemessenen superlinearen Speedup erzeugen.

2.2 Die Problemgröße ändern und Kosten einbeziehen

Zusätzliche Prozessoren können entweder dieselbe Aufgabe verkürzen oder einen Rechner eine größere Aufgabe bearbeiten lassen. Starke Skalierung und schwache Skalierung messen diese unterschiedlichen Einsatzarten. Beide hängen davon ab, wie viel nutzbare Arbeit nach Abzug der Koordinationskosten übrig bleibt.

Feste und wachsende Arbeit

Bei starker Skalierung bleibt die Problemgröße fest. Bei schwacher Skalierung wächst die Arbeit proportional zur Prozessorzahl, sodass die Arbeit pro Prozessor konstant bleibt. Perfekte schwache Skalierung hält die Gesamtlaufzeit konstant, während die Gesamtarbeit wächst.

Betrachte zehn sequenzielle Additionen, gefolgt von der elementweisen Summe zweier Matrizen. Eine 10 × 10-Matrix benötigt 100 parallele Additionen. Die Gesamtzeit beträgt 110 Einheiten auf einem Prozessor, 20 auf zehn und 12 auf fünfzig: Die Speedups betragen 5,5 und etwa 9,2. Eine 40 × 40-Matrix benötigt 1.600 parallele Additionen. Die Zeiten betragen 1.610, 170 und 42 Einheiten: Die Speedups betragen etwa 9,5 und 38,3. Beim größeren Problem fällt die nutzbare parallele Arbeit gegenüber denselben zehn sequenziellen Additionen stärker ins Gewicht.

Gustafsons anderer Ausgangswert

Das gustafsonsche Gesetz nutzt den sequenziellen Zeitanteil, der beim parallelen Lauf gemessen wird. Bezeichnet man diesen Anteil mit s, beträgt der skalierte Speedup SG=s+(1−s)p. Für s=0,05 und 100 Prozessoren gilt SG=0,05+0,95(100)=95,05.

Das amdahlsche Gesetz ergibt bei 5 % sequenzieller Zeit im ursprünglichen Lauf auf einem Prozessor nur etwa 16,8 auf 100 Prozessoren. Diese Anteile haben unterschiedliche Bezugsgrößen und beantworten unterschiedliche Fragen. Ein skalierter Speedup von 95,05 bedeutet nicht, dass die ursprüngliche Aufgabe mit fester Größe 95,05-mal so schnell abgeschlossen wurde.

Die langsamste Arbeitseinheit bestimmt den Endzeitpunkt

Werden 400 gleich große Arbeitseinheiten auf acht Kerne verteilt, beträgt der ausgeglichene Anteil je 50. Angenommen, einer erhält 120, während die anderen sieben je 40 erhalten. Der Schritt dauert 120 Zeiteinheiten, sodass der Speedup 400/120≈3,33 beträgt. Wer durch die durchschnittliche Last dividiert, übersieht das Warten auf den am stärksten belasteten Kern.

Auch das Erzeugen und Einplanen von Threads, Nachrichten, Barrieren und Konkurrenz um gemeinsame Bandbreite verbrauchen Zeit. Granularität ist der Umfang der Berechnungen zwischen Kommunikations- oder Synchronisationsereignissen. Größere Teilstücke senken die Koordinationskosten pro nützlicher Operation, aber bei zu wenigen Teilstücken können einige Arbeitseinheiten untätig bleiben.

Mehr Prozessoren können die Zeit verlängern

Für eine vollständig parallelisierbare Aufgabe von 100 s mit einem Aufwand von 0,5p Sekunden gilt Tp=100/p+0,5p. Zehn Prozessoren benötigen 15 s. Vierzehn benötigen etwa 14,14 s, nahe dem Minimum bei ungefähr 200 Prozessoren. Vierzig benötigen 22,5 s, weil ihr Aufwand von 20 s die kürzere nutzbare Berechnung überwiegt.

Gib bei der Ergebnisdarstellung an, ob die Arbeit fest blieb oder wuchs, und vergleiche mit der Zeit des besten sequenziellen Programms. Wenn du eine langsame parallele Implementierung auf einem Prozessor als Ausgangswert nutzt, kann der angegebene Speedup überhöht sein.

Wichtige Erkenntnisse

  • Starke Skalierung hält die Gesamtarbeit fest; schwache Skalierung hält die Arbeit pro Prozessor fest.
  • Gustafsons sequenzieller Anteil wird beim parallelen Lauf gemessen.
  • Die langsamste Arbeitseinheit bestimmt den Endzeitpunkt eines parallelen Schritts.
  • Kommunikation, Synchronisation und Ressourcenkonkurrenz können mit der Prozessorzahl zunehmen.
  • Bei der Granularität stehen Koordinationskosten und Lastverteilung in einem Zielkonflikt.
  • Verwende bei der Angabe des Speedups die Gesamtlaufzeit und das beste sequenzielle Programm als Vergleichsbasis.

2.3 Das Rechenleistungs- oder Bandbreitendach bestimmen

Die beworbene Rechenrate eines Prozessors ist nur eine Grenze. Das Roofline-Modell fragt auch, ob der Speicher Daten schnell genug liefern kann, um diese Rate aufrechtzuerhalten. Es gibt eine obere Schranke an und hilft damit, eine sinnvolle Richtung für Optimierungen zu finden.

Operationen pro DRAM-Byte zählen

Die arithmetische Intensität ist die Anzahl der Gleitkommaoperationen geteilt durch die zwischen DRAM und Prozessor übertragenen Byte. Die ursprüngliche Arbeit zum Roofline-Modell nennt dieses DRAM-bezogene Maß operationale Intensität. Zähle den Datenverkehr an dieser Schnittstelle einschließlich der Lese- und Schreibzugriffe.

DAXPY berechnet yi=axi+yi mit Zahlen doppelter Genauigkeit. Jedes Element benötigt eine Multiplikation und eine Addition: zwei Gleitkommaoperationen. Das Lesen eines 8 Byte großen Werts aus jedem Array und das Zurückschreiben von 8 Byte übertragen 24 Byte. Die Intensität beträgt I=2/24≈0,0833 Gleitkommaoperationen pro Byte. Der skalare Koeffizient wird wiederverwendet; in diesem Verkehrsmodell wird er nicht für jedes Element erneut aus dem DRAM geladen.

Beide Grenzen anwenden

Sind die Spitzenrechenleistung P und die maximale Speicherbandbreite B, dann ist das Dach min⁡(P,BI). Bandbreite mal Gleitkommaoperationen pro Byte ergibt die Einheit Gleitkommaoperationen pro Sekunde. In einem doppelt logarithmischen Diagramm steigt die Bandbreitengrenze an und die Rechenleistungsgrenze verläuft waagerecht.

Bei 1.000 GFLOP/s und 100 GB/s liegt der Knickpunkt bei P/B=1000/100=10 Gleitkommaoperationen pro Byte. Unterhalb dieser Intensität liegt das Bandbreitendach niedriger, darüber das Rechenleistungsdach. DAXPY ist durch 100(2/24)≈8,33 GFLOP/s begrenzt, also weniger als 1 % der Spitzenrechenleistung des Rechners. Ein Kernel mit der Intensität 2 ist auf 200 GFLOP/s begrenzt.

Ein speichergebundener Kernel kann dennoch von zusätzlichen Kernen oder breiteren SIMD-Einheiten profitieren, solange zu wenige Anfragen gleichzeitig bearbeitet werden, um die verfügbare Bandbreite zu nutzen. Sobald die Bandbreite ausgeschöpft ist, hebt zusätzliche Rechenkapazität sein Dach nicht an. Eine höhere Bandbreite oder mehr nutzbare Berechnung pro übertragenem Byte hebt es dagegen an.

Wiederverwendung verändert die Intensität

Die Multiplikation zweier 1000 × 1000-Matrizen mit doppelter Genauigkeit führt etwa 2(1000)3=2×109 Gleitkommaoperationen aus. Wenn jedes Element der beiden Eingabematrizen und der Ausgabematrix die DRAM-Grenze einmal überquert, beträgt der gesamte Datenverkehr 24 MB. Das ergibt etwa 83 Gleitkommaoperationen pro Byte und liegt über dem Knickpunkt des Beispielrechners.

Eine naive Implementierung kann Matrixwerte wiederholt aus dem DRAM lesen. Kachelung organisiert Schleifen um Teilmatrizen, die in den Cache passen, sodass Werte für viele Operationen genutzt werden, bevor sie ersetzt werden. Der Algorithmus bleibt eine Matrixmultiplikation, aber die Implementierung überträgt pro Operation weniger Byte aus dem oder in das DRAM.

Ein Dach ist kein Messergebnis

Ein Kernel kann wegen Abhängigkeiten, Befehlsaufwand, ungünstiger Zugriffsmuster oder zu wenig paralleler Arbeit unter der Schranke bleiben. Niedrigere Leistungsgrenzen zeigen solche Einschränkungen: Fehlende SIMD-Befehle können die Rechenleistungsgrenze senken, ungünstige Zugriffsmuster dagegen die nutzbare Bandbreite. Ein Punkt unterhalb eines Dachs muss untersucht werden; das Dach allein sagt seine genaue Rechenrate nicht voraus.

Wichtige Erkenntnisse

  • Die Intensität zählt Gleitkommaoperationen pro Byte an der DRAM-Grenze.
  • Das Dach ist der kleinere Wert aus Spitzenrechenleistung und Bandbreite mal Intensität.
  • Der Knickpunkt ist die Spitzenrechenleistung geteilt durch die maximale Bandbreite.
  • Wiederverwendung kann die Intensität erhöhen, ohne den mathematischen Algorithmus zu ändern.
  • Ein Roofline-Diagramm gibt eine obere Schranke an; niedrigere Leistungsgrenzen erklären weitere Einschränkungen.
3

Arrays mit Lanes und GPU-Threads verarbeiten

Arrays bieten sich für wiederholte Operationen auf unabhängigen Elementen an, die auf Lanes und Threads verteilt werden können. Verfolge diese Idee von SIMD-Registern fester Breite über Vektorschleifen mit variabler Länge bis zu GPU-Warps. Jeder Entwurf benötigt eine wirksame Datenanordnung und genügend Arbeit, um seine Hardware auszulasten. Ein kleiner Kernel zeigt, wie Arrayindizes zu Threadindizes werden; die Übertragungskosten entscheiden mit darüber, ob die Auslagerung der gesamten Aufgabe hilft.

3.1 Arrayoperationen über SIMD-Lanes ausführen

Eine SIMD-Erweiterung teilt ein breites Register in Lanes. Ein Befehl führt in jeder Lane dieselbe Operation aus. Deshalb eignen sich regelmäßige Schleifen über unabhängige Elemente gut dafür.

Lanes und Iterationen zählen

Die Anzahl der Lanes ist die Registerbreite geteilt durch die Elementbreite. Ein 256-Bit-Register fasst acht 32-Bit-Gleitkommazahlen einfacher Genauigkeit, vier 64-Bit-Gleitkommazahlen doppelter Genauigkeit oder 32 Elemente zu je einem Byte. SSE verwendet 128-Bit-XMM-Register; AVX und AVX2 verwenden 256-Bit-YMM-Register. Im 64-Bit-Modus gibt es 16 YMM-Register. AVX-512 stellt 32 512-Bit-ZMM-Register bereit, die jeweils 16 Gleitkommazahlen einfacher Genauigkeit fassen. Arm Neon verwendet 128-Bit-Register.

Für c[i] = a[i] + b[i] über 1.000 Gleitkommazahlen verarbeiten Befehle mit acht Lanes das Array in 125 Vektoriterationen. Jede Iteration lädt zwei Vektoren, addiert deren Lanes und speichert einen Vektor. Bei 1.003 Elementen bleiben nach 125 vollständigen Iterationen drei Elemente übrig. Eine skalare Restschleife oder eine maskierte Operation verarbeitet diesen kurzen Rest, ohne über das Ende der Arrays hinaus zuzugreifen.

Acht Lanes beschreiben eine Rechenkapazität und garantieren keinen achtfachen Speedup des Programms. Initialisierung, Restverarbeitung, sequenzielle Arbeit und Speicherbandbreite beanspruchen weiterhin Zeit.

Eine Anordnung wählen, die ein Register füllt

Einfache Vektorladebefehle eignen sich gut für zusammenhängende Elemente mit Schrittweite 1. Ein Array aus {x, y, z}-Punkten mit 4 Byte pro Koordinate legt aufeinanderfolgende x-Felder im Abstand von 12 Byte ab. Eine Struktur von Arrays legt die x-Werte zusammen ab, danach die y-Werte und dann die z-Werte. Werden nur die x-Werte verarbeitet, kann nun ein zusammenhängender Ladezugriff einen Vektor füllen. Gather- und Scatter-Befehle unterstützen verstreute Adressen, verursachen aber meist höhere Zugriffskosten.

Bedingte Arbeit innerhalb der Lanes ausführen

Für c[i] = (a[i] > 0) ? a[i] : 0 erzeugt ein Vergleich eine Maske mit einem Wert pro Lane. Ein Auswahlbefehl wählt zwischen möglichen Ergebnissen, oder maskierte Befehle aktualisieren nur die ausgewählten Lanes. Inaktive Lanes behalten oder erhalten Werte entsprechend dem Maskenverhalten des Befehls.

Wenn unterschiedliche Lanes lange, unterschiedliche Verzweigungen benötigen, müssen die Befehle dieser Pfade weiterhin ausgegeben werden, wobei nur die jeweils betroffenen Lanes aktiv sind. Die Gruppe kann nicht jeder Lane einen eigenen Befehlsstrom geben. Eine Maske erhält die Korrektheit, lässt aber nicht alle Befehle dieser Pfade verschwinden.

Unabhängigkeit der Iterationen prüfen

Compiler können Schleifen automatisch vektorisieren; Programmierer können auch Bibliotheken oder Intrinsics wie _mm256_add_ps verwenden. Der Compiler muss nachweisen, dass gleichzeitige Iterationen das Ergebnis bewahren. Die Rekurrenz a[i] = a[i-1] + b[i] hängt vom neuen Wert der vorhergehenden Iteration ab und kann nicht direkt als unabhängige Elemente vektorisiert werden. Eine mögliche Überlappung von Zeigern, Aliasing genannt, kann ebenfalls eine Überlappungsprüfung zur Laufzeit nötig machen oder die Vektorisierung verhindern.

Eine Reduktion hält mehrere Teilsummen in einem Register und führt anschließend die Lanes zusammen. Das Umordnen von Gleitkommaadditionen kann die letzten Bits verändern, weil die Addition nicht assoziativ ist. Ganzzahlige Summen stimmen überein, wenn bei der gewählten Arithmetik kein Überlauf auftritt oder definierte modulare Arithmetik verwendet wird.

SIMD und Mehrkernausführung lassen sich kombinieren. Acht Kerne, die jeweils eine Addition mit acht Lanes pro Taktzyklus ausgeben, können bis zu 64 Gleitkommaadditionen pro Taktzyklus ausführen. Sie unterliegen weiterhin gemeinsamen Grenzen wie der Speicherbandbreite.

Wichtige Erkenntnisse

  • Die Anzahl der SIMD-Lanes hängt sowohl von der Registerbreite als auch von der Elementbreite ab.
  • Reste benötigen eine skalare Restschleife oder einen korrekt maskierten Zugriff.
  • Zusammenhängende Anordnungen helfen Vektorladebefehlen, ihre Lanes effizient zu nutzen.
  • Masken behandeln Bedingungen pro Element bei gemeinsamer Befehlsausgabe.
  • Abhängigkeiten und Aliasing können eine direkte Vektorisierung verhindern.
  • Bei Gleitkommareduktionen kann eine Umgruppierung der Operationen die Rundung verändern.

3.2 Jeden Schleifendurchlauf durch die Vektorlänge steuern

Eine Vektorarchitektur beschreibt eine Operation auf einer Folge von Elementen und speichert die aktive Vektorlänge in einem Register. Dasselbe Programm kann auf Implementierungen mit unterschiedlich großen Vektorregistern laufen.

Kapazität, Länge und Lanes unterscheiden

Die RISC-V-Vektorerweiterung RVV wurde 2021 in Version 1.0 ratifiziert. Sie stellt 32 Vektorregister bereit, von v0 bis v31. Jede Implementierung wählt ihre Registerbreite VLEN als Zweierpotenz. Elementbreite und Registergruppierung bestimmen, wie viele Elemente hineinpassen.

Die aktive Länge vl ist die Anzahl der Elemente, die die nächsten Vektorbefehle bearbeiten. vsetvli konfiguriert die Vektoroperation anhand der verbleibenden Elementzahl und des gewünschten Elementformats und gibt die gewählte Länge vl zurück. Der Code rückt um diesen Rückgabewert weiter. Das ist wichtig, weil portabler Code die tatsächlich von der Implementierung gewählte Länge verwenden muss.

Lanes sind die parallelen Pipelines, die die Vektoroperation ausführen. Eine Addition mit 32 Elementen auf vier Lanes benötigt nach dem Anlaufen der Pipeline etwa acht Taktzyklen. Ein Vektor mit 32 Elementen benötigt keine 32 Recheneinheiten. Längere Vektoren und mehr Lanes sind voneinander unabhängige Entwurfsentscheidungen.

Eine Schleife mit Strip-Mining aufteilen

Strip-Mining teilt eine lange Schleife in vektorgroße Stücke. Für 100 Elemente und höchstens 32 pro Operation ist 32, 32, 32 und 4 eine mögliche Folge von Längen. Jeder Durchlauf lädt den nächsten Teil, berechnet und speichert ihn und verringert die verbleibende Anzahl um den Wert von vl.

DAXPY über 1.000 Gleitkommazahlen doppelter Genauigkeit kann entsprechend 31 Durchläufe mit je 32 und einen mit acht Elementen verwenden, insgesamt also 32 Durchläufe. RVV kann gegen Ende andere zulässige Längen wählen. Deshalb verwendet die Schleife den zurückgegebenen Wert von vl, statt eine bestimmte letzte Aufteilung anzunehmen. Das Setzen der aktiven Länge behandelt den kurzen Rest ohne separate skalare Restschleife.

Das Muster zur Schleifensteuerung lautet:

  1. Fordere eine Länge für die verbleibenden Elemente an.
  2. Lade und berechne diese Anzahl von Elementen.
  3. Speichere die Ergebnisse.
  4. Setze die Zeiger weiter und ziehe die zurückgegebene Länge ab.

Ein Vektorbefehl beschreibt viele Elementoperationen. Gegenüber einem skalaren Rumpf, der für jedes Element wiederholt wird, verringert das den Aufwand für das Holen und Dekodieren von Befehlen.

Abhängige Operationen und nicht zusammenhängende Daten versorgen

Verkettung erlaubt einem verarbeitenden Vektorbefehl, mit frühen Ergebnissen zu beginnen, bevor der erzeugende Befehl spätere Elemente fertiggestellt hat. Bei einer Multiplikation mit anschließender Addition kann das erste Produkt in die Additionspipeline gelangen, während spätere Produkte noch gebildet werden.

Eine Maske, bei RVV häufig im Register v0, wählt aus, welche Elemente aktualisiert werden. Ein Ladebefehl mit fester Schrittweite greift mit einem festen Byteabstand zu. In einer zeilenweise gespeicherten 100 × 100-Matrix aus Gleitkommazahlen doppelter Genauigkeit führt ein Schritt nach unten in einer Spalte um 100 Elemente oder 800 Byte weiter. Indizierte Lade- und Speicherbefehle verwenden explizite Adressen für unregelmäßige Daten.

Sowohl Vektorarchitekturen als auch Erweiterungen fester Breite gehören in der flynnschen Taxonomie zu SIMD. Erweiterungen fester Breite kodieren bestimmte Breiten; RVV-Code beschreibt Längen, die sich an die verfügbare Hardware anpassen. Beide benötigen weiterhin eine Ausführungsreihenfolge, die die Datenabhängigkeiten der Schleife beachtet.

Wichtige Erkenntnisse

  • Die Vektorlänge gibt an, wie viele Elemente eine Operation bearbeitet; die Lanes geben an, wie viele gleichzeitig voranschreiten können.
  • RVV-Code rückt um die tatsächlich von vsetvli zurückgegebene Länge weiter.
  • Strip-Mining verarbeitet ein langes Array in vektorgroßen Stücken.
  • Verkettung überlappt abhängige Vektoroperationen Element für Element.
  • Masken, Schrittweiten und indizierte Zugriffe unterstützen weniger regelmäßige Daten.

3.3 Eine GPU mit vielen Warps auslasten

Eine CPU konzentriert ihre Ressourcen auf geringe Latenz für wenige Threads. Eine GPU konzentriert ihre Ressourcen auf hohen Durchsatz über viele datenparallele Threads. Bei der Wahl zwischen beiden muss die gesamte Aufgabe einschließlich der Datenübertragung betrachtet werden.

Threads laufen auf Streaming Multiprocessors

Eine GPU von NVIDIA enthält viele Streaming Multiprocessors, kurz SMs. Ein SM besitzt Rechen-Lanes, Warp-Scheduler, einen großen Registersatz und schnellen Shared Memory auf dem Chip. Ein „CUDA Core“ bezeichnet eine Rechen-Lane und keinen vollständigen unabhängigen Kern wie bei einer CPU. AMD nennt die entsprechende Verarbeitungsgruppe Compute Unit.

NVIDIA fasst Threads zu Warps aus jeweils 32 Threads zusammen. Ein ausgegebener Befehl wirkt auf die aktiven Threads des Warps, die jeweils eigene Registerwerte und Daten besitzen. Das ist SIMT: ein einzelner Befehl für mehrere Threads. AMD verwendet Wavefronts mit je nach Architektur 32 oder 64 Threads.

Ein SM hält viele Warps vor. Wartet einer auf den Speicher, wählt der Scheduler einen anderen bereiten Warp. Mehr bereite Threads als Lanes verdecken Latenz; sie verringern nicht die Latenz eines einzelnen DRAM-Zugriffs.

Divergenz lässt Lanes untätig

Nehmen Threads eines Warps unterschiedliche Verzweigungen, führt der Warp die benötigten Pfade aus und maskiert dabei die jeweils anderen Threads. Eine gleichmäßig aufgeteilte if-else-Verzweigung mit gleich aufwendigen Zweigen kann ungefähr die doppelte Zeit eines Pfads benötigen, weil beide Pfade ausgeführt werden müssen. Eine Verzweigung kann unproblematisch sein, wenn ihre Bedingung innerhalb jedes Warps einheitlich ist, selbst wenn verschiedene Warps unterschiedliche Pfade wählen.

Speicherzugriffe aufeinander abstimmen

Register pro Thread halten private Werte. Shared Memory pro Block ist ein vom Programm verwalteter Speicher auf dem Chip. L1- und L2-Caches ermöglichen automatische Wiederverwendung, während der globale Speicher das DRAM der GPU ist, etwa GDDR oder HBM.

Wenn 32 Threads aufeinanderfolgende Wörter zu je 4 Byte lesen, kann ihr Bereich von 128 Byte durch wenige breite Transaktionen bedient werden. Dieses Coalescing nutzt die Bandbreite effizient. Verstreute Adressen können für dieselben nutzbaren Daten viele Transaktionen benötigen. Die Wiederverwendung im Shared Memory kann wiederholten Verkehr zum globalen Speicher weiter verringern.

Die Übertragungszeit einbeziehen

Bei einer separaten GPU werden Eingaben und Ergebnisse über eine Verbindung wie PCIe oder NVLink übertragen. Das Senden von 800 MB und Empfangen von 400 MB überträgt bei effektiv 20 GB/s insgesamt 1,2 GB in 0,06 s, also 60 ms. Mit einem Kernel von 10 ms ergeben sich insgesamt 70 ms. Eine CPU, die in 50 ms fertig ist, gewinnt diesen Vergleich trotz der viel schnelleren GPU-Berechnung.

Bleiben Daten über mehrere Kernel hinweg auf der GPU, entfallen wiederholte Übertragungen. Große, regelmäßige Aufgaben können außerdem genügend nutzbare Rechenarbeit bieten, um die Kosten für Übertragung und Start aufzuwiegen. Bei kleinen, sequenziellen Aufgaben mit vielen Verzweigungen ist oft eine CPU im Vorteil.

Bei geeigneter Arbeit weiter spezialisieren

Ein heterogenes System verwendet die CPU für die Ausführung von Programm und Betriebssystem und einen Beschleuniger für geeignete Teile. Domänenspezifische Beschleuniger wie TPUs und NPUs widmen ihre Hardware einer enger gefassten Aufgabe, häufig der Matrixmultiplikation mit 8-Bit-Ganzzahlen oder 16-Bit-Gleitkommazahlen. Spezialisierung kann in diesem Bereich die Rechenleistung pro Watt verbessern und verringert zugleich die Bandbreite der Aufgaben, die die Hardware gut bewältigt.

Wichtige Erkenntnisse

  • Ein SM plant Warps ein; ein CUDA Core ist eine Rechen-Lane.
  • NVIDIA-Warps enthalten 32 Threads mit getrennten Daten und gemeinsamer Befehlsausgabe.
  • Bereite, vorgehaltene Warps verdecken Speicherwartezeiten.
  • Divergenz und verstreute Zugriffe verschwenden Lane-Zeit und Speicherbandbreite.
  • Bei Auslagerungsentscheidungen zählen Übertragungen ebenso wie die Kernelzeit.
  • Spezialisierte Beschleuniger tauschen Flexibilität gegen Effizienz in einem engeren Bereich.

3.4 Arrayelemente GPU-Threads zuordnen

Ein GPU-Kernel läuft einmal pro gestartetem Thread. Der Host startet ein Grid aus Threadblöcken, und jeder Thread berechnet, welchen Teil der Daten er bearbeitet. CUDA nennt die CPU den Host und die GPU das Gerät; OpenCL verwendet die verwandten Begriffe Work-Item und Work-Group.

Einen eindeutigen Index berechnen

Bei einem eindimensionalen Start lautet der Elementindex blockIdx.x * blockDim.x + threadIdx.x. Bei 256 Threads pro Block bearbeitet Thread 5 in Block 2 das Element 517: Die beiden vorhergehenden Blöcke umfassen 512 Elemente, und der Thread ergänzt einen Versatz von fünf. Thread- und Blockindizes beginnen bei null.

Ein SAXPY-Kernel wendet eine Multiplikation und eine Addition auf jede Gleitkommazahl an:

__global__ void saxpy(int n, float a, float *x, float *y) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) {
        y[i] = a * x[i] + y[i];
    }
}

Das Grid ersetzt die gewöhnliche Schleife über die Elemente. Jeder aktive Thread aktualisiert sein eigenes y[i]; benachbarte Threads verwenden benachbarte Adressen und unterstützen so Coalescing.

Die Blockzahl aufrunden

Für 1.000.000 Elemente und 256 Threads pro Block benötigt das Grid ⌈1000000/256⌉=3907 Blöcke. Diese starten 1.000.192 Threads. Die letzten 192 haben Indizes außerhalb des Arrays, sodass die Bedingung i < n ihre Speicherzugriffe verhindert. Abrunden würde zu wenige Threads starten und gültige Elemente unbearbeitet lassen.

Ein Block mit 256 Threads bildet acht Warps. Blöcke können beliebigen SMs zugewiesen und in beliebiger Reihenfolge ausgeführt werden. Die Korrektheit des Programms darf nicht davon abhängen, dass Block 0 vor Block 1 fertig wird.

Arbeit von Host und Gerät organisieren

Ein typischer Host reserviert Gerätespeicher, kopiert die Eingaben, startet saxpy<<<3907, 256>>>(n, 2.0f, d_x, d_y) und erhält die Ergebnisse. Der Start ist asynchron: Die CPU kann fortfahren, während der Kernel läuft. Der Host muss durch Synchronisation oder eine geeignete blockierende Ergebniskopie warten, bevor er die fertigen Daten verwendet.

Innerhalb eines Blocks zusammenarbeiten

Threads eines Blocks können Werte über Shared Memory austauschen und sich bei __syncthreads() treffen. Jeder Thread, der an dieser blockweiten Barriere teilnimmt, muss sie erreichen. Die Barriere innerhalb von if (i < n) zu platzieren, ist unsicher, wenn nur einige Threads die Bedingung erfüllen.

Für eine Reduktion von 1.024 Werten im Shared Memory addieren 512 Threads Paare, dann führen 256 die Ergebnisse zusammen, danach 128 und so weiter. Zehn Halbierungsstufen lassen eine Summe übrig. Eine Barriere zwischen den Stufen verhindert, dass ein Thread ein Teilergebnis verarbeitet, bevor der erzeugende Thread es schreibt.

Ein gewöhnlicher Start besitzt keine gridweite Barriere. Getrennte Blöcke können Teilsummen schreiben, die ein zweiter Kernel zusammenführt; alternativ können geeignete atomare Operationen ein globales Ergebnis aktualisieren. Eine Blockbarriere allein kann verschiedene Blöcke nicht koordinieren. Eine Schleife mit Grid-Schrittweite ist ein weiteres Zuordnungsmuster: Jeder Thread bearbeitet mehrere Elemente und rückt dabei jeweils um die gesamte Grid-Größe weiter.

Wichtige Erkenntnisse

  • Berechne Indizes aus Blockgröße, Blockindex und Threadindex.
  • Runde Blockzahlen auf und sichere Zugriffe außerhalb des Bereichs ab.
  • Kernelstarts erfolgen asynchron zum Host.
  • Shared Memory und __syncthreads() unterstützen die Zusammenarbeit innerhalb eines Blocks.
  • Gewöhnliche Blöcke laufen unabhängig; das Zusammenführen ihrer Ergebnisse benötigt einen anderen Mechanismus.
4

Speicher gemeinsam nutzen und Cachebesitz verfolgen

Ein gemeinsamer Adressraum ermöglicht es Threads, Werte durch gewöhnliche Speicheroperationen auszutauschen. Private Caches machen diese Operationen schnell, erzeugen aber mehrere Kopien, die koordiniert werden müssen. Verfolge eine Reduktion von lokaler Arbeit bis zu gemeinsamen Ergebnissen und anschließend die Berechtigungen, die Cachekopien kohärent halten. Der Speicherbedarf von Verzeichnissen und False Sharing verbinden diese Korrektheitsmechanismen mit den Leistungskosten der Datenplatzierung.

4.1 Einen Adressraum teilen und Teilergebnisse zusammenführen

Ein Multiprozessor mit gemeinsamem Speicher stellt seinen Prozessoren einen physischen Adressraum zur Verfügung. Threads kommunizieren durch Lade- und Speicherzugriffe auf gemeinsame Variablen und halten zugleich private Werte wie lokale Teilsummen vor.

Gemeinsame Adressen können unterschiedlich viel kosten

Bei UMA, dem gleichförmigen Speicherzugriff, ist die Speicherzugriffszeit von jedem Prozessor aus ungefähr gleich. Bei NUMA, dem nicht gleichförmigen Speicherzugriff, erreicht ein Sockel seinen lokalen Speicher schneller als den Speicher eines anderen Sockels. Der Adressraum wird gemeinsam genutzt, obwohl der physische Speicher verteilt ist.

Bei 70 % lokalen Zugriffen mit 80 ns und 30 % entfernten Zugriffen mit 140 ns beträgt das gewichtete arithmetische Mittel 0,7(80)+0,3(140)=98 ns. Werden Daten nahe bei ihrem Hauptnutzer abgelegt, sinkt der Anteil entfernter Zugriffe. Würde man jeden Zugriff als lokal zählen, würde man die Zeit unterschätzen.

Eine verbreitete Cacheanordnung gibt jedem Kern private L1-Befehls- und Datencaches, häufig einen privaten L2-Cache und einen gemeinsam genutzten Cache der letzten Ebene. Ein Ring oder Gitter verbindet die Kerne und Caches. Gemeinsamer Speicher beschreibt die Adressierung; er verlangt nicht, dass jeder Kern denselben Cache nutzt.

Aufteilen, berechnen und reduzieren

Um 64.000 Werte auf 64 Kernen zu summieren, bearbeitet jeder Kern 1.000 Werte. Die 64 Teilsummen können in einem Reduktionsbaum zusammengeführt werden. Die Anzahl aktiver Addierer halbiert sich auf jeder Stufe: 32, 16, 8, 4, 2 und 1. Sechs Stufen führen die Teilergebnisse zusammen.

Mit etwa 1.000 lokalen Additionsschritten und sechs Schritten zum Zusammenführen ergeben sich vor Berücksichtigung des Aufwands etwa 1.006 Schritte auf dem längsten Pfad. Der Baum vermeidet, dass jede Eingabe einen gemeinsamen Zähler aktualisiert. Jede Stufe hängt von den fertigen Werten der vorherigen Stufe ab, sodass sich die Arbeitseinheiten zwischen den Stufen an Barrieren treffen.

OpenMP kann dies mit #pragma omp parallel for reduction(+:sum) ausdrücken. Die Anweisung teilt Iterationen auf, gibt Threads private Teilsummen und führt sie zusammen. POSIX-Threads bieten eine explizitere Kontrolle über die Threadverwaltung.

Eine Aktualisierung unteilbar machen

Eine atomare Lese-Änderungs-Schreiboperation macht eine Aktualisierung aus Sicht anderer Prozessoren unteilbar. Atomarer Austausch und Fetch-and-Add sind Beispiele. Ein Laden mit anschließendem gewöhnlichem Speichern sind zwei getrennte Operationen, sodass ein anderer Thread dazwischen eingreifen kann.

RISC-V stellt lr.w und sc.w bereit. Der reservierende Ladebefehl liest ein Wort und legt eine Reservierung an. Der bedingte Speicherbefehl versucht zu schreiben und meldet Erfolg oder Misserfolg. Ein zwischenzeitlicher Schreibzugriff auf die reservierte Stelle lässt den Versuch fehlschlagen; die Software versucht es erneut. Die Reservierung blockiert keine anderen Prozessoren, und ein Fehlschlag kann auch aus anderen zulässigen Gründen auftreten. Diese Grundoperationen unterstützen Synchronisationsmechanismen.

Gemeinsame Engpässe beachten

Kann jeder Kern Daten mit 15 GB/s kontinuierlich verarbeiten, der Sockel aber nur 60 GB/s liefern, schöpfen etwa vier solche Datenströme die Bandbreite aus. Mehr Kerne können die Datenrate des Sockels nicht erhöhen. Auch Kommunikation über Caches verursacht Aufwand: Ein schreibender Kern ohne Schreibberechtigung muss den Besitz erlangen und andere Kopien invalidieren. Ein Kern, der bereits einen Block in Modified hält, kann lokal weiterschreiben; spätere Leser müssen möglicherweise eine neue Kopie holen.

Wichtige Erkenntnisse

  • Gemeinsamer Speicher bedeutet einen Adressraum; private Daten und Caches bleiben möglich.
  • Bei NUMA beeinflusst die Datenplatzierung die Rechenleistung.
  • Lokale Teilsummen und ein Reduktionsbaum begrenzen die Ressourcenkonkurrenz.
  • Barrieren trennen voneinander abhängige Arbeitsphasen.
  • Atomare Operationen sichern unteilbare Aktualisierungen; LR/SC wiederholt fehlgeschlagene Versuche.
  • Kerne teilen sich die Speicherbandbreite und verursachen Aufwand beim Übertragen des Besitzes.

4.2 Kopien einer Speicherstelle kohärent halten

Private Caches verringern die Latenz, können aber mehrere Kopien derselben Speicherstelle halten. Cachekohärenz verhindert, dass diese Kopien widersprüchliche Folgen von Schreibzugriffen auf diese Stelle zeigen.

Warum die Aktualisierung des Speichers nicht genügt

Zu Beginn steht X = 0 im Speicher. Kern A liest den Wert null und speichert ihn im Cache; Kern B tut dasselbe. A schreibt den Wert eins in seinen Cache mit Rückschreibverfahren. Ohne Kohärenzprotokoll kann B einen Treffer im eigenen Cache haben und weiterhin null lesen. Das Durchschreiben in den Speicher würde Bs bereits zwischengespeicherte Kopie nicht korrigieren.

Kohärenz arbeitet auf der Ebene von Cacheblöcken, üblicherweise 64 Byte. Ein Controller verfolgt den Zustand jedes Blocks und befolgt Protokollregeln, wenn Prozessoren ihn lesen oder schreiben. Migration verschiebt nutzbare Daten in den Cache ihres aktuellen Nutzers. Replikation ermöglicht mehreren Lesern, unveränderte Kopien zu halten. Kohärenz muss beide Vorteile bewahren und zugleich Schreibzugriffe steuern.

Drei erforderliche Eigenschaften
EigenschaftWas sie verlangt
Programmreihenfolge für eine SpeicherstelleEin Prozessor liest seinen eigenen vorherigen Schreibzugriff, wenn kein zwischenzeitlicher Schreibzugriff ihn ersetzt.
SchreibpropagierungEin Schreibzugriff wird schließlich für die anderen Prozessoren sichtbar.
SchreibserialisierungAlle Prozessoren stimmen in der Reihenfolge der Schreibzugriffe auf diese Stelle überein.

Wird auf eine Speicherstelle erst der Wert eins und danach der Wert zwei geschrieben, können Leser nicht unterschiedlicher Meinung darüber sein, welcher Schreibzugriff später kam. Erst den späteren und dann den früheren Schreibzugriff zu beobachten, würde diese Reihenfolge umkehren. Ein neuer nachfolgender Schreibzugriff könnte natürlich erneut den Wert eins speichern; Serialisierung betrifft Schreibereignisse und nicht die Frage, ob ein Zahlenwert jemals wieder auftreten darf.

Besitz und Kopien steuern

In einem Schreibinvalidierungsprotokoll erlangt ein schreibender Kern exklusive Schreibberechtigung und invalidiert andere Cachekopien. Ein späterer Lesezugriff auf einen invalidierten Block führt zu einem Fehlzugriff und holt aktuelle Daten. Dies ist ein kohärenzbedingter Fehlzugriff, zusätzlich zu obligatorischen, kapazitätsbedingten und konfliktbedingten Fehlzugriffen.

Ein Schreibaktualisierungsprotokoll sendet neue Werte stattdessen an vorhandene Kopien. Wiederholte Schreibzugriffe können dies aufwendig machen. Snooping sendet Kohärenzanfragen an alle, damit Caches reagieren können. Ein Kohärenzverzeichnis erfasst Mitnutzer und leitet Nachrichten an die betreffenden Caches.

Kohärenz, Reihenfolge und Atomarität

Kohärenz betrifft eine Speicherstelle. Ein Speicherkonsistenzmodell definiert zulässige beobachtbare Reihenfolgen und Ergebnisse von Lese- und Schreibzugriffen, einschließlich Operationen auf verschiedenen Stellen. Sequenzielle Konsistenz verlangt ein Ergebnis, das einer Verschachtelung entspricht, die die Programmreihenfolge jedes Prozessors bewahrt. Schwächere Modelle erlauben mehr Umordnungen; Fence-Befehle erzwingen bei Bedarf die erforderliche Reihenfolge.

Weder kohärente Kopien noch eine konsistente Reihenfolge machen eine aus mehreren Befehlen bestehende Erhöhung atomar. Angenommen, zwei Threads erhöhen einen gemeinsamen Zähler, der anfangs fünf beträgt. Eine mögliche Folge ist: A liest fünf, B liest fünf, A schreibt sechs, B schreibt sechs. Jeder Lese- und Schreibzugriff kann kohärent sein, dennoch beträgt der Endstand sechs statt sieben. Das Programm benötigt eine atomare Aktualisierung oder geeignete Synchronisation, um beide Erhöhungen zu erhalten.

Wichtige Erkenntnisse

  • Kohärenz ist auch nötig, wenn Caches in den Speicher durchschreiben.
  • Kohärente Systeme bewahren die Programmreihenfolge für eine Speicherstelle, propagieren Schreibzugriffe und serialisieren sie.
  • Schreibinvalidierung entfernt andere nutzbare Kopien, bevor ein neuer Besitzer schreibt.
  • Invalidierte Daten können kohärenzbedingte Fehlzugriffe verursachen.
  • Konsistenzmodelle behandeln die Reihenfolge über verschiedene Speicherstellen hinweg.
  • Ein kohärenter Lesezugriff und ein kohärenter Schreibzugriff bleiben zwei getrennte Operationen.

4.3 Besitzwechsel bei MSI und MESI verfolgen

Ein Snooping-Cachecontroller überwacht Kohärenzanfragen auf einer Verbindung mit Rundsendung. Um ein Protokoll zu verfolgen, halte für die Blockkopie jedes Kerns einen Zustand fest und aktualisiere nach jedem Zugriff alle betroffenen Kopien.

Zustände als Berechtigungen lesen
ZustandNutzbare Kopie?Wer darf sie sonst besitzen?Ist der Speicher aktuell?
Modified (M)Ja, Lesen und SchreibenKeine andere gültige KopieNein
Shared (S)Ja, LesenAndere Leser dürfen Kopien besitzenJa
Invalid (I)NeinAndere Caches dürfen Kopien besitzenHängt von deren Zustand ab
Exclusive (E), nur MESIJa, Lesen und stiller Übergang zum SchreibenKeine andere gültige KopieJa

Im grundlegenden MSI sendet ein Lesefehlzugriff eine Busleseanfrage und lädt den Block in S. Das Schreiben eines Blocks in S benötigt ein Upgrade, um andere Kopien zu invalidieren. Das Schreiben aus I benötigt eine exklusive Leseanfrage, um Daten zu holen und Besitz zu erlangen. Der schreibende Kern endet in M. Ein Treffer in M benötigt keine Kohärenztransaktion.

Fünf Zugriffe verfolgen

Beginne mit X = 0 im Speicher und A und B jeweils in Invalid.

  1. A liest X. Eine Busleseanfrage liefert null. Zustände: A = S, B = I.
  2. B liest X. Eine weitere Busleseanfrage liefert null. Zustände: A = S, B = S.
  3. A schreibt eins. Sein Upgrade invalidiert B. Zustände: A = M, B = I.
  4. B liest X. B hat einen Fehlzugriff; A liefert eins und wechselt nach S. Im grundlegenden MSI wird auch der Speicher wieder aktuell. Zustände: A = S, B = S.
  5. B schreibt zwei. Sein Upgrade invalidiert A. Zustände: A = I, B = M.

Jeder Zugriff in diesem Ablauf benötigt eine Bustransaktion. Der vierte Zugriff ist die wichtige Prüfung des Besitzes: Der Speicher allein enthielt noch den alten Wert, bevor A seine veränderten Daten lieferte.

Was Exclusive spart

MESI ergänzt E für eine einzelne unveränderte Cachekopie. Liest A einen nicht zwischengespeicherten Block und hat kein anderer Cache ihn, erhält A den Zustand E. Ein anschließender Schreibzugriff ändert E stillschweigend in M, weil keine anderen Kopien invalidiert werden müssen. MSI würde zunächst S laden und für diesen Schreibzugriff dann ein Upgrade senden.

Liest ein anderer Kern, während A den Zustand E hält, wechseln beide nach S. M und E haben beide einen gültigen Besitzer, aber nur M enthält Daten, die neuer als der Speicherinhalt sind.

Wiederholte Schreibzugriffe und Skalierung

Ein schreibender Kern, der M erlangt hat, kann den Block zehnmal aktualisieren, ohne zehn neue Invalidierungen auszulösen. Ein Schreibaktualisierungsverfahren würde die geänderten Werte an die Mitnutzer senden.

Snooping mit Rundsendung wird aufwendig, wenn immer mehr Kerne jede Anfrage überwachen. Verzeichnisstrukturen verringern diese Auffächerung. Ausgefeiltere Protokolle ergänzen nützliche Zustände: Der Owned-Zustand von MOESI erlaubt eine veränderte gemeinsam genutzte Kopie, und MESIF bestimmt einen Mitnutzer im Forward-Zustand zur Beantwortung von Anfragen.

Wichtige Erkenntnisse

  • MSI verfolgt Kopien in den Zuständen Modified, Shared und Invalid.
  • Ein schreibender Kern benötigt exklusiven Besitz; Treffer in Modified bleiben lokal.
  • Ein entfernter Lesezugriff veranlasst im grundlegenden MSI den Besitzer in Modified, aktuelle Daten zu liefern und nach Shared zu wechseln.
  • Der Exclusive-Zustand von MESI lässt einen einzelnen Leser mit unveränderter Kopie ohne Upgrade-Transaktion schreiben.
  • Exclusive und Modified haben beide einen Besitzer, aber nur Modified ist verändert.

4.4 Mitnutzer erfassen und unabhängige Daten trennen

Jede Kohärenzanfrage an alle zu senden, wird auf großen Rechnern aufwendig. Ein Kohärenzverzeichnis erfasst, welche Caches einen Block möglicherweise besitzen, sodass Anfragen an diese Caches gehen können. Dieselbe Erfassung auf Blockebene erklärt auch ein häufiges Leistungsproblem: False Sharing.

Den Heimatknoten eines Blocks fragen

Jeder Block besitzt einen Eintrag im Heimatverzeichnis. Dieser hält fest, ob der Block nicht im Cache, gemeinsam genutzt oder verändert ist und welche Caches ihn besitzen. Heimatknoten sind auf Knoten oder Verzeichnisteile verteilt; so verteilen sich Speicherbedarf und Anfragebearbeitung.

Ein Lesefehlzugriff geht an den Heimatknoten. Hat der Speicher die aktuellen Daten, kann er sie liefern, und das Verzeichnis erfasst den neuen Mitnutzer. Besitzt ein anderer Cache eine Modified-Kopie, leitet der Heimatknoten die Anfrage an diesen Besitzer weiter, damit aktuelle Daten geliefert werden können. In einem grundlegenden Verzeichnisprotokoll wird dadurch auch der Speicher wieder aktuell.

Um ohne bestehenden Besitz im Zustand Modified zu schreiben, fragt ein Kern den Heimatknoten nach Berechtigung. Das Verzeichnis sendet Invalidierungen an erfasste Mitnutzer, wartet auf Bestätigungen und gewährt exklusiven Besitz. Wiederholte Schreibtreffer in M benötigen dann keine weiteren Kohärenznachrichten. Der Umweg über das Verzeichnis erhöht die Latenz, aber Punkt-zu-Punkt-Verkehr vermeidet es, jeden Cache nach jedem Block zu fragen. Snoop-Filter auf dem Chip erfüllen einen verwandten Zweck, indem sie Anfragen auf mögliche Besitzer beschränken.

Speicherbedarf des Verzeichnisses abschätzen

Ein vollständiger Präsenzvektor enthält ein Bit pro Kern und Block. Bei 64 Kernen sind das 64 Bit oder acht Byte. Im Verhältnis zu einem 64 Byte großen Datenblock kosten allein die Präsenzbits 8/64=0,125, also 12,5 %. Bei 256 Kernen kostet der 32 Byte große Vektor 50 %. Zustandsbits kommen hinzu. Begrenzte Mitnutzerlisten, gröbere Vektoren und die Erfassung nur zwischengespeicherter Blöcke verringern diesen Speicherbedarf.

False Sharing erkennen

True Sharing tritt auf, wenn Kerne Daten über dasselbe Wort austauschen. False Sharing tritt auf, wenn sie auf verschiedene Variablen innerhalb eines Cacheblocks zugreifen und mindestens einer schreibt. Die Variablen sind im Programm unabhängig, aber die Kohärenzeinheit ist größer als jede der beiden Variablen.

Zwei Threads erhöhen getrennte 8 Byte große Zähler an 0x1000 und 0x1008. Bei 64 Byte großen Blöcken sind ihre Blocknummern ⌊4096/64⌋=64 und ⌊4104/64⌋=64. Jeder Besitzwechsel überträgt die Berechtigung für beide Zähler zusammen. Häufige abwechselnde Schreibzugriffe können den Block zwischen Caches hin- und herwandern lassen, obwohl keiner der Threads den Wert des anderen benötigt.

Eine Verschiebung des zweiten Zählers nach 0x1040 legt ihn in Block 65. Padding oder Ausrichtung kann Daten pro Thread trennen; auch die Gruppierung von Werten nach ihrem schreibenden Thread hilft. Ein lokaler Akkumulator, der einmal zurückgeschrieben wird, verringert den Verkehr für Besitzwechsel, ohne jeden Wert auffüllen zu müssen.

Auch ein schreibender Kern und ein Leser einer benachbarten Variablen können von False Sharing betroffen sein: Der schreibende Kern invalidiert den ansonsten nutzbaren Block des Lesers. Zwei Leser allein verursachen es nicht. False Sharing erhöht Verkehr und Verzögerung; es führt nicht selbst dazu, dass Aktualisierungen getrennter Variablen falsche Werte erzeugen. Miss Zugriffsmuster und die Platzierung von Cachezeilen, bevor du eine Datenanordnung änderst.

Wichtige Erkenntnisse

  • Kohärenzverzeichnisse senden Nachrichten über den Heimatknoten eines Blocks an die erfassten Besitzer.
  • Der Speicherbedarf von Präsenzvektoren wächst sowohl mit der Kernzahl als auch mit der Blockzahl.
  • False Sharing betrifft verschiedene Variablen in einem Block und mindestens einen schreibenden Kern.
  • Trenne den Besitz durch Padding, Platzierung oder weniger gemeinsame Schreibzugriffe.
5

Knoten verbinden und im Maßstab eines Warehouse-Scale Computers betreiben

Über einen einzelnen Rechner mit gemeinsamem Speicher hinaus tauschen Knoten Nachrichten über ein Netzwerk aus. Ein Cluster muss Datenplatzierung und Kommunikation ebenso sorgfältig organisieren wie die Aufteilung der Berechnungen. Im Maßstab eines Warehouse-Scale Computers kommen Stromversorgung, Kühlung und alltägliche Hardwareausfälle zum Netzwerk hinzu. Vergleiche die Netzwerkkapazität anhand eines kritischen Schnitts und beurteile dann mit Energie- und Latenzberechnungen, wie ein großer Rechnerverbund einen zuverlässigen Dienst bereitstellt.

5.1 Knoten mit privatem Speicher und ihre Netzwerke vergleichen

Ein Cluster verbindet vollständige Rechner mit jeweils eigenem Speicher und Betriebssystem. Die Knoten arbeiten durch explizite Nachrichten zusammen. Datenplatzierung und Kommunikationskosten werden daher Teil des Leistungsmodells des Programms.

Daten aufteilen und Ergebnisse zusammenführen

MPI, das Message Passing Interface, gibt jedem Prozess einen Rang und stellt Operationen wie Senden, Empfangen, Rundsenden und Reduzieren bereit. Ein SPMD-Programm kann anhand der Ränge die Daten jedes Prozesses auswählen. Ein Zeiger im privaten Adressraum eines Knotens ist kein gewöhnlicher Verweis über gemeinsamen Speicher auf die Daten eines anderen Knotens.

Sind eine Million Werte bereits auf 100 Knoten verteilt, summiert jeder Knoten lokal 10.000. Eine Baumreduktion führt die Teilsummen in sieben Runden zusammen, denn ⌈log⁡2100⌉=7. Diese Runden umfassen Netzwerknachrichten und nicht nur lokale Additionen. Werden Daten nahe bei der Arbeit gehalten, die sie verarbeitet, sinkt der Übertragungsbedarf.

Cluster skalieren mit Standardkomponenten, und ausgefallene Hardware kann ersetzt werden. Eine Anwendung benötigt nach dem Ausfall eines Knotens möglicherweise dennoch eine Wiederherstellung oder einen Neustart; austauschbare Knoten allein erhalten den Fortschritt einer unterbrochenen Aufgabe nicht.

Mehr als die Verbindungsgeschwindigkeit messen

Latenz ist die Zeit, bis eine Nachricht eintrifft. Verbindungsbandbreite ist die Datenrate einer einzelnen Verbindung. Die Gesamtbandbreite des Netzwerks summiert die Verbindungskapazitäten und beschreibt den idealen Gesamtwert bei Auslastung aller Verbindungen. Die Bisektionsbandbreite summiert die Kapazität über den Schnitt mit der geringsten Kapazität, der die Knoten in gleich große Hälften teilt.

Vergleiche für Verbindungen gleicher Kapazität mit der Bandbreite B Netzwerke mit 64 Knoten anhand einer einheitlichen Zählweise für Verbindungen:

TopologieVerbindungenGesamtkapazitätBisektionskapazität
Ring6464B2B
8 × 8-Gitter112112B8B
8 × 8-Torus128128B16B
6-dimensionaler Hyperwürfel192192B32B
Vollständig verbunden20162016B1024B

Das Gitter hat acht Reihen mit je sieben horizontalen Verbindungen und acht Spalten mit je sieben vertikalen Verbindungen, also 112. Verbindungen zwischen den gegenüberliegenden Rändern beider Dimensionen ergeben die 128 des Torus. Jeder Hyperwürfelknoten hat sechs Nachbarn, was 64(6)/2=192 Verbindungen ergibt, weil jede Verbindung an zwei Endpunkten gezählt wird.

Den Schnitt verfolgen und dann die Kosten betrachten

Ein in zwei Hälften geteilter Ring wird von nur zwei Verbindungen geschnitten. Viele Nachrichten können daher an dieser Stelle konkurrieren, obwohl der Ring insgesamt 64 Verbindungen hat. Ein vollständig verbundenes Netzwerk hat 32(32)=1024 Verbindungen zwischen seinen beiden Hälften, benötigt aber insgesamt 64(63)/2=2016 Verbindungen.

Mehr Verbindungen können die Bandbreite verbessern und die Zahl der Zwischenstationen senken, erhöhen aber den Bedarf an Switch-Ports, Kabeln und Leistungsaufnahme. Gemeinsame Busse haben eine einzige gemeinsam genutzte Kommunikationsressource; Gitter und Tori verteilen Verbindungen über den Raum. Große Cluster verwenden oft mehrstufige vermittelte Netzwerke wie Fat Trees. Ihr Nutzen hängt ebenso vom Verkehrsmuster wie von ihrer Gesamtkapazität ab. Für die Kommunikation zwischen Rechnerhälften zeigt die Bisektion eine Grenze, die die Gesamtbandbreite verbirgt.

Wichtige Erkenntnisse

  • Clusterknoten nutzen private Adressräume und explizite Kommunikation.
  • MPI-Ränge identifizieren Prozesse; kollektive Operationen führen verteilte Arbeit zusammen.
  • Nachrichtenrunden verursachen zusätzlichen Aufwand über die lokale Berechnung hinaus.
  • Die Gesamtbandbreite misst die gesamte Verbindungskapazität; die Bisektionsbandbreite misst einen kritischen Schnitt durch den Rechner.
  • Netzwerkkapazität steht in einem Zielkonflikt mit Ports, Kabeln, Leistungsaufnahme und Zwischenstationen.

5.2 Ein Rechenzentrum als einen Rechner messen

Ein Warehouse-Scale Computer verbindet Zehntausende Server mit Stromversorgung, Kühlung und einem Netzwerk, um Internetdienste bereitzustellen. Unabhängige Anfragen liefern parallele Arbeit, während Stapelverarbeitungs-Frameworks wie MapReduce große Datenverarbeitungsaufgaben auf Rechner verteilen.

Den Entwurf auf den Dienst abstimmen

Warehouse-Scale-Systeme legen Wert auf Kosten pro Anfrage, Energieeffizienz und Verfügbarkeit. Die Software wiederholt Arbeit, repliziert Daten und leitet Anfragen an ausgefallenen Rechnern vorbei. Ein Supercomputer konzentriert sich häufiger auf ein einzelnes eng gekoppeltes wissenschaftliches Programm und ein schnelles Verbindungsnetz.

Server sind mit Switches an der Spitze ihrer Racks verbunden, die wiederum über höhere Switch-Ebenen verbunden sind. Zusätzliche Ebenen erhöhen die Kommunikationslatenz. Aufwärtsführende Verbindungen sind oft überbucht, ihre Kapazität liegt also unter der Gesamtkapazität der Serververbindungen. Manche nichtblockierenden Netzwerke nach dem Clos-Prinzip bieten auf den oberen Ebenen genügend Kapazität, um diese Einschränkung zu vermeiden.

Vierzig Server mit Verbindungen von je 10 Gbit/s bieten einem Rack-Switch 400 Gbit/s. Vier aufwärtsführende Verbindungen mit je 25 Gbit/s stellen 100 Gbit/s bereit, das Verhältnis beträgt also 4:1. Senden alle Server gleichzeitig aus dem Rack und teilen sich die Kapazität gleichmäßig, erreicht jeder durchschnittlich 2,5 Gbit/s. Ein gering belasteter Server kann mehr nutzen, wenn andere untätig sind.

Anlagenaufwand von nutzbarer Berechnung trennen

Die Effektivität des Energieeinsatzes, PUE, ist die Gesamtenergie der Anlage geteilt durch die Energie der IT-Geräte im selben Zeitraum. Zehn MW gleichbleibende IT-Last und 1,5 MW für Kühlung und Verteilungsverluste ergeben PUE=11,5/10=1,15. Der Idealwert ist 1,0. Google meldete für 2025 einen jährlichen PUE-Wert von 1,09 über alle seine Rechenzentren hinweg.

PUE misst den Anlagenaufwand und nicht die nutzbaren Berechnungen pro Joule. Untätige oder ineffiziente Server können innerhalb der IT Energie verschwenden, selbst wenn die Anlage einen ausgezeichneten PUE-Wert hat.

Bei 50.000 Servern mit durchschnittlich 300 W beträgt die IT-Leistungsaufnahme 15 MW. Bei PUE 1,2 beträgt die Leistungsaufnahme der Anlage 18 MW. Über 8.760 Stunden verbraucht sie damit 157.680 MWh; allein der Zusatzaufwand verbraucht 26.280 MWh. Stromversorgungsanlagen, Kühlung, Strom, Server und Gebäude tragen alle zu den Betriebskosten bei.

Geringe Last kann dennoch viel Leistung aufnehmen

Energieproportionalität bedeutet, dass die Leistungsaufnahme proportional zur Last steigen sollte. Ein Server mit 150 W im Leerlauf und 300 W Spitzenleistung, dessen Leistungsaufnahme linear steigt, benötigt bei 30 % Last 150+0,3(150)=195 W. Er benötigt 65 % der Spitzenleistung für 30 % der maximalen Arbeit. Frühere Messungen an Warehouse-Scale-Systemen ergaben, dass viele Server bei etwa 10 % bis 50 % Auslastung arbeiteten. Deshalb ist die Leistungsaufnahme im Leerlauf wichtig.

Ausfälle und langsame Antworten einplanen

Fallen 50.000 Server jeweils durchschnittlich einmal in zehn Jahren aus, sind im Rechnerverbund 5.000 Ausfälle pro Jahr zu erwarten, etwa 14 pro Tag. Diese Erwartung begründet Redundanz und erneute Versuche; sie legt nicht genau 14 Ausfälle für jeden Tag fest.

Eine Anfrage, die Antworten vieler Server benötigt, wartet auf die langsamste erforderliche Antwort. Ist jeder von 100 Servern unabhängig von den anderen mit einer Wahrscheinlichkeit von 1 % langsam, beträgt die Wahrscheinlichkeit, dass keiner langsam ist, 0,99100. Damit ist mindestens einer mit der Wahrscheinlichkeit 1−0,99100≈0,634 langsam. Die Tail-Latenz eines Servers wird bei großer Auffächerung zu einer häufigen Verzögerung der Anfrage.

Wichtige Erkenntnisse

  • Beim Entwurf von Warehouse-Scale-Systemen werden Dienstdurchsatz, Energie, Kosten und Verfügbarkeit gegeneinander abgewogen.
  • Überbuchte aufwärtsführende Verbindungen begrenzen den gleichzeitigen Datenverkehr aus dem Rack.
  • PUE misst den Anlagenaufwand, während die Servereffizienz die nutzbare Arbeit innerhalb der IT misst.
  • Die Leistungsaufnahme im Leerlauf macht eine geringe Auslastung kostspielig.
  • In großen Rechnerverbünden sind Ausfälle alltäglich, und Auffächerung verstärkt die Tail-Latenz.

Mehrkernprozessoren: Beispiele

5 Interaktive Lektionen

1

Eine nutzbare Quelle paralleler Arbeit wählen

15 Schritte
Verfolge eine Arbeitslast von Leistungsgrenzen zu Befehlsströmen und nutze dann bereite Threads, um Speicherwartezeiten abzudecken.
  1. 1
    EinführungMehr Arbeit ohne einen heißeren Takt

    Ein Dienst muss mehr Aufgaben bearbeiten, aber eine höhere CPU-Taktfrequenz würde sein Leistungsbudget überschreiten. Parallele Hardware erledigt innerhalb eines festen Leistungsbudgets mehr. Die Entwickler können Kerne hinzufügen (MIMD), Datenoperationen verbreitern (SIMD) oder mehr Threads bereithalten (Multithreading). Jede Wahl benötigt eine geeignete Arbeitsquelle. Bestimme zuerst, was gleichzeitig laufen kann, und frag dann, wie diese Arbeit die Hardware erreicht und ob der Vorteil eine kürzere Antwortzeit oder eine größere Dienstkapazität (Durchsatz) ist.

  2. 2
    ErklärungDie Spannung wirkt im Quadrat

    Für die dynamische Leistungsaufnahme gilt näherungsweise P≈CV2f. Bei unveränderter Kapazität multipliziert eine Senkung von Spannung und Frequenz auf 85 % die Leistungsaufnahme mit 0,85×0,85×0,85=0,614125. Diese starke Senkung hilft zu erklären, warum mehrere einfachere Kerne attraktiv sein können. Die Power Wall entstand, als Spannungssenkungen die Wärme und den Leistungsaufwand höherer Taktfrequenzen nicht mehr ausgleichen konnten.

  3. 3
    BeispielEine Anfrage von vielen Anfragen unterscheiden

    Laufen vier unabhängige Downloads auf vier Kernen, kann der Rechner mehr Downloads pro Sekunde abschließen, selbst wenn jeder Download gleich lange dauert. Das ist ein Durchsatzgewinn durch Arbeit auf Anfrageebene. Wird ein Bild in unabhängige Bereiche aufgeteilt und von vier Threads bearbeitet, kann dieses eine Bild früher fertig werden. Parallele Hardware dient beiden Zielen, aber das Programm muss die passende Arbeit bereitstellen.

  4. 4
    ErklärungArbeit innerhalb eines Programms finden

    Eine Pipeline überlappt Befehle aus einem Strom: ILP. Eine Arrayoperation wiederholt sich über Elemente hinweg: DLP. Getrennte Threads bieten TLP mit eigenen Ausführungszuständen und einem gemeinsamen Prozessadressraum. Diese Formen können gleichzeitig auftreten. Ein Arrayprogramm mit Threads kann Bereiche auf Kerne verteilen, innerhalb jedes Bereichs SIMD nutzen und diese Befehle durch die Pipeline jedes Kerns ausführen.

  5. 5
    HerausforderungZählt Abwechseln?

    Ein Kern wechselt zwischen zwei Aufgaben. Beide sind eine Sekunde lang in Bearbeitung, aber ihre Befehle werden nie zum selben Zeitpunkt ausgeführt. Ist das parallele Ausführung?

    ---reveal---

    Es ist nebenläufige Ausführung durch Zeitaufteilung. Parallelität verlangt gleichzeitige Operationen auf getrennten Hardwareressourcen. Ein weiterer Kern könnte diese Gleichzeitigkeit ermöglichen, benötigte aber weiterhin ausführungsbereite Arbeit.

  6. 6
    ErklärungFrag dich, wer den nächsten Befehl auswählt

    Die flynnsche Taxonomie beginnt mit Befehls- und Datenströmen. Ein herkömmlicher skalarer einzelner Kern ist SISD. Eine breite Operation, die einen Befehl auf mehrere Elemente anwendet, ist SIMD. Unabhängig gesteuerte Prozessoren, die ihre Daten bearbeiten, sind MIMD. MISD kombiniert mehrere Befehlsströme mit einem Datenstrom und hat wenige eindeutige praktische Beispiele. Zähle die Ströme auf einer gewählten Hardwareebene.

  7. 7
    BeispielEin Programm, unabhängiger Fortschritt

    Vier Arbeitseinheiten teilen anhand ihrer IDs ein Array mit 4.000 Elementen in vier Bereiche mit je 1.000 Elementen auf. Sie führen dasselbe Programm aus, aber eine kann ihre letzte Addition erreichen, während eine andere noch Werte lädt. Das ist SPMD-Software auf MIMD-Hardware. Gemeinsamer Programmtext verlangt keine Befehlsausgabe im Gleichschritt. Ein SIMD-Befehl innerhalb einer beliebigen Arbeitseinheit würde eine weitere Ebene paralleler Ausführung hinzufügen.

  8. 8
    HerausforderungDie gewählte Ebene klassifizieren

    Eine Mehrkern-CPU mit unabhängig gesteuerten Kernen verwendet in jedem Kern Vektoradditionen. Welche Klassen liegen über die Kerne hinweg und innerhalb einer Vektoraddition vor?

    ---reveal---

    Die Kerne bilden MIMD-Hardware, weil sie Befehle unabhängig auswählen. Jede Vektoraddition ist SIMD, weil ein Befehl auf mehreren Datenelementen arbeitet. Beide Beschreibungen können auf denselben Rechner zutreffen, wenn sie sich auf unterschiedliche Ebenen beziehen.

  9. 9
    ErklärungAusführungszustand bereithalten

    Ein Hardwarethreadkontext speichert einen Befehlszähler und Register. Mehrere Kontexte können sich die Recheneinheiten und Caches eines Kerns teilen. Wenn eine Speicheranfrage einen Thread warten lässt, kann ein anderer bereiter Thread freie Ausführungskapazität füllen. Das Betriebssystem sieht jeden Kontext als logischen Prozessor. Zwei Kontexte in einem Kern teilen sich weiterhin dessen physische Ausführungsressourcen.

  10. 10
    ErklärungWählen, wann Threads den Kern teilen

    Feingranulares Multithreading wählt in jedem Taktzyklus einen bereiten Thread. Grobgranulares Multithreading wechselt nach einer langen Wartezeit und verursacht Kosten für den Wechsel und das erneute Füllen der Pipeline. SMT geht auf einem Kern mit Mehrfachausgabe weiter: Befehle verschiedener Threads können im selben Taktzyklus ausgegeben werden. Alle drei Verfahren hängen von bereiter nutzbarer Arbeit ab; keines liefert unbegrenzte zusätzliche Rechenkapazität.

  11. 11
    BeispielZuerst die Leerlauflücke messen

    Ein Thread rechnet 20 Taktzyklen und wartet dann 200. Seine Periode beträgt 220 Taktzyklen, sodass die aktive Zeit 20/220≈9,1% ausmacht. Eine lange Wartezeit lässt die meisten Taktzyklen ungenutzt, wenn kein anderer Thread verfügbar ist. Behalte die gesamte Periode aus Rechnen und Warten im Nenner. Eine Division allein durch die Wartezeit würde ein anderes Verhältnis beschreiben und nicht den Anteil der vergangenen Taktzyklen mit nutzbarer Arbeit.

  12. 12
    BeispielDie Lücke mit bereiten Rechenphasen füllen

    Bei vier frei versetzten Threads, die jeweils 20 Rechentaktzyklen pro Periode von 220 Taktzyklen beitragen, beträgt die ideale Auslastung 80/220≈36,4%. Elf Threads können die Periode füllen: Während einer 200 Taktzyklen wartet, tragen die anderen zehn 200 Rechentaktzyklen bei. Dieses ideale Modell setzt kostenlosen Wechsel und keine zusätzliche Ressourcenkonkurrenz voraus; reale Konkurrenz um Bandbreite und Cache kann weniger nutzbare Arbeit bereithalten.

  13. 13
    HerausforderungWürde ein weiterer Kontext das lösen?

    Die Recheneinheiten eines Kerns sind bereits vollständig ausgelastet, und seine beiden Threads benötigen dieselben Einheiten. Würde ein weiterer Hardwarethread die Kapazität eines weiteren Kerns bereitstellen? Erkläre es anhand der gemeinsam genutzten Ressource.

    ---reveal---

    Nein. Ein neuer Kontext liefert einen weiteren Befehlsstrom, teilt sich aber weiterhin die ausgelasteten Ausführungseinheiten. Ein weiterer vollständiger Kern ergänzt Ausführungshardware. Multithreading ist besonders nützlich, wenn es Kapazität füllt, die wegen Wartezeiten oder zu weniger bereiter Befehle ungenutzt bleibt.

  14. 14
    VerbindungDie Verbesserung des Dienstes ihrer Ursache zuordnen

    Der Dienst ergänzt Hardwarekontexte und schließt nun mehr unabhängige Anfragen pro Sekunde ab, während die CPU-Arbeit jeder Anfrage etwas länger dauert. Dieses Ergebnis passt zu einem verbesserten Durchsatz: Bereite Anfragen füllen freie Plätze und teilen sich dabei Ressourcen. Es wäre irreführend, dies als Verbesserung der Latenz einer einzelnen Anfrage zu bezeichnen. Wähle ein Leistungsmaß, das zu der Arbeit passt, deren Abschluss die Nutzer benötigen.

  15. 15
    ZusammenfassungDie erste Hardwareentscheidung treffen

    Bestimme für eine neue Arbeitslast zuerst unabhängige Befehle, Datenelemente, Threads oder Anfragen. Ermittle dann die Hardwareebene, die ihre Befehlsströme steuert. Soll der Gewinn durch zusätzliche Kontexte entstehen, untersuche, welche Wartezeiten Kapazität freilassen und welche Ressourcen sich die Kontexte teilen. Das bietet eine konkrete Grundlage, um vor der Messung des Ergebnisses mehr Kerne, breitere Operationen oder mehr bereite Threads zu wählen.

2

Die Grenze vor dem Hinzufügen von Prozessoren bestimmen

16 Schritte
Untersuche Speedup bei fester Größe, skalierte Arbeitslasten und einen bandbreitengebundenen Kernel.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungDrei Gründe, warum zusätzliche Hardware enttäuschen kann
  2. 2
    ErklärungDie zeitliche Vergleichsbasis wählen
  3. 3
    BeispielNur den parallelen Anteil teilen
  4. 4
    KernaussageDer feste Teil bestimmt die Gesamtgrenze
  5. 5
    HerausforderungIst das Speedup-Ziel erreichbar?
  6. 6
    ErklärungDie Frage nach der Arbeitslast im Blick behalten
  7. 7
    BeispielDen Anteil des parallelen Laufs verwenden
  8. 8
    BeispielAuf die am stärksten belastete Arbeitseinheit warten
  9. 9
    HerausforderungWann verlängern zusätzliche Kerne die Zeit?
  10. 10
    ErklärungDie Byte zählen, die den Speicher verlassen
  11. 11
    BeispielDie beiden Dächer bestimmen
  12. 12
    ErklärungWiederverwendung verschiebt den Kernel nach rechts
  13. 13
    HerausforderungWelche Erweiterung hebt die aktuelle Schranke an?
  14. 14
    HerausforderungEin schneller Kernel in einem langsamen Programm
  15. 15
    TippDen angegebenen Gewinn reproduzierbar machen
  16. 16
    ZusammenfassungDie nächste Messung wählen
3

Eine Arrayschleife in GPU-Arbeit umwandeln

22 Schritte
Zähle SIMD-Elemente, teile eine Vektorschleife mit Strip-Mining auf und erstelle eine abgesicherte GPU-Zuordnung mit korrekter Zusammenarbeit.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungMit unabhängigen Arrayelementen beginnen
  2. 2
    BeispielVor den Befehlen die Elemente zählen
  3. 3
    ErklärungDie Werte nebeneinanderlegen
  4. 4
    ErklärungElemente mit einer Maske auswählen
  5. 5
    HerausforderungKönnen alle Iterationen gleichzeitig beginnen?
  6. 6
    ErklärungDie aktive Länge beschreibt den Durchlauf
  7. 7
    BeispielEinen langen Vektor in Durchläufe aufteilen
  8. 8
    VerbindungEine Vektoroperation mit einer anderen versorgen
  9. 9
    HerausforderungUm die tatsächlich ausgeführte Länge weiterrücken
  10. 10
    ErklärungEinen Warp einplanen, während ein anderer wartet
  11. 11
    BeispielUnterschiedliche Pfade lassen Lanes untätig
  12. 12
    ErklärungMit einer Transaktion viele Threads bedienen
  13. 13
    HerausforderungDen Weg zum Gerät einbeziehen
  14. 14
    VerbindungAuf eine engere Arbeitslast spezialisieren
  15. 15
    BeispielDas Arrayelement eines Threads finden
  16. 16
    BeispielDen letzten unvollständigen Block abdecken
  17. 17
    ErklärungWarten, bevor der Host Ergebnisse verwendet
  18. 18
    BeispielInnerhalb eines Blocks reduzieren
  19. 19
    HerausforderungKann ein Block auf alle anderen warten?
  20. 20
    KernaussageEine Reduktion ändert die Rechenreihenfolge
  21. 21
    HerausforderungEine sichere Zuordnung mit effizientem Zugriff verbinden
  22. 22
    ZusammenfassungDen vollständigen Arraypfad prüfen
4

Einen gemeinsamen Block vom Leser zum schreibenden Kern verfolgen

19 Schritte
Teile eine Summe auf, verfolge Cacheberechtigungen und diagnostiziere die gegenseitige Beeinträchtigung unabhängiger Zähler.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungGemeinsame Variablen brauchen weiterhin Koordination
  2. 2
    ErklärungEin Adressraum, unterschiedliche Zugriffspfade
  3. 3
    BeispielLokale Arbeit vor dem Zusammenführen abschließen
  4. 4
    HerausforderungWas geschieht bei einem zwischenzeitlichen Schreibzugriff?
  5. 5
    BeispielDen veralteten Cache-Treffer finden
  6. 6
    ErklärungÜber die Schreibfolge einer Speicherstelle einig sein
  7. 7
    HerausforderungKann Kohärenz beide Erhöhungen bewahren?
  8. 8
    VerbindungReihenfolge und Besitz unterscheiden
  9. 9
    ErklärungDie Berechtigungen in MSI lesen
  10. 10
    BeispielZunächst beiden Kernen unveränderte Kopien geben
  11. 11
    BeispielDen Besitz an den schreibenden Kern übertragen
  12. 12
    KernaussageExclusive spart eine Anfrage für private Daten
  13. 13
    HerausforderungEinen Lese- und zwei Schreibzugriffe verfolgen
  14. 14
    ErklärungDie Anfrage über den Heimatknoten senden
  15. 15
    BeispielVor der Aufwandsschätzung Bit umrechnen
  16. 16
    BeispielFinden, welche Byte den Besitz teilen
  17. 17
    HerausforderungMuss der benachbarte Leser schreiben?
  18. 18
    HerausforderungEine korrekte Summe mit weniger Konkurrenz berechnen
  19. 19
    ZusammenfassungSowohl Programm als auch Block untersuchen
5

Daten, Energie und langsame Antworten im Rechnerverbund verfolgen

14 Schritte
Vergleiche Netzwerkschnitte, berechne die Energie der Anlage und sieh, warum große Dienste seltene Ereignisse einplanen.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungEin Knoten ist nun ein vollständiger Rechner
  2. 2
    ErklärungArbeit nahe bei ihrer Eingabe platzieren
  3. 3
    BeispielTeilsummen in Nachrichtenrunden zusammenführen
  4. 4
    ErklärungDen engen Schnitt zählen
  5. 5
    HerausforderungEin breiteres Netzwerk bezahlen
  6. 6
    ErklärungDie aufwärtsführenden Verbindungen teilen
  7. 7
    BeispielKühlung und Verteilung einbeziehen
  8. 8
    BeispielGleichbleibende Leistung in Jahresenergie umrechnen
  9. 9
    HerausforderungWelche Effizienz hat die Änderung verbessert?
  10. 10
    BeispielGeringe Last benötigt weiterhin Leistung
  11. 11
    ErklärungKleine Ausfallraten summieren sich im Rechnerverbund
  12. 12
    BeispielEine langsame Antwort kann die Anfrage aufhalten
  13. 13
    HerausforderungVerkürzen mehr Server jede Anfrage?
  14. 14
    ZusammenfassungEin Kennmaß für den Rechnerverbund gezielt wählen

Mehrkernprozessoren: Übungsaufgaben

50 Übungsfragen in 5 Sets

Set 1: Parallele Arbeit und ihre Kosten erkennen10 Übungsfragen

Frage 1 von 10

Ein Webdienst weist unabhängige Anfragen zum Herunterladen von Bildern verschiedenen Servern zu. Welche Art von Parallelität wird genutzt?
  1. Befehlsparallelität
  2. Anfrageparallelität
  3. Datenparallelität
  4. Feingranulares Multithreading
Antwort zeigenAntwort ausblenden
Antwort: B
Jeder Server bearbeitet eine eigene Anfrage, die parallele Arbeit entsteht also aus unabhängigen Aufgaben. Datenparallelität würde dieselbe Operation auf viele Elemente innerhalb einer Berechnung anwenden; die Bearbeitung verschiedener Anfragen verlangt nicht, dass diese einem gemeinsamen Befehl folgen.

Frage 2 von 10

Alle Prozessoren stimmen in der Reihenfolge der Schreibzugriffe auf eine Speicherstelle überein. Welche Kohärenzeigenschaft ist das?
  1. Schreibpropagierung
  2. Sequenzielle Konsistenz
  3. Atomare Lese-Änderungs-Schreiboperation
  4. Schreibserialisierung
Antwort zeigenAntwort ausblenden
Antwort: D
Die Schreibserialisierung gibt allen Prozessoren dieselbe Reihenfolge für Schreibzugriffe auf eine Speicherstelle vor. Sequenzielle Konsistenz schränkt zusätzlich die gesamte Verschachtelung von Operationen über verschiedene Speicherstellen hinweg ein und bewahrt dabei die Programmreihenfolge jedes Prozessors. Die Übereinstimmung über die Schreibfolge einer einzelnen Stelle ist eine engere Eigenschaft.

Frage 3 von 10

Eine Aufgabe benötigt mit der besten sequenziellen Implementierung 144 s und auf acht Prozessoren 24 s. Wie groß ist ihre parallele Effizienz?
  1. 75%
  2. 16,7%
  3. 60%
  4. 80%
Antwort zeigenAntwort ausblenden
Antwort: A
Der Speedup ist das Zeitverhältnis 144/24 = 6. Die Effizienz teilt diesen Gewinn durch die acht Prozessoren und ergibt 6/8=0,75, also 75 %. Der Wert 16,7 % entsteht, wenn man die parallele Zeit durch die sequenzielle Zeit teilt; er misst den verbleibenden Zeitanteil statt der Effizienz.

Frage 4 von 10

Ein Kernel hat eine Intensität von 3 Gleitkommaoperationen pro Byte auf Hardware mit 720 GFLOP/s Spitzenrechenleistung und 80 GB/s DRAM-Bandbreite. Welche Roofline-Schranke gilt?
  1. 720 GFLOP/s
  2. 960 GFLOP/s
  3. 240 GFLOP/s
  4. 26,7 GFLOP/s
Antwort zeigenAntwort ausblenden
Antwort: C
Das Bandbreitendach beträgt 80×3=240 GFLOP/s und liegt unter dem Rechenleistungsdach von 720 GFLOP/s. Die niedrigere Leistungsgrenze bestimmt die Schranke. Wer allein die Spitzenrechenleistung wählt, nimmt an, dass Daten schnell genug eintreffen, um sie aufrechtzuerhalten. Dieser Kernel bräuchte aber erheblich mehr Byte pro Sekunde, als der Speicher liefert.

Frage 5 von 10

Wie viele 64-Bit-Elemente passen in ein 512-Bit-SIMD-Register?
  1. 4 Elemente
  2. 16 Elemente
  3. 8 Elemente
  4. 64 Elemente
Antwort zeigenAntwort ausblenden
Antwort: C
Teile die Registerbreite durch die Breite eines Elements: 512/64 = 8. Die Anzahl der Lanes hängt sowohl von der Elementgröße als auch von der Registergröße ab. Sechzehn Lanes würden für 32-Bit-Werte passen; bei 64-Bit-Werten würde diese Anzahl nur die Hälfte des benötigten Platzes pro Element vorsehen.

Frage 6 von 10

Zwei GPU-Warps nehmen entgegengesetzte Pfade durch eine if-else-Verzweigung. Innerhalb jedes Warps stimmen alle Threads über den Pfad überein. Was geschieht mit der Kontrollflussdivergenz?
  1. Beide Warps führen jeden Zweig aus.
  2. Keiner der Warps divergiert intern.
  3. Die Hälfte jedes Warps wird inaktiv.
  4. Jeder Warp teilt sich in zwei Warps.
Antwort zeigenAntwort ausblenden
Antwort: B
Divergenz wird innerhalb eines Warps bestimmt, in dem die Befehlsausgabe gemeinsam erfolgt. Jeder beschriebene Warp hat eine einheitliche Bedingung und kann nur seinen eigenen Pfad ausführen. Verschiedene Warps können unterschiedlichen Pfaden folgen, ohne dass einer von ihnen beide Zweige mit jeweils der Hälfte seiner Lanes maskiert ausführen muss.

Frage 7 von 10

Eine NUMA-Arbeitslast führt 60 % ihrer Zugriffe mit 75 ns und den Rest mit 135 ns aus. Wie groß ist die mittlere Zugriffslatenz?
  1. 99 ns
  2. 105 ns
  3. 81 ns
  4. 135 ns
Antwort zeigenAntwort ausblenden
Antwort: A
Gewichte jede Latenz mit ihrem Anteil an den Zugriffen: 0,6×75+0,4×135=45+54=99 ns. Ein ungewichtetes arithmetisches Mittel ergibt 105 ns, würde aber gleich viele lokale und entfernte Zugriffe voraussetzen. Hier treten die schnelleren lokalen Zugriffe häufiger auf.

Frage 8 von 10

Zwei Threads lesen beide den Wert 9 aus einem kohärenten Zähler und speichern nach einer gewöhnlichen Erhöhung beide den Wert 10. Welche Eigenschaft fehlt der Erhöhung?
  1. Schreibpropagierung
  2. Schreibserialisierung
  3. Cachereplikation
  4. Atomarität
Antwort zeigenAntwort ausblenden
Antwort: D
Die Erhöhung besteht aus einem Lesezugriff und einem getrennten Schreibzugriff. Daher können beide Threads neun lesen, bevor einer von ihnen zehn speichert. Kohärenz kann beide Schreibzugriffe mit dem Wert zehn korrekt serialisieren, und dennoch geht eine Erhöhung verloren. Eine atomare Lese-Änderungs-Schreiboperation macht jede vollständige Aktualisierung für den anderen Thread unteilbar.

Frage 9 von 10

Im grundlegenden MSI beginnen A und B für einen Block mit dem Wert 4 im Zustand Invalid. A liest, A schreibt 7 und danach liest B. Welche A/B-Zustände und welchen von B gelesenen Wert erhält man am Ende?
  1. M/S, B liest 7
  2. S/S, B liest 7
  3. I/S, B liest 4
  4. S/S, B liest 4
Antwort zeigenAntwort ausblenden
Antwort: B
A lädt zunächst in Shared und erlangt dann den Besitz im Zustand Modified, um sieben zu schreiben. Bs späterer Lesezugriff veranlasst A, den veränderten Wert zu liefern und nach Shared zu wechseln; auch B erhält Shared. Bliebe A in Modified, widerspräche das der Regel des grundlegenden MSI, dass ein Block in Modified keine andere gültige Cachekopie hat.

Frage 10 von 10

Ein Ring mit 20 Knoten hat für jede Verbindung dieselbe Bandbreite von 5 Gbit/s. Wie groß ist seine Bisektionsbandbreite, wenn pro Verbindung ein Kapazitätswert verwendet wird?
  1. 10 Gbit/s
  2. 100 Gbit/s
  3. 50 Gbit/s
  4. 5 Gbit/s
Antwort zeigenAntwort ausblenden
Antwort: A
Der minimale Schnitt eines Rings in gleich große Hälften durchquert zwei Verbindungen, seine Kapazität beträgt also 2×5=10 Gbit/s. Die Gesamtbandbreite von 100 Gbit/s zählt alle zwanzig Verbindungen und beschreibt die Gesamtkapazität. Sie kann nicht vollständig den Verkehr über die beiden Verbindungen zwischen den Hälften tragen.
Set 2: Skalierungs-, Indizierungs- und Kohärenzregeln anwenden10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Ein Kern gibt im selben Taktzyklus Befehle aus zwei verschiedenen Threads aus. Welche Hardwaretechnik beschreibt das?
  1. Grobgranulares Multithreading
  2. Feingranulares Multithreading
  3. Simultanes Multithreading
  4. Zeitaufteilung des Betriebssystems
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Eine feste Aufgabe verbringt 20 % ihrer sequenziellen Zeit mit Arbeit, die nicht parallelisiert werden kann. Welcher Speedup ergibt sich bei idealer Aufteilung des Rests auf vier Prozessoren?
  1. 2,5
  2. 3,2
  3. 4,0
  4. 5,0
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Eine Simulation wächst von zwei Millionen Zellen auf vier Prozessoren auf vier Millionen Zellen auf acht Prozessoren, wobei die Arbeit pro Zelle fest bleibt. Welches Skalierungsexperiment ist das?
  1. Starke Skalierung
  2. Superlineare Skalierung
  3. Skalierung bei fester Arbeitslast
  4. Schwache Skalierung
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Eine RVV-Schleife hat noch 90 Elemente. Ihre Implementierung wählt nacheinander die aktiven Längen 32, 32 und 26. Um wie viele Elemente sollte der Code nach dem zweiten Durchlauf weiterrücken?
  1. 26 Elemente
  2. 32 Elemente
  3. 64 Elemente
  4. 90 Elemente
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Ein Array hat 4.103 Elemente. Ein Kernel bearbeitet ein Element pro Thread und verwendet 128 Threads pro Block. Wie viele Blöcke werden benötigt?
  1. 33 Blöcke
  2. 32 Blöcke
  3. 34 Blöcke
  4. 129 Blöcke
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Sechs Kerne führen jeweils eine Kopie eines Programms aus. Sie wählen Befehle unabhängig und verarbeiten unterschiedliche Arraybereiche. Welche Hardwareklasse liegt vor?
  1. SIMD
  2. SISD
  3. MISD
  4. MIMD
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Bei MESI liest A einen nicht zwischengespeicherten Block, schreibt ihn, schreibt ihn erneut und dann liest B ihn. Beide Kopien beginnen in Invalid. Wie viele Kohärenz-Busanfragen treten in dieser Folge auf?
  1. 1 Anfrage
  2. 3 Anfragen
  3. 2 Anfragen
  4. 4 Anfragen
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Ein vollständiges Kohärenzverzeichnis verwendet für jeden 128 Byte großen Datenblock ein Präsenzbit pro Kern. Wie hoch ist bei 128 Kernen der Speicheraufwand allein für den Präsenzvektor?
  1. 1,56%
  2. 12,5%
  3. 16%
  4. 100%
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Achtundvierzig Clusterknoten besitzen bereits gleiche Anteile von 960.000 Werten. Ein binärer Baum führt pro Knoten eine lokale Summe zusammen. Wie viele Werte entfallen auf jeden Knoten und wie viele Runden braucht das Zusammenführen?
  1. 20.000 Werte und 48 Runden
  2. 46.080.000 Werte und 6 Runden
  3. 20.000 Werte und 5 Runden
  4. 20.000 Werte und 6 Runden
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Ein Rack hat 24 Server mit Verbindungen zu je 25 Gbit/s und sechs aufwärtsführende Verbindungen zu je 50 Gbit/s. Wie groß sind bei gleichmäßiger Aufteilung das Überbuchungsverhältnis und die Rate pro Server, wenn alle Server gleichzeitig aus dem Rack senden?
  1. 2:1 und 25 Gbit/s
  2. 4:1 und 6,25 Gbit/s
  3. 2:1 und 12,5 Gbit/s
  4. 1:2 und 50 Gbit/s
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 3: Leistungsgrenzen im gesamten System diagnostizieren10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Die Kapazität bleibt fest, während die Spannung auf 90 % und die Frequenz auf 80 % ihrer ursprünglichen Werte sinkt. Welcher Anteil der ursprünglichen dynamischen Leistungsaufnahme bleibt?
  1. 0,720
  2. 0,810
  3. 0,5832
  4. 0,648
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Ein einzelner superskalarer Kern folgt einem Befehlsstrom und überlappt unabhängige skalare Befehle. Wie wird er in der flynnschen Taxonomie klassifiziert?
  1. SIMD
  2. SISD
  3. MIMD
  4. MISD
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Sechs Kerne erhalten anfangs 35, 35, 35, 35, 35 und 65 jeweils gleich aufwendige Aufgaben. Ein Scheduler verschiebt vom am stärksten belasteten Kern zehn Aufgaben zu jedem der anderen fünf. Wie ändert sich der Speedup gegenüber sequenzieller Ausführung, wenn kein Zusatzaufwand entsteht und jeder Kern eine Aufgabe pro Zeiteinheit erledigt?
  1. Von etwa 3,69 auf 5,33
  2. Von etwa 3,69 auf 6,00
  3. Von genau 6,00 auf 5,33
  4. Von genau 4,00 auf 5,33
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Ein Rechner erreicht maximal 960 GFLOP/s und 120 GB/s. Ein Kernel führt 12 GFLOPs aus und überträgt 3 GB aus dem DRAM. Kachelung halbiert den Verkehr, ohne die Arbeit zu ändern. Was geschieht mit der Roofline-Schranke?
  1. Sie steigt von 480 auf 1.920 GFLOP/s.
  2. Sie bleibt bei 480 GFLOP/s.
  3. Sie steigt von 480 auf 960 GFLOP/s.
  4. Sie steigt von 240 auf 480 GFLOP/s.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Eine Schleife berechnet a[i] = a[i-1] + b[i] von links nach rechts. Warum kann der Compiler aufeinanderfolgende Iterationen nicht direkt durch unabhängige SIMD-Lanes ersetzen?
  1. Jede Iteration liest Werte aus zwei verschiedenen Arrays.
  2. Jede Iteration benötigt das neue Ergebnis der vorherigen Iteration.
  3. Jede Iteration enthält mehr als eine arithmetische Eingabe.
  4. Jede Iteration speichert ihr Ergebnis in einem zusammenhängenden Array.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Eine RVV-Schleife hat noch 50 Gleitkommazahlen doppelter Genauigkeit und eine Kapazität von 32. Die Implementierung gibt vl = 28 zurück. Der Programmierer rückt beide Zeiger um 32 Elemente weiter und zieht 32 von der verbleibenden Anzahl ab. Welcher Datenbereich geht zuerst verloren?
  1. Ursprüngliche Indizes 0 bis 27
  2. Ursprüngliche Indizes 32 bis 49
  3. Ursprüngliche Indizes 24 bis 27
  4. Ursprüngliche Indizes 28 bis 31
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Warum können in einem NUMA-System zwei Zugriffe von verschiedenen Sockeln auf dieselbe gemeinsame Adresse unterschiedliche Latenzen haben?
  1. Die Adresse kann für einen Sockel lokal und für einen anderen entfernt sein.
  2. Jeder Sockel muss der Adresse einen anderen Zahlenwert zuweisen.
  3. Jeder Sockel muss einen eigenen Anwendungsadressraum nutzen.
  4. Die Adresse muss jeden privaten Cache des Rechners umgehen.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Bei 64 Byte großen Blöcken schreibt A wiederholt einen 8 Byte großen Zähler an 0x2040; B liest wiederholt einen unabhängigen 8 Byte großen Statuswert an 0x2078. Warum kann B kohärenzbedingte Fehlzugriffe erleiden?
  1. Die Variablen liegen in benachbarten Blöcken, daher liest jeder Zugriff beide.
  2. Beide Threads schreiben denselben Zähler, daher geht eine Erhöhung verloren.
  3. Beide Variablen liegen in Block 129, und As Schreibzugriffe invalidieren Bs Kopie.
  4. Der Leser benötigt Modified-Besitz, bevor er den Status lesen kann.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Eine Vektoraddition mit 72 Elementen läuft auf sechs Lanes. Wie viele Taktzyklen werden für die Elementoperationen benötigt, wenn das Anlaufen nicht berücksichtigt wird?
  1. 6 Taktzyklen
  2. 72 Taktzyklen
  3. 12 Taktzyklen
  4. 432 Taktzyklen
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

IT-Geräte nehmen gleichbleibend 8 MW auf, und der Anlagenaufwand fügt 2 MW hinzu. Wie groß ist der PUE-Wert?
  1. 1,25
  2. 0,25
  3. 0,80
  4. 4,00
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 4: Hardwareverhalten mit Leistungsmodellen verbinden10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Ein Rechner hat 12 Kerne und zwei Hardwarethreads pro Kern. Wie viele logische Prozessoren sind sichtbar, und wie viele physische Kerne gibt es?
  1. 24 logische Prozessoren und 12 Kerne
  2. 24 logische Prozessoren und 24 Kerne
  3. 12 logische Prozessoren und 24 Kerne
  4. 12 logische Prozessoren und 12 Kerne
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Ein Einkernsystem wechselt zwischen zwei lang laufenden Aufgaben und führt ihre Befehle nie zum selben Zeitpunkt aus. Wie ist ihre Ausführung zu beschreiben?
  1. Parallel, aber nicht nebenläufig
  2. Sowohl parallel als auch nebenläufig
  3. Nebenläufig, aber nicht parallel
  4. Weder parallel noch nebenläufig
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Ein Kernel mit geringer Intensität schöpft bereits die DRAM-Bandbreite aus und läuft an seiner Roofline-Schranke. Die SIMD-Breite verdoppelt sich, während Bandbreite und Intensität fest bleiben. Wie ändert sich seine Roofline-Schranke?
  1. Sie verdoppelt sich.
  2. Sie halbiert sich.
  3. Sie steigt um die ursprüngliche Intensität.
  4. Sie bleibt gleich.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Ein Reduktionskernel verwendet if (i < n) { load_into_shared(); __syncthreads(); combine(); }. In seinem letzten Block erfüllen nur einige Threads die Bedingung. Welche strukturelle Korrektur macht die Blockbarriere sicher?
  1. Entferne die Bereichsprüfung, damit alle Blockthreads ein Arrayelement laden.
  2. Lass alle Blockthreads die Barriere erreichen und nutze neutrale Werte für inaktive Eingaben.
  3. Ersetze die Blockbarriere durch ein Warten des Hosts nach dem Kernelstart.
  4. Setze eine zweite identische Barriere in denselben bedingten Zweig.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Eine CPU benötigt 36 ms pro Stapel. Eine separate GPU benötigt eine Übertragung von 500 MB zur GPU, dann drei Kernel mit je 4 ms und anschließend eine Übertragung von 100 MB zurück. Die Übertragungen erreichen 15 GB/s, können sich nicht mit der Berechnung überlappen und die Startkosten sind vernachlässigbar. Welcher Weg ist um wie viel schneller?
  1. Die GPU ist um 24 ms schneller.
  2. Die CPU ist um 16 ms schneller.
  3. Die CPU ist um 4 ms schneller.
  4. Die GPU ist um 16 ms schneller.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Zweiunddreißig Kerne teilen 32.000 Werte gleichmäßig auf. Jeder Thread beginnt bei null und addiert seine zugewiesenen Werte; anschließend führt ein binärer Baum die Teilsummen zusammen. Jede Addition kostet eine Zeiteinheit; jede Baumstufe besitzt außerdem eine Barriere von zwei Zeiteinheiten. Welcher Speedup ergibt sich ohne weitere Kosten gegenüber einer sequenziellen Summe, die bei null beginnt?
  1. Etwa 31,53
  2. Etwa 31,84
  3. Etwa 31,69
  4. Genau 32,00
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Ein Kern verwendet einen Cache mit Durchschreibverfahren. Ein anderer Kern hält bereits eine unveränderte Cachekopie derselben Adresse. Warum ist nach dem Schreibzugriff des ersten Kerns weiterhin ein Kohärenzmechanismus nötig?
  1. Das Durchschreibverfahren verhindert die Aktualisierung des Speichers durch den ersten Kern.
  2. Eine unveränderte Cachekopie kann niemals ungültig werden.
  3. Der zweite Kern muss bei jedem Lesezugriff alle Cacheblöcke verwerfen.
  4. Die Aktualisierung des Speichers allein lässt die andere Cachekopie veraltet.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Bei MESI liest A einen nicht zwischengespeicherten Block, B liest ihn, A schreibt 3, A schreibt 6 und B liest erneut. Wie viele Busanfragen treten auf und welchen Wert erhält B beim letzten Lesezugriff?
  1. 3 Anfragen, B erhält 6
  2. 5 Anfragen, B erhält 6
  3. 4 Anfragen, B erhält 6
  4. 4 Anfragen, B erhält 3
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Zwei Anlagen haben denselben PUE-Wert. Eine betreibt überwiegend untätige Server; die andere erledigt mit ihrer IT-Energie weit mehr Arbeit. Was belegt der gleiche PUE-Wert?
  1. Ihre nutzbaren Berechnungen pro Joule sind gleich.
  2. Ihre gesamten Energiemengen der Anlagen sind gleich.
  3. Ihre prozentualen Serverauslastungen sind gleich.
  4. Ihre Verhältnisse von Anlagenenergie zu IT-Energie sind gleich.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Acht unabhängig gesteuerte CPU-Kerne führen jeweils in einem Taktzyklus eine SIMD-Addition mit acht Lanes aus. Wie sind die beiden Ebenen zu beschreiben?
  1. SIMD über die Kerne hinweg und SISD innerhalb jeder Addition
  2. SISD über die Kerne hinweg und MIMD innerhalb jeder Addition
  3. MIMD über die Kerne hinweg und SIMD innerhalb jeder Addition
  4. MISD über die Kerne hinweg und SIMD innerhalb jeder Addition
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 5: Die Modelle auf neue Entwurfsentscheidungen übertragen10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Ein idealer Lauf mit fester Arbeitslast erreicht auf acht Prozessoren einen Speedup von 4. Seine sequenzielle Arbeit wird anschließend doppelt so schnell, während die parallele Arbeit unverändert bleibt. Welchen Speedup erreicht der neue Lauf auf acht Prozessoren gegenüber dem ursprünglichen sequenziellen Ausgangslauf?
  1. 4,0
  2. 5,6
  3. 4,67
  4. 8,0
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Entwurf A hat vier Kerne mit jeweils zwei Hardwarekontexten; Entwurf B hat zwei Kerne mit jeweils acht Kontexten. Jeder Thread wiederholt 15 Rechentaktzyklen und danach 105 Wartetaktzyklen. Jeder Kern kann pro Taktzyklus einen Rechenschritt ausführen. Wie verhalten sich ihre Rechendurchsätze im eingeschwungenen Zustand bei idealer Versetzung, kostenlosem Wechsel und ohne Speicherkonkurrenz?
  1. A liefert den doppelten Durchsatz von B.
  2. Beide liefern denselben Durchsatz.
  3. B liefert den doppelten Durchsatz von A.
  4. B liefert den vierfachen Durchsatz von A.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Eine feste Arbeitslast muss bei idealer Skalierung nach Amdahl auf sechzehn Prozessoren mindestens einen Speedup von 12 erreichen. Wie groß darf der sequenzielle Anteil ihrer ursprünglichen Zeit höchstens sein?
  1. 1/45, etwa 2,22 %
  2. 1/12, etwa 8,33 %
  3. 1/16, etwa 6,25 %
  4. 1/15, etwa 6,67 %
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Für eine vollständig aufteilbare Aufgabe gilt das gemessene Zeitmodell Tp=288/p+2p Sekunden. Du kannst 8, 12, 16 oder 24 Prozessoren verwenden. Welche Zuweisung ist am schnellsten fertig?
  1. 8 Prozessoren
  2. 16 Prozessoren
  3. 24 Prozessoren
  4. 12 Prozessoren
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Eine Schleife addiert zwei Arrays mit je 1.237 Gleitkommazahlen mithilfe von 256-Bit-SIMD-Befehlen. Zuerst werden vollständige Vektoren verarbeitet, danach ein skalarer Rest. Wie viele vollständige Iterationen und skalare Elemente werden benötigt?
  1. 155 Vektoriterationen und 3 skalare Elemente
  2. 154 Vektoriterationen und 8 skalare Elemente
  3. 153 Vektoriterationen und 5 skalare Elemente
  4. 154 Vektoriterationen und 5 skalare Elemente
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Ein Ring mit 16 Knoten und ein vollständig verbundenes Netzwerk mit 16 Knoten verwenden beide Verbindungen mit 10 Gbit/s. Welchen Gewinn an Bisektionskapazität bietet die vollständige Verbindung bei einem Kapazitätswert pro Verbindung, und wie viele zusätzliche Verbindungen benötigt sie?
  1. 32-fache Kapazität, mit 120 zusätzlichen Verbindungen
  2. 32-fache Kapazität, mit 104 zusätzlichen Verbindungen
  3. 8-fache Kapazität, mit 104 zusätzlichen Verbindungen
  4. 7,5-fache Kapazität, mit 104 zusätzlichen Verbindungen
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Welche Hardwaregruppe enthält in NVIDIAs SIMT-Ausführungsmodell 32 Threads, die sich die Befehlsausgabe teilen?
  1. Ein Threadblock
  2. Ein Streaming Multiprocessor
  3. Ein Warp
  4. Ein CUDA Core
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Ein abgesicherter Kernel mit einem Element pro Thread startet für ein Array mit 2.350 Elementen 37 Blöcke mit je 64 Threads. Wie viele Threads im letzten Block greifen auf gültige Elemente zu, und wie lautet ihr letzter gültiger Threadindex innerhalb dieses Blocks?
  1. 46 Threads; letzter lokaler Index 45
  2. 46 Threads; letzter lokaler Index 46
  3. 18 Threads; letzter lokaler Index 17
  4. 47 Threads; letzter lokaler Index 46
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Ein Cache hält bei MESI einen Block im Zustand Exclusive. Sein Prozessor schreibt den Block, während kein anderer Kern darauf zugreift. Welcher Zustand und welche Kohärenzanfrage ergeben sich?
  1. Modified, ohne Busanfrage
  2. Shared, mit einer Busleseanfrage
  3. Modified, mit einer Upgrade-Anfrage
  4. Exclusive, mit einer Schreibaktualisierungsanfrage
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Zwei unabhängige 8 Byte große Zähler liegen bei 64 Byte großen Cacheblöcken an 0x3000 und 0x3038. Jeder hat einen eigenen schreibenden Thread. Welche Verschiebung trennt sie in verschiedene Blöcke?
  1. Verschiebe den zweiten Zähler nach 0x3020.
  2. Verschiebe den zweiten Zähler nach 0x3040.
  3. Verschiebe den ersten Zähler nach 0x3008.
  4. Verschiebe den zweiten Zähler nach 0x3010.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Hängst du bei deiner eigenen Aufgabe fest? Hausaufgabenhilfe

Schlüsselbegriffe

100 Schlüsselbegriffe, jeweils mit Definition

A

Aliasing
Aliasing tritt auf, wenn verschiedene Referenzen auf überlappenden Speicher zugreifen können, wodurch gleichzeitige Schleifenoperationen unsicher sein können.
Ein Compiler prüft auf Aliasing, bevor er Lade- und Speicherzugriffe über möglicherweise überlappende Zeiger umordnet.
Amdahlsches Gesetz
Das amdahlsche Gesetz begrenzt den Gesamt-Speedup einer Verbesserung anhand des betroffenen Anteils der ursprünglichen Zeit und der Beschleunigung dieses Anteils.
Das amdahlsche Gesetz erklärt, warum ein wesentlich schnellerer kleiner Programmteil die Gesamtzeit kaum ändern kann.
Anfrageparallelität
Anfrageparallelität führt unabhängige Aufgaben oder Dienstanfragen gleichzeitig aus, wobei ihre Berechnungen wenig Koordination untereinander benötigen.
Ein Suchdienst gewinnt Anfrageparallelität dadurch, dass Tausende Nutzer unabhängige Fragen stellen.
Arithmetische Intensität
Die arithmetische Intensität ist die Anzahl der Gleitkommaoperationen pro übertragenem Byte; in einem DRAM-Roofline-Modell werden die Byte an der DRAM-Grenze gezählt.
Die Wiederverwendung im Cache erhöht die arithmetische Intensität, wenn die Anzahl nutzbarer Operationen fest bleibt, der DRAM-Verkehr aber sinkt.
Asynchroner Kernelstart
Ein asynchroner Kernelstart startet Arbeit auf dem Gerät, ohne den Host vor der Fortsetzung seiner Ausführung auf deren Abschluss warten zu lassen.
Ein asynchroner Kernelstart benötigt später eine Abschlussprüfung oder eine blockierende Ergebniskopie, bevor der Host das Ergebnis verwendet.
Atomare Lese-Änderungs-Schreiboperation
Eine atomare Lese-Änderungs-Schreiboperation aktualisiert eine Speicherstelle aus Sicht anderer Prozessoren unteilbar und verbindet dabei Lesen und Schreiben.
Eine atomare Lese-Änderungs-Schreiboperation verhindert, dass zwei Zählererhöhungen beide denselben alten Wert überschreiben.
Automatische Vektorisierung
Die automatische Vektorisierung ist eine Compilertransformation, die geeignete skalare Schleifenarbeit in SIMD-Operationen umwandelt und dabei die erforderlichen Ergebnisse bewahrt.
Eine mögliche Zeigerüberlappung kann die automatische Vektorisierung verhindern, sofern keine Prüfung feststellt, dass die Arrays nicht überlappen.

B

Barriere
Eine Barriere ist ein Synchronisationspunkt, den alle teilnehmenden Threads erreichen müssen, bevor einer in die nächste Phase übergeht.
Eine Barriere zwischen Reduktionsstufen verhindert, dass eine Arbeitseinheit eine Teilsumme liest, bevor sie geschrieben ist.
Befehlsparallelität
Befehlsparallelität überlappt Befehle aus einem Befehlsstrom durch Techniken wie Pipelining und Mehrfachausgabe.
Ein Kern nutzt Befehlsparallelität, indem er zwei unabhängige skalare Additionen gemeinsam ausgibt.
Bereichsprüfung
Eine Bereichsprüfung prüft, ob ein berechneter Index innerhalb des gültigen Datenbereichs liegt, bevor ein Thread den zugehörigen Speicherzugriff ausführt.
Wird ein Grid auf ganze Blöcke aufgerundet, deaktiviert eine Bereichsprüfung die zusätzlichen Threads im letzten Block, ohne gültige Elemente zu überspringen.
Bisektionsbandbreite
Die Bisektionsbandbreite ist die geringste gesamte Verbindungskapazität über einen Schnitt, der die Knoten eines Netzwerks in zwei gleich große Gruppen teilt.
Ein Ring hat nur zwei Verbindungen über einen minimalen Schnitt, sodass seine Bisektionsbandbreite den Verkehr zwischen den Hälften begrenzen kann.

C

Cachekohärenz
Cachekohärenz koordiniert Kopien einer Speicherstelle, sodass Prozessoren eine miteinander vereinbare Folge ihrer Schreibzugriffe und gelesenen Werte beobachten.
Cachekohärenz verhindert, dass ein Leser nach der Aktualisierung durch einen anderen Kern unbegrenzt eine veraltete private Kopie verwendet.
Cluster
Ein Cluster ist ein über ein Netzwerk verbundener Verbund vollständiger Rechner, die jeweils eigenen Speicher und ein eigenes Betriebssystem besitzen.
Ein Cluster verteilt ein großes Array auf Knoten und führt deren lokale Ergebnisse durch Netzwerknachrichten zusammen.
Coalescing
Coalescing fasst nahe beieinanderliegende Speicherzugriffe benachbarter Threads zu wenigen breiten Transaktionen zusammen, um die Bandbreite effizient zu nutzen.
Coalescing funktioniert gut, wenn aufeinanderfolgende Warp-Threads aufeinanderfolgende 4 Byte große Elemente eines Arrays lesen.

D

Datenparallelität
Datenparallelität wendet dieselbe Operation auf mehrere unabhängige Datenelemente an, häufig mithilfe von SIMD-Lanes oder GPU-Threads.
Die Addition entsprechender Arrayelemente bietet Datenparallelität, weil jedes Paar unabhängig verarbeitet werden kann.
Domänenspezifischer Beschleuniger
Ein domänenspezifischer Beschleuniger spezialisiert Hardware auf eine eingeschränkte Arbeitslast und tauscht Flexibilität gegen hohe Rechenleistung pro Watt in diesem Bereich.
Ein matrixorientierter domänenspezifischer Beschleuniger kann für neuronale Netze Multiplikationen mit geringer Genauigkeit bevorzugen.

E

Energieeffizienz
Energieeffizienz setzt die abgeschlossene nutzbare Arbeit ins Verhältnis zur verbrauchten Energie und berücksichtigt auch, ob Serverressourcen wirksam genutzt werden.
Eine Anlage kann ihren PUE-Wert verbessern und dennoch eine schlechte Serverenergieeffizienz haben, wenn ein großer Teil ihrer IT-Last keine nutzbare Arbeit leistet.
Energieproportionalität
Energieproportionalität ist das Entwurfsziel, dass die Leistungsaufnahme proportional zur nutzbaren Last steigen soll, die ein System bearbeitet.
Hohe Leistungsaufnahme im Leerlauf schwächt die Energieproportionalität, weil ein gering ausgelasteter Server dennoch beträchtliche Energie verbraucht.
Exclusive-Zustand
Der Exclusive-Zustand bei MESI kennzeichnet einen unveränderten Block, den nur ein Cache hält, und erlaubt bei einem Schreibzugriff den stillschweigenden Übergang nach Modified.
Ein Lesezugriff mit anschließendem privatem Schreibzugriff profitiert vom Exclusive-Zustand, weil der Schreibzugriff keine Upgrade-Anfrage benötigt.

F

False Sharing
False Sharing ist die gegenseitige Beeinträchtigung durch Kohärenz zwischen Kernen, die auf verschiedene Variablen in einem Cacheblock zugreifen, wenn mindestens ein Kern schreibt.
False Sharing kann getrennte Zähler verlangsamen, wenn ihre schreibenden Threads wiederholt den Besitz eines Blocks austauschen.
Fan-out
Fan-out ist die Aufteilung der Arbeit einer Anfrage auf mehrere Server, deren benötigte Antworten zu ihrem Abschluss beitragen.
Ein größerer Fan-out bietet einer seltenen Verzögerung auf einem einzelnen Server mehr Gelegenheiten, die gesamte Anfrage aufzuhalten.
Feingranulares Multithreading
Feingranulares Multithreading wählt in jedem Taktzyklus einen Thread, üblicherweise reihum unter bereiten Kontexten, und überspringt wartende Kontexte.
Feingranulares Multithreading kann kurze Arbeitsphasen mehrerer Threads abwechseln, um Pipeline-Wartezeiten abzudecken.
Fetch-and-Add
Fetch-and-Add ist eine atomare Operation, die den vorherigen Wert einer Speicherstelle zurückgibt und zugleich unteilbar einen angegebenen Betrag addiert.
Fetch-and-Add kann jede Erhöhung bewahren, wenn mehrere Threads gleichzeitig einen gemeinsamen Zähler aktualisieren.
Flynnsche Taxonomie
Die flynnsche Taxonomie klassifiziert Hardware auf einer gewählten Rechnerebene danach, ob Befehlsströme und Datenströme einzeln oder mehrfach vorliegen.
Die flynnsche Taxonomie kann unabhängige CPU-Kerne anders beschreiben als die SIMD-Einheiten innerhalb dieser Kerne.

G

Globaler Speicher
Der globale Speicher ist das GPU-DRAM, auf das über das gesamte Grid hinweg zugegriffen werden kann. Die Zugriffe laufen über die Cachehierarchie des Geräts.
Ein Kernel kann Kacheln im Shared Memory wiederverwenden, um Daten seltener erneut aus dem globalen Speicher zu lesen.
Granularität
Die Granularität ist der Umfang der Berechnungen, die in einer parallelen Berechnung zwischen Kommunikations- oder Synchronisationsereignissen ausgeführt werden.
Größere Granularität kann die Nachrichtenkosten pro Operation senken, aber zu wenige Teilstücke für eine gute Lastverteilung übrig lassen.
Grid
Ein Grid ist die Gesamtheit der Threadblöcke, die ein GPU-Kernelstart erzeugt. Seine gewöhnlichen Blöcke können in beliebiger Reihenfolge laufen.
Ein Grid muss genügend Blöcke enthalten, um alle Daten abzudecken, wenn der Kernel nur ein Element pro Thread bearbeitet.
Grobgranulares Multithreading
Grobgranulares Multithreading wechselt bei langen Wartezeiten den Thread und erlaubt zwischen kostspieligen Wechseln eine längere Ausführung eines einzelnen Threads.
Grobgranulares Multithreading kann nach einem Fehlzugriff im Cache der letzten Ebene wechseln, der einen langen Speicherzugriff benötigt.
Gustafsonsches Gesetz
Das gustafsonsche Gesetz schätzt den skalierten Speedup anhand der Prozessorzahl und des beim parallelen Lauf gemessenen sequenziellen Zeitanteils ab.
Das gustafsonsche Gesetz beschreibt, wie ein größeres paralleles Problem einen größeren Rechner innerhalb eines ähnlichen Zeitbudgets nutzen kann.

H

Hardware-Multithreading
Hardware-Multithreading hält mehrere Threadkontexte in einem Kern vor, sodass er bereite Arbeit ausführen kann, während ein anderer Thread wartet.
Hardware-Multithreading kann Speicherwartezyklen füllen, ohne einen vollständigen physischen Kern zu verdoppeln.
Heimatknoten
Ein Heimatknoten verwaltet den Verzeichniseintrag eines bestimmten Speicherblocks und koordiniert Anfragen zu dessen Cachekopien.
Verschiedene Blöcke können verschiedene Heimatknoten haben, wodurch Verzeichnisspeicher und Anfragebearbeitung verteilt werden.
Host
Der Host ist die CPU-Seite eines heterogenen Programms und für die Organisation von Gerätespeicher, Übertragungen, Starts und Ergebnisverwendung verantwortlich.
Der Host kann nach einem Start fortfahren, muss aber auf fertige Geräteergebnisse warten, bevor er sie verarbeitet.

I

Indizierter Zugriff
Ein indizierter Zugriff ermittelt Elementadressen aus Indizes und unterstützt so unregelmäßige Gather- und Scatter-Zugriffe über feste Schrittweiten hinaus.
Ein indizierter Zugriff kann die Arrayeinträge holen, die eine unregelmäßige Liste von Positionen auswählt.
Invalid-Zustand
Der Invalid-Zustand kennzeichnet einen Cacheblock, dessen Inhalt nicht zur Bedienung eines Lese- oder Schreibzugriffs des Prozessors verwendet werden darf.
Ein späterer Lesezugriff auf einen Block im Invalid-Zustand muss über die Speicherhierarchie eine gültige Kopie beschaffen.
Iterationsübergreifende Abhängigkeit
Eine iterationsübergreifende Abhängigkeit entsteht, wenn eine Iteration einen Wert benötigt, den eine andere Iteration erzeugt hat, wodurch ihre Ausführungsreihenfolge eingeschränkt wird.
Eine akkumulierende Rekurrenz hat eine iterationsübergreifende Abhängigkeit, weil jeder neue Wert das vorherige Ergebnis verwendet.

K

Kernel
Ein Kernel ist eine Gerätefunktion, die über viele GPU-Threads hinweg gestartet wird. Jeder führt die Funktion mit eigenen Indizes und Daten aus.
Ein SAXPY-Kernel weist jedem gültigen Thread ein Arrayelement zu und prüft die obere Indexschranke.
Knickpunkt
Der Knickpunkt ist die Intensität, bei der das Bandbreitendach auf das Rechenleistungsdach trifft. Sie entspricht der Spitzenrechenleistung geteilt durch die Bandbreite.
Bei einem Knickpunkt von zehn Gleitkommaoperationen pro Byte liegt ein Kernel mit zwei Gleitkommaoperationen pro Byte unterhalb des rechenleistungsbegrenzten Bereichs.
Kohärenzbedingter Fehlzugriff
Ein kohärenzbedingter Fehlzugriff entsteht, wenn ein Zugriff einen Block erneut holen muss, den eine Kohärenzaktion eines anderen Prozessors invalidiert hat.
Der schreibende Zugriff auf eine benachbarte Variable kann einen kohärenzbedingten Fehlzugriff verursachen, selbst wenn sich die eigene Variable des Lesers nie ändert.
Kohärenzverzeichnis
Ein Kohärenzverzeichnis erfasst den Kohärenzzustand von Speicherblöcken und die Besitzer von Cachekopien, sodass Anfragen an die betreffenden Caches gesendet werden können.
Ein Kohärenzverzeichnis leitet eine Leseanfrage an den Cache mit der neuesten Modified-Kopie weiter, statt sie an alle zu senden.
Kontrollflussdivergenz
Kontrollflussdivergenz tritt auf, wenn Threads innerhalb eines Warps unterschiedliche Pfade nehmen, sodass diese Pfade mit unterschiedlichen aktiven Masken ausgeführt werden müssen.
Kontrollflussdivergenz kann die Hälfte eines Warps untätig lassen, während die dem anderen Pfad zugewiesenen Threads ausgeführt werden.

L

Lastverteilung
Die Lastverteilung ist die Aufteilung nutzbarer Arbeit auf Prozessoren, sodass die Überlastung einer Arbeitseinheit die Phase nicht unnötig verzögert.
Eine schlechte Lastverteilung lässt sieben Arbeitseinheiten warten, während eine einen unverhältnismäßig großen Anteil fertigstellt.
Latenzverdeckung
Latenzverdeckung führt während einer Wartezeit andere bereite Arbeit aus und verbessert so die Ressourcennutzung, ohne die wartende Operation selbst zu verkürzen.
Eine GPU nutzt Latenzverdeckung, wenn ihr Scheduler während eines ausstehenden Speicherzugriffs einen anderen Warp auswählt.
Leistungsgrenze
Eine Leistungsgrenze ist eine niedrigere Schranke innerhalb einer Roofline-Analyse, die eine Einschränkung wie fehlendes SIMD oder ungünstige Zugriffsmuster darstellt.
Eine Bandbreitengrenze unterhalb des Hauptdachs kann zeigen, wie viel Rechenleistung durch ineffiziente Speicherzugriffe verloren geht.
Logischer Prozessor
Ein logischer Prozessor ist ein Hardwarethreadkontext, der dem Betriebssystem als Ausführungsplatz für einen Softwarethread erscheint.
Ein Chip mit sechs Kernen und zwei Kontexten pro Kern stellt zwölf logische Prozessoren bereit, die sich sechs Kerne teilen.

M

Maske
Eine Maske wählt aktive Elemente einer SIMD- oder Vektoroperation aus und ermöglicht bedingte Arbeit ohne einen eigenen Befehlsstrom pro Lane.
Eine Maske kann Aktualisierungen für Arrayelemente unterdrücken, die einen Vergleich nicht bestehen oder außerhalb des gültigen Restbereichs liegen.
MIMD
MIMD ist eine Hardwareklasse mit mehreren unabhängig gesteuerten Befehlsströmen, die auf mehreren Datenströmen arbeiten.
Ein Cluster ist MIMD, wenn seine Knoten unabhängig in ihren Berechnungen voranschreiten und Nachrichten austauschen.
MISD
MISD ist die Hardwareklasse mit mehreren Befehlsströmen, die auf einen Datenstrom wirken; nur wenige praktische Rechner passen eindeutig dazu.
Die Bezeichnung MISD vervollständigt die vier Kombinationen einzelner und mehrerer Ströme, während vorgeschlagene reale Beispiele häufig von der Interpretation abhängen.
Modified-Zustand
Der Modified-Zustand kennzeichnet die einzige gültige Cachekopie eines Blocks, deren Daten beschrieben wurden und neuer als der Speicherinhalt sind.
Ein Kern kann einen Block im Modified-Zustand wiederholt aktualisieren, ohne erneut Schreibberechtigung zu erlangen.
MPI
MPI ist eine standardisierte Schnittstelle zum Nachrichtenaustausch, über die Prozesse in einem parallelen Programm Daten austauschen und kollektive Operationen ausführen.
Eine MPI-Reduktion führt verteilte Teilsummen zusammen, ohne Daten entfernter Knoten als gewöhnliche lokale Zeiger zu behandeln.
Multiprozessor mit gemeinsamem Speicher
Ein Multiprozessor mit gemeinsamem Speicher ermöglicht Prozessoren, durch Lade- und Speicherzugriffe in einem physischen Adressraum zu kommunizieren.
Ein Multiprozessor mit gemeinsamem Speicher kann dennoch getrennte private Caches und auf Sockel verteilten Speicher besitzen.

N

Nebenläufigkeit
Nebenläufigkeit ist der Fortschritt mehrerer Aufgaben während sich überschneidender Zeiträume, auch durch abwechselnde Nutzung einer Ausführungsressource.
Ein Einkernbetriebssystem unterstützt Nebenläufigkeit, indem es zwischen einem Download und einem Editor wechselt.
NUMA
NUMA ist eine Organisation mit gemeinsamem Speicher, bei der die Kosten eines Speicherzugriffs von der Lage des Prozessors relativ zu den Daten abhängen.
Eine NUMA-Arbeitslast kann die mittlere Latenz senken, indem sie häufig genutzte Seiten nahe bei den zugreifenden Threads ablegt.

P

Parallele Effizienz
Die parallele Effizienz ist der Speedup geteilt durch die Prozessorzahl und drückt den nutzbaren Gewinn im Verhältnis zu den zugewiesenen Prozessoren aus.
Ein Speedup von sechs auf acht Prozessoren ergibt eine parallele Effizienz von 75 %, obwohl die Zeitersparnis größer ist.
Parallelisierungsaufwand
Der Parallelisierungsaufwand sind zusätzliche Ausführungskosten durch die parallele Organisation, etwa für Einplanung, Kommunikation, Synchronisation oder zusätzliche Arbeit.
Der Parallelisierungsaufwand kann so stark wachsen, dass eine Aufgabe nach Erhöhung ihrer Prozessorzahl länger dauert.
Parallelität
Parallelität ist die gleichzeitige Ausführung von Operationen auf getrennten Hardwareressourcen, um die Latenz zu senken oder den Durchsatz zu erhöhen.
Eine Simulation nutzt Parallelität, wenn mehrere Kerne unabhängige Bereiche zum selben Zeitpunkt aktualisieren.
Power Wall
Die Power Wall ist die Beschränkung durch Leistungsaufnahme und Wärme, die Leistungsgewinne durch weitere Steigerung der Prozessortaktfrequenz begrenzt.
Die Power Wall veranlasste Chipentwickler, zusätzliche Transistoren für mehr Prozessorkerne einzusetzen.
Präsenzvektor
Ein Präsenzvektor verwendet in einem Verzeichnis mit vollständigem Vektor ein Bit pro Kern, um festzuhalten, welche Caches einen bestimmten Block besitzen.
Ein Präsenzvektor für 64 Kerne benötigt ohne die Kohärenzzustandsbits acht Byte pro erfasstem Block.
PUE
PUE ist das Verhältnis der Gesamtenergie der Anlage zur Energie der IT-Geräte im selben Zeitraum und misst den Energieaufwand außerhalb der IT-Last.
Ein PUE-Wert von 1,2 bedeutet, dass die Gesamtenergie der Anlage 20 % über der IT-Energie liegt, ohne die nutzbare Arbeit innerhalb der Server zu messen.

R

Rang
Ein Rang ist die Kennung eines MPI-Prozesses innerhalb eines Kommunikators. Sie dient dazu, Teilnehmer auszuwählen und Daten oder Kommunikationsrollen zuzuweisen.
Ein Prozess bestimmt anhand seines Rangs, welchen Arraybereich er summiert und wohin er sein Teilergebnis sendet.
Rechengebundener Kernel
Ein rechengebundener Kernel hat eine so hohe Intensität, dass im Roofline-Modell die maximale Rechenkapazität die niedrigere Grenze bildet.
Kachelung kann eine Berechnung in Richtung eines rechengebundenen Kernels verschieben, indem Daten für viele Rechenoperationen wiederverwendet werden.
Reduktionsbaum
Ein Reduktionsbaum führt Teilergebnisse in aufeinanderfolgenden parallelen Stufen zusammen und reduziert viele Werte über einen kurzen abhängigen Pfad auf einen Wert.
Ein Reduktionsbaum führt 32 Teilsummen in fünf Stufen paarweise zusammen, statt 31 aufeinanderfolgende Additionen auszuführen.
Roofline-Modell
Das Roofline-Modell begrenzt die erreichbare Rechenleistung durch den kleineren Wert aus Spitzenrechenleistung und Bandbreite mal Intensität.
Das Roofline-Modell hilft zu entscheiden, ob schnellere Berechnungen oder weniger Datenübertragung die Schranke eines Kernels anheben können.

S

Schreibinvalidierungsprotokoll
Ein Schreibinvalidierungsprotokoll gewährt einem schreibenden Kern exklusive Schreibberechtigung, indem es andere Cachekopien seines Blocks unbrauchbar macht.
Ein Schreibinvalidierungsprotokoll erlaubt einem Besitzer wiederholte Schreibzugriffe in Modified, ohne jeden neuen Wert an alle zu senden.
Schreibpropagierung
Schreibpropagierung ist die Kohärenzanforderung, dass ein Schreibzugriff eines Prozessors schließlich für Lesezugriffe anderer Prozessoren sichtbar wird.
Schreibpropagierung stellt sicher, dass ein neuer Wert nicht dauerhaft im privaten Cache des schreibenden Kerns verborgen bleibt.
Schreibserialisierung
Schreibserialisierung verlangt, dass in einem kohärenten Speichersystem alle Prozessoren in der Reihenfolge der Schreibzugriffe auf dieselbe Stelle übereinstimmen.
Schreibserialisierung verhindert, dass Prozessoren zwei Schreibzugriffe auf dieselbe Stelle X in entgegengesetzter Reihenfolge beobachten.
Schwache Skalierung
Schwache Skalierung lässt die Gesamtarbeit proportional zur Prozessorzahl wachsen und hält so die Arbeit pro Prozessor während des Experiments konstant.
Ein Experiment zur schwachen Skalierung verdoppelt die Daten, wenn es die Prozessorzahl verdoppelt, und vergleicht dann die Gesamtlaufzeiten.
Sequenzielle Konsistenz
Sequenzielle Konsistenz verlangt Ergebnisse, die einer Verschachtelung aller Prozessoroperationen entsprechen, welche die Programmreihenfolge jedes Prozessors bewahrt.
Sequenzielle Konsistenz beschränkt den gemeinsamen Ablauf, ohne zu verlangen, dass Prozessoren mit derselben Geschwindigkeit arbeiten.
Sequenzieller Anteil
Der sequenzielle Anteil ist der Teil der Ausführungszeit des Ausgangslaufs, der im parallelen Modell nicht auf Prozessoren aufgeteilt werden kann.
Ein sequenzieller Anteil von 0,1 lässt ein Zehntel der ursprünglichen Zeit übrig, selbst wenn alle parallele Arbeit kostenlos würde.
Shared Memory
Shared Memory ist vom Programm verwalteter GPU-Speicher auf dem Chip, der Threads eines Blocks zur Zusammenarbeit und Datenwiederverwendung zur Verfügung steht.
Ein Block lädt eine Kachel in den Shared Memory, bevor er sie für mehrere Rechenoperationen wiederverwendet.
Shared-Zustand
Der Shared-Zustand kennzeichnet eine unveränderte, schreibgeschützte Cachekopie eines Blocks, die auch in anderen Caches vorhanden sein kann.
Ein schreibender Kern muss Besitz anfordern, bevor er einen Block im Shared-Zustand ändert, weil andere Leser ihn besitzen können.
SIMD
SIMD ist eine Hardwareklasse, bei der ein Befehl dieselbe Operation auf mehreren Datenelementen oder Rechen-Lanes steuert.
Eine Arrayaddition mit acht Lanes ist SIMD, obwohl sie mit einem ausgegebenen Befehl acht Elementadditionen ausführt.
SIMD-Lane
Eine SIMD-Lane ist eine Elementposition und die zugehörige Rechenarbeit innerhalb einer breiten Operation, die durch einen gemeinsamen Befehl gesteuert wird.
Eine 256-Bit-Addition hat acht SIMD-Lanes für 32-Bit-Gleitkommazahlen einfacher Genauigkeit, aber vier Lanes für 64-Bit-Zahlen doppelter Genauigkeit.
SIMT
SIMT ist eine GPU-Ausführungsart, die unabhängige Threads bereitstellt und zugleich einen Befehl für die aktiven Threads einer Gruppe ausgibt.
SIMT-Code berechnet einen Index pro Thread, obwohl die Befehlsausgabe innerhalb jedes Warps gemeinsam erfolgt.
Simultanes Multithreading
Simultanes Multithreading ermöglicht einem Kern mit Mehrfachausgabe, innerhalb desselben Taktzyklus Befehle verschiedener Hardwarethreads auszugeben.
Simultanes Multithreading füllt freie Ausgabeplätze, wenn ein Thread nicht genügend bereite Befehle liefern kann.
SISD
SISD ist eine Hardwareklasse mit einem Befehlsstrom und einem Datenstrom, zu der auch herkömmliche skalare Kerne mit Pipeline gehören.
Ein skalarer Kern mit Pipeline bleibt SISD, weil überlappende Befehle weiterhin einem Befehlsstrom folgen.
Snooping
Snooping ist eine Kohärenzmethode, bei der Cachecontroller Rundsendeanfragen überwachen und die Berechtigungen oder Daten ihrer Blöcke aktualisieren.
Snooping ermöglicht einem Besitzer in Modified, die Leseanfrage eines anderen Kerns zu erkennen und den aktuellen Blockinhalt zu liefern.
Speedup
Der Speedup ist die beste sequenzielle Ausführungszeit geteilt durch die parallele Ausführungszeit für die verglichene Arbeitslast.
Ein Programm, das statt in 60 s in 12 s fertig wird, hat gegenüber seinem sequenziellen Ausgangslauf einen Speedup von fünf.
Speichergebundener Kernel
Ein speichergebundener Kernel hat ein niedrigeres Speicherbandbreitendach als Rechenleistungsdach, sodass seine obere Rate von der Datenversorgung abhängt.
Sobald ein speichergebundener Kernel die DRAM-Bandbreite ausschöpft, kann eine breitere Recheneinheit allein seine Roofline-Schranke nicht anheben.
Speicherkonsistenzmodell
Ein Speicherkonsistenzmodell definiert zulässige beobachtbare Reihenfolgen und Ergebnisse von Lese- und Schreibzugriffen, auch auf verschiedene Speicherstellen.
Ein Speicherkonsistenzmodell bestimmt, wie ein anderer Prozessor Zugriffe auf ein Flag und dessen Daten beobachten darf.
SPMD
SPMD ist ein Programmierstil, bei dem Arbeitseinheiten Kopien desselben Programms ausführen und anhand ihrer Kennungen unterschiedliche Daten auswählen.
Eine SPMD-Arraysumme verwendet die ID jeder Arbeitseinheit, um einen Bereich auszuwählen, bevor die Teilergebnisse zusammengeführt werden.
Starke Skalierung
Starke Skalierung misst, wie sich die Gesamtlaufzeit ändert, wenn mehr Prozessoren dasselbe Rechenproblem fester Größe ausführen.
Ein Experiment zur starken Skalierung hält die Zellzahl einer Simulation fest und erhöht zugleich die Anzahl zugewiesener Prozessoren.
Streaming Multiprocessor
Ein Streaming Multiprocessor ist eine Verarbeitungseinheit in NVIDIA-GPUs, die vorgehaltene Warps auf Rechen-Lanes und Speicher auf dem Chip einplant.
Ein Streaming Multiprocessor kann einen anderen bereiten Warp ausgeben, wenn ein vorgehaltener Warp auf den globalen Speicher wartet.
Strip-Mining
Strip-Mining teilt eine lange Schleife in Stücke, die zur Vektorkonfiguration passen, und aktualisiert den Fortschritt nach jedem verarbeiteten Stück.
Strip-Mining kann 100 Elemente mit den aufeinanderfolgenden aktiven Längen 32, 32, 32 und vier verarbeiten.
Struktur von Arrays
Eine Struktur von Arrays speichert die Werte jedes Felds in einem eigenen Array, sodass die Werte eines Felds für den Vektorzugriff zusammenhängend liegen.
Eine Struktur von Arrays hält alle x-Koordinaten zusammen, wenn eine Geometrieschleife nur dieses Feld verarbeitet.
Superlinearer Speedup
Ein superlinearer Speedup ist ein gemessener Speedup, der die Prozessorzahl übersteigt. Er ist möglich, wenn die parallele Aufteilung auch die Kosten der Arbeit senkt.
Besseres Passen in den Cache kann einen superlinearen Speedup erzeugen, wenn jeder Teilbereich die DRAM-Fehlzugriffe des sequenziellen Laufs vermeidet.

T

Tail-Latenz
Die Tail-Latenz bezeichnet den Bereich hoher Verzögerungen unter den Antwortzeiten, der eine Anfrage dominieren kann, die Antworten vieler Server benötigt.
Eine aufgefächerte Anfrage wartet auf ihre langsamste benötigte Antwort, sodass die Tail-Latenz eines einzelnen Servers den ganzen Dienst betrifft.
Threadblock
Ein Threadblock ist eine Gruppe von GPU-Threads, die über Shared Memory zusammenarbeiten und sich mit einer blockweiten Barriere synchronisieren können.
Ein Threadblock kann seine Teilsummen zusammenführen, während ein späterer Kernel Ergebnisse getrennter Blöcke zusammenführt.
Threadparallelität
Threadparallelität führt mehrere Threads gleichzeitig aus, die jeweils einen eigenen Befehlszähler und Registerzustand besitzen.
Ein Bildrenderprogramm nutzt Threadparallelität, indem es unterschiedliche Bildbereiche verschiedenen Arbeitseinheiten zuweist.
Torus
Ein Torus ist ein Gitternetzwerk mit Verbindungen zwischen gegenüberliegenden Rändern, die weitere Pfade hinzufügen und die Querschnittskapazität erhöhen.
Ein 8 × 8-Torus hat 128 Verbindungen, einschließlich der Randverbindungen, die einem gewöhnlichen Gitter fehlen.
True Sharing
True Sharing tritt auf, wenn Prozessoren über dasselbe Speicherwort kommunizieren, sodass ihre Kohärenzinteraktion dieselben Daten betrifft.
Ein Erzeuger schreibt einen Wert, den ein Verbraucher liest, wodurch True Sharing dieser Kommunikationsvariablen entsteht.

U

UMA
UMA ist eine Organisation mit gemeinsamem Speicher und ungefähr gleichförmiger Speicherzugriffszeit von den Prozessoren auf Speicherstellen.
Ein kleiner UMA-Rechner bietet ähnliche Speicherzugriffspfade, ohne zwischen lokalen und entfernten Sockeln zu unterscheiden.

Ü

Überbuchung
Überbuchung tritt auf, wenn obere Netzwerkverbindungen weniger Kapazität bieten als die Gesamtkapazität der unteren Verbindungen, die sie speisen.
Ein Rack mit 400 Gbit/s an Serververbindungen und 100 Gbit/s an aufwärtsführenden Verbindungen hat eine Überbuchung von 4:1.

V

Vektorlänge
Die Vektorlänge ist die Anzahl aktiver Elemente, die Vektorbefehle unter der aktuellen Vektorkonfiguration verarbeiten.
Eine kurze Vektorlänge erlaubt dem letzten Schleifendurchlauf, seine acht verbleibenden Elemente ohne separate skalare Restschleife zu aktualisieren.
Verbindungsbandbreite
Die Verbindungsbandbreite ist die verfügbare Datenrate einer Netzwerkverbindung, gemessen nach einer einheitlichen Konvention für die Kapazität je Richtung.
Eine Topologie mit mehr Verbindungen kann eine größere Gesamtkapazität haben, selbst wenn jede Verbindungsbandbreite unverändert bleibt.
Verfügbarkeit
Verfügbarkeit ist die Fähigkeit eines Dienstes, trotz Ausfällen nutzbar zu bleiben. In großem Maßstab wird sie durch Redundanz, erneute Versuche und Umleitung unterstützt.
Ein Warehouse-Scale-Dienst schützt seine Verfügbarkeit, indem er neue Anfragen an einem ausgefallenen Server vorbeileitet.
Verkettung
Verkettung überlappt abhängige Vektoroperationen, indem eine verarbeitende Operation mit frühen Elementen beginnen kann, bevor die erzeugende Operation alle Elemente fertigstellt.
Durch Verkettung kann eine Addition die ersten Produkte verwenden, während die Multiplikationspipeline weitere Produkte erzeugt.
VLEN
VLEN ist die Vektorregisterbreite einer RVV-Implementierung in Bit und unterscheidet sich von der aktiven Elementzahl und der Anzahl paralleler Ausführungs-Lanes.
Ein größeres VLEN kann mehr Elemente aufnehmen, während das Programm weiterhin um die erhaltene aktive Länge weiterrückt.

W

Warehouse-Scale Computer
Ein Warehouse-Scale Computer betreibt ein großes Gebäude mit vernetzten Servern, Stromversorgung und Kühlung als eine Plattform für Dienste und Stapelverarbeitung.
Ein Warehouse-Scale Computer muss neben dem Anfragedurchsatz auch Energie und alltägliche Ausfälle berücksichtigen.
Warp
Ein Warp ist eine Gruppe von 32 Threads in NVIDIAs Ausführungsmodell; aktive Threads teilen sich die Befehlsausgabe und behalten getrennte Daten.
Threads eines Warps können aufeinanderfolgende Indizes verwenden, sodass ihre Ladezugriffe zu effizienten Speichertransaktionen zusammengefasst werden.

Z

Zugriff mit fester Schrittweite
Ein Zugriff mit fester Schrittweite besucht aufeinanderfolgende Elemente in einem festen Adressabstand, etwa dem Abstand zwischen Einträgen einer Matrixspalte.
Ein Zugriff mit fester Schrittweite entlang einer Spalte einer Matrix mit 100 Spalten aus Gleitkommazahlen doppelter Genauigkeit rückt zwischen benachbarten Spalteneinträgen um 800 Byte weiter.

Über diese Einheit

Von StudeliFehler melden

Erstelle deine eigenen Lernmaterialien

Mach aus deinen Notizen, Folien und Dokumenten Lernleitfäden, Übungsfragen, Karteikarten und 6 weitere Tools.

Jetzt starten