Vektorprozessor

Im Computer, a Vektorprozessor oder Array -Prozessor ist ein Zentrale Verarbeitungseinheit (CPU), das eine implementiert Befehlssatz wo es ist Anweisungen sind so konzipiert, dass sie effizient und effektiv bei großem Betrieb arbeiten Eindimensionale Arrays von Daten genannt Vektoren. Dies steht im Gegensatz zu Skalarprozessoren, deren Anweisungen nur bei einzelnen Datenelementen arbeiten, und im Gegensatz zu einigen derselben Skalarprozessoren mit zusätzlichen Einzelanweisung, mehrere Daten (SIMD) oder SWAR Arithmetische Einheiten. Vektorprozessoren können die Leistung bei bestimmten Workloads erheblich verbessern, insbesondere bei Arbeitsbelastungen numerische Simulation und ähnliche Aufgaben. Die Vektorverarbeitungstechniken arbeiten auch in Videospielkonsole Hardware und in Grafikbeschleuniger.

Vektormaschinen erschienen in den frühen 1970er Jahren und dominierten Supercomputer Design in den 1970er Jahren bis in die 1990er Jahre, insbesondere die verschiedenen Cray Plattformen. Der schnelle Sturz in der Preis-Leistungs-Verhältnis von konventionellem Mikroprozessor Entwürfe führten in den neunziger Jahren zu einem Rückgang der Vektor -Supercomputer.

Geschichte

Frühe Arbeit

Die Entwicklung der Vektorverarbeitung begann Anfang der 1960er Jahre bei Westinghouse in ihrem "Solomon" -Projekt. Das Ziel von Solomon war es, die mathematische Leistung dramatisch zu erhöhen, indem eine große Anzahl einfacher Mathematik-Co-Prozessoren unter der Kontrolle eines einzelnen Meisters Zentralprozessor. Die CPU fütterte alle gemeinsame Anweisungen für alle Arithmetische Logikeinheiten (Alus), eine pro Zyklus, aber mit einem anderen Datenpunkt für jeden, an dem sie arbeiten können. Dies ermöglichte es der Solomon -Maschine, eine einzelne anzuwenden Algorithmus zu einem großen Datensatz, in Form eines Arrays gefüttert.

1962 hat Westinghouse das Projekt abgesagt, aber die Anstrengungen wurden neu gestartet. Universität von Illinois als die ILLIAC IV. Ihre Version des Designs forderte ursprünglich eine 1 Gflops Maschine mit 256 Alus, aber als es 1972 endlich geliefert wurde, hatte es nur 64 Alus und konnte nur 100 bis 150 Mflops erreichen. Dennoch zeigte sich das grundlegende Konzept solide und bei datenintensiver Anwendungen wie z. Computerflüssigkeitsdynamik, der Ilikas war die schnellste Maschine der Welt. Der iliakische Ansatz der Verwendung separater ALUs für jedes Datenelement ist für spätere Entwürfe nicht üblich und wird häufig unter einer separaten Kategorie bezeichnet. massiv parallel Computer. Um diese Zeit kategorisierte Flynn diese Art der Verarbeitung als frühe Form von Simt.

A Computer für Operationen mit Funktionen wurde 1967 von Kartsev präsentiert und entwickelt.[1]

Supercomputer

Die ersten Vektor -Supercomputer sind die Steuerungsdatengesellschaft Stern-100 und Texas Instrumente Erweiterter wissenschaftlicher Computer (ASC), die 1974 bzw. 1972 eingeführt wurden.

Der Basis -ASC (d. H. "One Pipe") Alu verwendete eine Pipeline -Architektur, die sowohl Skalar- als auch Vektorberechnungen unterstützte, wobei die Spitzenleistung ungefähr 20 Mflops erreichte, die bei der Verarbeitung langer Vektoren leicht erreicht wurden. Erweiterte ALU -Konfigurationen unterstützten "zwei Rohre" oder "vier Rohre" mit einer entsprechenden 2x- oder 4 -fachen Leistungsverstärkung. Die Speicherbandbreite reichte aus, um diese erweiterten Modi zu unterstützen.

Der Star-100 war ansonsten langsamer als der von CDCs eigene Supercomputer mögen die CDC 7600Aber bei datenbezogenen Aufgaben konnten sie mithalten und viel kleiner und kostengünstiger sind. Die Maschine brauchte jedoch auch eine beträchtliche Zeit, um die Vektoranweisungen zu dekodieren und sich auf den Prozess vorzubereiten. Daher mussten sehr bestimmte Datensätze arbeiten, bevor sie tatsächlich etwas beschleunigt wurde.

Die Vektorechnik wurde 1976 erstmals von den Berühmten vollständig ausgenutzt Cray-1. Anstatt die Daten wie das Star-100 und ASC im Speicher zu lassen, hatte das Cray-Design acht Vektorregister, die jeweils vierundsechzig 64-Bit-Wörter enthielten. Die Vektoranweisungen wurden zwischen Registern angewendet, was viel schneller ist als mit dem Hauptspeicher zu sprechen. Während der Stern-100 einen einzelnen Betrieb auf einen langen Vektor im Speicher anwenden und dann zum nächsten Vorgang übergehen würde, lädt das Cray-Design einen kleineren Abschnitt des Vektors in Register und wendet dann so viele Vorgänge wie möglich auf diese Daten an , damit viele der viel langsameren Speicherzugriffsvorgänge vermieden werden.

Das Cray -Design wurde verwendet Pipeline Parallelität Implementieren von Vektoranweisungen anstelle von mehreren ALUs. Darüber hinaus hatte das Design die Pipelines für unterschiedliche Anweisungen vollständig separate Anweisungen, beispielsweise wurde Addition/Subtraktion in unterschiedlicher Hardware als Multiplikation implementiert. Dies ermöglichte es, eine Menge Vektoranweisungen in die einzelnen Alu -Untereinheiten zu pipelieren, eine Technik, die sie nannten Vektorkettung. Der Cray-1 hatte normalerweise eine Leistung von etwa 80 Mflops, aber mit bis zu drei Ketten konnte er bei 240 Mflops ihren Höhepunkt erreichten und im Durchschnitt bei 150-weitaus schneller als jede Maschine der Ära.

Cray J90 Prozessormodul mit vier Skalar-/Vektorprozessoren

Andere Beispiele folgten. Steuerungsdatengesellschaft versuchte wieder in den High-End-Markt mit seinem einzutreten ETA-10 Maschine, aber es verkaufte sich schlecht und sie nutzten das als Gelegenheit, das Supercomputationsfeld vollständig zu verlassen. In den frühen und Mitte der 1980er Jahre japanische Unternehmen (Fujitsu, Hitachi und Nippon Electric Corporation (NEC) Einführte registrierungsbasierte Vektormaschinen, die dem Cray-1 ähnlich sind, in der Regel etwas schneller und viel kleiner. Oregon-basierend Schwimmende Punktsysteme (FPS) Erstellte Add-On-Array-Prozessoren für Minicomputer, später ihre eigenen bauen Minisupercomputer.

Währenddessen war Cray weiterhin der Performance -Leiter und übertraf den Wettbewerb ständig mit einer Reihe von Maschinen, die zum zur Cray-2, Cray x-mp und Cray Y-Mp. Seitdem hat sich der Supercomputermarkt viel mehr darauf konzentriert massiv parallel Verarbeitung eher als bessere Implementierungen von Vektorprozessoren. IBM entwickelte jedoch die Vorteile der Vektorverarbeitung und entwickelte sich jedoch Virtuelle Vektorarchitektur Für die Verwendung in Supercomputern, die mehrere Skalarprozessoren entwickelt haben, um als Vektorprozessor zu fungieren.

Obwohl Vector Supercomputer, die dem Cray-1 ähneln SX -Serie von Computern. Zuletzt die SX-Ourora Tsubasa platziert den Prozessor und entweder 24 oder 48 Gigabyte Speicher auf einen HBM 2 Modul innerhalb einer Karte, die einem Grafik-Coprozessor physisch ähnelt, aber anstatt als Co-Prozessor zu dienen, ist es der Hauptcomputer mit dem PC-kompatiblen Computer, in den es angeschlossene Servierfunktionen steckt.

GPU

Moderne Grafikverarbeitungseinheiten (GPUS) Fügen Sie eine Auswahl an Shader -Pipelines was kann durch getrieben werden von Kernel berechnenund kann als Vektorprozessoren betrachtet werden (unter Verwendung einer ähnlichen Strategie zum Verstecken von Speicherlatenzen). Wie gezeigt in Flynns 1972er Papier Der wichtigste Unterscheidungsfaktor von SIMT-basiertem GPUs besteht darin, dass es über einen einzelnen Befehlsdecoder-Broadcaster verfügt, aber dass die Kerne, die dieselbe Anweisung empfangen und ausführen Ihre eigenen unabhängigen L1 -Daten Caches. Obwohl alle Kerne gleichzeitig die genaue Anweisung in der Sperrschritte miteinander ausführen, tun sie dies mit vollständig unterschiedlichen Daten von vollständig unterschiedlichen Speicherorten. Das ist bedeutend komplexer und involvierter als "Packed Simd", was streng auf die Ausführung paralleler pipelinierter arithmetischer Operationen beschränkt ist. Obwohl die genauen internen Details der heutigen kommerziellen GPUs proprietäre Geheimnisse sind, sind die Miaow[2] Das Team war in der Lage, anekdotische Informationen zusammenzusetzen, die ausreichten, um eine Teilmenge der AMDGPU -Architektur zu implementieren.[3]

Vergleich mit modernen Architekturen

Ab 2016 Die meisten Rohstoff-CPUs implementieren Architekturen mit SIMD-Anweisungen mit fester Länge. Bei der ersten Inspektion können diese als Form der Vektorverarbeitung betrachtet werden, da sie an mehreren (vektorisierten, expliziten Länge) Datensätzen und Merkmalen von Vektorprozessoren ausleihen. Jedoch per Definition Die Zugabe von SIMD kann nicht für sich selbst einen Prozessor qualifizieren wie Ein tatsächlicher Vektorprozessor, weil SIMD festgelegt ist und die Vektoren variabel sind. Der Unterschied wird nachstehend mit Beispielen dargestellt, die die drei Kategorien zeigen und vergleichen: reine SIMD, vorherige SIMD und reine Vektorverarbeitung.

Andere CPU -Designs enthalten einige zahlreiche Anweisungen für die Vektorverarbeitung bei mehreren (vektorisierten) Datensätzen, die normalerweise als bezeichnet werden Mimd (Multiple INstruktion, Multiple Data) und realisiert mit VLIW (VEry LOng INstruktion Word). Das Fujitsu FR-V Vliw/Vektorprozessor kombiniert beide Technologien.

Unterschied zwischen SIMD und Vektorprozessor

SIMD -Anweisungssätze fehlen im Vergleich zu Vektorprozessor -Anweisungssätzen wichtige Funktionen. Das Wichtigste davon ist, dass Vektorprozessoren seit Definition und Design seit ihrer Gründung immer variabler Länge waren.

Wo reine (feste Breite, keine Prädikation) Simd üblicherweise fälschlicherweise fälschlicherweise ist behauptet "Vektoren" sein (weil SIMD Daten verarbeitet, welche das passiert Um Vektoren zu sein) kann beobachtet, dass tatsächliche Vektorprozessoren durch enge Analyse und Vergleich historischer und moderner ISAs die folgenden Merkmale haben, die kein Simd ISA hat:

  • eine Möglichkeit, die Vektorlänge festzulegen (wie die setvl Anweisung in RISCV RVV[5]) oder eine Bereitstellung eines REP (Befehl wiederholen) Feature in irgendeiner Form, ohne Wiederholungen auf a zu begrenzen Kraft von zwei
  • Iteration und Reduzierung der Elemente innerhalb Vektoren. RISC-V-Vektoren ab Version 0.10 haben nur eine Reduzierung, während die SX-Ourora- und spätere Cray-Systeme sowohl Iteration als auch Reduzierung aufweisen.[6][7][8]

Vorherigte SIMD (Teil von Flynns Taxonomie) Das ist umfassende Prädikatmasken auf individueller Elementebene auf jeder Vektoranweisung, wie es jetzt in Arm SVE2 erhältlich ist.[9] und AVX-512qualifiziert sich fast als Vektorprozessor. Das vorherige SIMD verwendet Simd Alus mit fester Breite, ermöglicht jedoch eine lokal kontrollierte (vorherige) Aktivierung von Einheiten, um das Erscheinungsbild variabler Längenvektoren zu ermöglichen. Beispiele unten helfen bei der Erklärung dieser kategorialen Unterscheidungen.

SIMD ist aufgrund der festen Breite die Stapelverarbeitung, ist durch Design nicht in der Lage mit Iteration und Reduktion umgehen. Dies wird weiter unten mit Beispielen dargestellt.

Simd vs vector.png

Darüber hinaus können Vektorprozessoren ressourceneffizienter sein (verwenden Sie langsamere Hardware, Speichern von Strom, erhalten aber dennoch den Durchsatz)[10] und haben weniger Latenz als Simd durch Vektorkettung.[11]

Betrachten Sie sowohl einen SIMD-Prozessor als auch einen Vektorprozessor, der an 4 64-Bit-Elementen arbeitet und eine Last durchführen, addieren, multiplizieren und sequenz speichern. Wenn die SIMD -Breite 4 beträgt, muss der SIMD -Prozessor vier Elemente vollständig laden, bevor er mit den Adds übergehen kann, alle Adds vervollständigen, bevor sie mit den Multiplys übergehen kann, und muss ebenfalls alle Multiplys vervollständigen, bevor sie kann Starten Sie die Geschäfte. Dies ist per Definition und nach Design.[12]

Die 4-weite gleichzeitige 64-Bit-Ladung und 64-Bit-Läden und 64-Bit-Geschäfte ist in der Hardware sehr kostspielig (256 Bit-Datenpfade zum Speicher). Mit 4x 64-Bit-Alus, insbesondere multiplizieren, ebenso multiplizieren. Um diese hohen Kosten zu vermeiden, müsste ein SIMD-Prozessor eine 1-weite 64-Bit-Last, 1 breites 64-Bit-Geschäft und nur 2-weiten 64-Bit-Alus haben. Wie im Diagramm gezeigt, das a annimmt a Multi-Issue-AusführungsmodellDie Konsequenzen sind, dass die Operationen jetzt länger dauern, bis sie abgeschlossen sind. Wenn mehrfach ein Multi-Issue möglich ist, dauern die Operationen noch länger, da der LD möglicherweise nicht gleichzeitig mit dem ersten hinzugefügt wird (so weiter. Wenn es nur 4-Breite 64-Bit-SIMD-Alus gibt, ist die Abschlusszeit noch schlechter: Nur wenn alle vier Die SIMD -Operationen werden abgeschlossen, und nur dann, wenn alle ALU -Vorgänge abgeschlossen sind, können die Geschäfte beginnen.

Ein Vektorprozessor dagegen, Auch wenn es sich und verwendet keinen Simd Alus mit nur 1 breitem 64-Bit-Ladung, 1 breit 64-Bit-Geschäft (und wie in der Cray-1Die Möglichkeit, multiplizieren gleichzeitig mit Add auszuführen) kann die vier Vorgänge schneller abschließen als ein SIMD-Prozessor mit 1-weiten Last, 1-breitem Speicher und 2-weiten SIMD. Diese effizientere Ressourcennutzung aufgrund von Vektorkettung, ist ein zentraler Vorteil und Unterschied im Vergleich zu SIMD. Simd durch Design und Definition Nicht für die gesamte Gruppe von Ergebnissen durchführen.[13]

Beschreibung

Im Allgemeinen können CPUs jeweils ein oder zwei Datenstücke manipulieren. Zum Beispiel haben die meisten CPUs eine Anweisung, in der im Wesentlichen "A zu B hinzufügen und das Ergebnis in C hinzufügen". Die Daten für A, B und C könnten - zumindest in der Theorie - direkt in den Anweisungen eingezogen werden. In effizienten Implementierung sind die Dinge jedoch selten so einfach. Die Daten werden selten in roher Form gesendet und werden stattdessen auf "zeigen", indem eine Adresse an einen Speicherort übergeben wird, der die Daten enthält. Die Dekodierung dieser Adresse und das Auslernen der Daten aus dem Speicher dauert einige Zeit, in der die CPU traditionell im Leerlauf sitzen würde und darauf warten würde, dass die angeforderten Daten angezeigt werden. Mit zunehmender CPU -Geschwindigkeit Speicherlatenz ist historisch gesehen zu einem großen Hindernis für die Leistung geworden; sehen Speicherwand.

Um die Menge an Zeit zu verringern, die diese Schritte verbraucht haben, verwenden die meisten modernen CPUs eine Technik, die als bekannt ist Unterrichtspipelining in dem die Anweisungen nacheinander durch mehrere Untereinheiten gehen. Die erste Untereinheit liest die Adresse und dekodiert sie, die nächste "holt" die Werte an diesen Adressen, und das nächste macht die Mathematik selbst. Mit der Pipelination des "Tricks" ist es, die nächste Anweisung zu entschlüsseln, noch bevor die erste die CPU auf die Weise von einem verlassen hat Fließband, so die Adressdecoder wird ständig verwendet. Jede bestimmte Anweisung braucht die gleiche Zeit, um zu vervollständigen, eine Zeit, die als die bekannt ist LatenzAber die CPU kann eine ganze Reihe von Operationen auf überlappende Weise viel schneller und effizienter verarbeiten als ein einzelner Zeitpunkt.

Vektorprozessoren gehen dieses Konzept noch einen Schritt weiter. Anstatt nur die Anweisungen zu pipelieren, pipeline sie auch die Daten selbst. Der Prozessor erhält Anweisungen mit der Feed, mit denen nicht nur A zu B hinzugefügt wird, sondern alle Zahlen "von hier zu hier zu" zu allen Zahlen "von dort nach dort" hinzuzufügen. Anstatt ständig Anweisungen zu dekodieren und dann die Daten abzurufen selbst dass die Anweisung erneut in einem anderen Datenelement funktioniert, an einer Adresse, die ein Inkrement größer als der letzte ist. Dies ermöglicht erhebliche Einsparungen in der Dekodierungszeit.

Um zu veranschaulichen, was für einen Unterschied dies ausmachen kann, berücksichtigen Sie die einfache Aufgabe, zwei Gruppen von 10 Zahlen zusammenzusetzen. In einer normalen Programmiersprache schrieb man eine "Schleife", die jedes der Zahlenpaare nacheinander aufnahm, und fügte sie dann hinzu. Für die CPU würde dies ungefähr so ​​aussehen:

; Hypothetische RISC -Maschine ; Fügen Sie 10 Zahlen in a bis 10 Zahlen in B hinzu und speichern Sie die Ergebnisse in C. ; Angenommen, A, B und C sind Speicherorte in ihren jeweiligen Registern  Bewegung  $ 10, zählen  ; Graf: = 10 Schleife:  Belastung  R1, a  Belastung  R2, b  hinzufügen  R3, R1, R2  ; R3: = R1 + R2  Laden R3, c  hinzufügen  a, a, $ 4  ; mach weiter  hinzufügen  b, b, $ 4  hinzufügen  c, c, $ 4  dez  zählen  ; Abnahme  Jnez  zählen, Schleife  ; Schleife zurück, wenn die Anzahl noch nicht 0 ist  ret 

Aber für einen Vektorprozessor sieht diese Aufgabe erheblich unterschiedlich aus:

; Angenommen, wir haben Vektorregister V1-V3  ; mit Größe gleich oder größer als 10  Bewegung  $ 10, zählen  ; count = 10  VLAD  v1, a, zählen  VLAD  v2, b, zählen  vadd  v3, v1, v2  vstore v3, c, zählen  ret 

Beachten Sie den vollständigen Mangel an Schleifen in den Anweisungen, da es das ist Hardware- Das hat 10 sequentielle Operationen durchgeführt: Effektiv ist die Schleifenzahl explizit Perinstruktion Basis.

Cray-Stil-Vektor-ISAs gehen noch einen Schritt weiter und bieten ein globales "Zähl" -Register, das als Vektorlänge (VL) bezeichnet wird:

; Nehmen Sie erneut an, wir haben Vektorregister V1-V3 ; mit Größe größer als oder gleich 10  setvli  $ 10  # Vektorlänge vl = 10 einstellen  VLAD  v1, a  # 10 Ladungen von a  VLAD  v2, b  # 10 Ladungen von B  vadd  v3, v1, v2  # 10 fügt hinzu  vstore v3, c  # 10 Geschäfte in c  ret 

Dieser Ansatz gibt mehrere Einsparungen.[14]

  1. Es sind nur drei Adressübersetzungen erforderlich. Abhängig von der Architektur kann dies eine erhebliche Einsparung für sich selbst darstellen.
  2. Eine weitere Ersparnis ist das Abrufen und Dekodieren der Anweisung selbst, die nur einmal anstelle von zehn erfolgen muss.
  3. Der Code selbst ist ebenfalls kleiner, was zu einer effizienteren Speicherverwendung, einer Verringerung der L1 -Befehls -Cache -Größe und der Verringerung des Stromverbrauchs führen kann.
  4. Da die Programmgröße reduziert wird, hat die Vorhersage der Filiale eine einfachere Aufgabe.
  5. Mit der Länge (äquivalent zur SIMD-Breite), die nicht in der Anweisung fest codiert ist, ist es nicht nur die Codierung kompakter, sondern auch "zukunftssicher" und erlaubt sogar sogar eingebetteter Prozessor Entwürfe, die über die Verwendung von Vektoren in Betracht gezogen werden sollen, um alle anderen Vorteile zu erzielen, anstatt eine hohe Leistung zu erzielen.

Darüber hinaus wurde in modernerem Vektorprozessor ISAs "Fail on First" oder "Fault First" eingeführt (siehe unten), was noch mehr Vorteile bringt.

Aber mehr als das kann ein Hochleistungsvektorprozessor mehrere haben Funktionseinheiten Hinzufügen dieser Zahlen parallel. Die Überprüfung von Abhängigkeiten zwischen diesen Zahlen ist nicht erforderlich, da eine Vektoranweisung mehrere unabhängige Operationen festgelegt ist. Dies vereinfacht die erforderliche Kontrolllogik und kann die Leistung weiter verbessern, indem Stände vermieden werden. Die mathematischen Operationen wurden somit insgesamt weitaus schneller abgeschlossen, wobei der begrenzende Faktor die Zeit ist, die zum Abholen der Daten aus dem Speicher erforderlich ist.

Nicht alle Probleme können mit dieser Art von Lösung angegriffen werden. Das Einschließen dieser Arten von Anweisungen erhöht die Kern -CPU notwendigerweise Komplexität. Diese Komplexität macht normalerweise Sonstiges Anweisungen laufen langsamer - d. H., wann immer es ist nicht addieren Sie viele Zahlen in einer Reihe. Die komplexeren Anweisungen tragen auch zur Komplexität der Decoder bei, was die Decodierung der häufigeren Anweisungen wie normales Hinzufügen verlangsamen könnte. (Dies kann etwas gemindert werden, indem die gesamte ISA aufbewahrt wird RISC Prinzipien: RVV fügt nur mit den erweiterten Funktionen rund 190 Vektoranweisungen hinzu.[15]))

Vektorprozessoren wurden traditionell nur dann so konzipiert, dass es am besten funktioniert, wenn viele Daten bearbeitet werden müssen. Aus diesem Grund wurden diese Arten von CPUs hauptsächlich in gefunden Supercomputerwie die Supercomputer selbst im Allgemeinen an Orten wie Wettervorhersagezentren und Physiklabors gefunden wurden, in denen große Mengen an Daten "knirscht" werden. Wie oben gezeigt und durch RISC-V RVV gezeigt Effizienz von Vector Isas bringt andere Vorteile mit sich, die auch für eingebettete Anwendungsfälle überzeugend sind.

Vektoranweisungen

Das obige Vektor -Pseudocode -Beispiel wird mit einer großen Annahme ausgestattet, dass der Vektorcomputer mehr als zehn Zahlen in einer Stapel verarbeiten kann. Für eine größere Menge an Zahlen im Vektorregister ist es nicht maßbar, dass der Computer ein so großes Register hat. Infolgedessen erlangt der Vektorprozessor entweder die Fähigkeit, Schleifen selbst durchzuführen, oder zeigt dem Programmierer, der normalerweise als Vektorlänge bezeichnet wird, ein Register für Vektorsteuerung (Status).

Die selbstverzögerten Anweisungen finden Sie in frühen Vektor-Computern wie dem Star-100, wo die obige Aktion in einer einzigen Anweisung beschrieben wird (etwas wie vadd c, a, b, $10). Sie sind auch in der gefunden x86 Architektur wie die REP Präfix. Auf diese Weise können jedoch nur sehr einfache Berechnungen effektiv in Hardware durchgeführt werden. Da alle Operanden für die Star-100-Architektur in Erinnerung bleiben müssen, wurde auch die durch den Zugang verursachte Latenz enorm.

Interessanterweise umfasste Broadcom Platz in allen Vektoroperationen der Vektor Videokore Iv isa für a REP Feld, aber im Gegensatz zum Star-100, der Speicher für seine Wiederholungen verwendet, sind die Wiederholungen von Videocore IV bei allen Vorgängen einschließlich arithmetischer Vektoroperationen. Die Wiederholungslänge kann ein kleiner Bereich von sein Kraft von zwei oder aus einem der skalaren Register bezogen.[16]

Das Cray-1 stellte die Idee der Verwendung vor Prozessorregister Vektordaten in Chargen halten. Die Chargenlängen (Vektorlänge, VL) könnten dynamisch mit einer speziellen Anweisung festgelegt werden, die Bedeutung im Vergleich zu Videokore IV (und entscheidend, wie unten gezeigt wird, ist auch Simd), dass die Wiederholungslänge nicht Teil von sein muss Die Anweisungscodierung. Auf diese Weise kann in jeder Charge deutlich mehr Arbeit geleistet werden. Die Anweisungscodierung ist auch viel eleganter und kompakter. Der einzige Nachteil ist, dass die Speicherbelastung und die speichernde Geschwindigkeit entsprechend erhöht werden mussten, um diese zusätzliche Stapelverarbeitungskapazität voll auszunutzen. Dies wird manchmal behauptet[von wem?] ein Nachteil von Vektorprozessoren im Cray-Stil zu sein: In Wirklichkeit ist es Teil des Erreichens des hohen Leistungsdurchsatzes, wie es in gesehen wird GPUS, was genau dem gleichen Problem ausgesetzt ist.

Moderne SIMD -Computer behaupten, den frühen Cray durch direkte Verwendung mehrerer Alus zu verbessern, um einen höheren Grad an Parallelität im Vergleich zur normalen Skalarpipeline zu erhalten. Moderne Vektorprozessoren (wie die SX-Ourora Tsubasa) Kombinieren Sie beide, indem Sie mehrere Daten an mehrere interne Pipelined SIMD Alus ausgeben, wobei die vom Vektorprogramm zur Laufzeit dynamische Ausgabe dynamisch ausgewählt wurde. Masken können verwendet werden, um Daten in Speicherorten selektiv zu laden und zu speichern und dieselben Masken zu verwenden, um das Verarbeitungselement von SIMD Alus selektiv zu deaktivieren. Einige Prozessoren mit SIMD (AVX-512, ARM SVE2) sind in der Lage zu dieser Art von selektivem, pro Eleement ("basiert") Verarbeitung, und es sind diese, die den "Vektorprozessor" der Nomenklatur etwas verdienen oder zumindest den Anspruch verdienen, "Vektorverarbeitung" zu sein. SIMD-Prozessoren ohne proelemente Prädikation (MMX, Sse, Altivec) kategorisch nicht.

Moderner GPU Einzelne Anweisungen Mehrere Threads (Simt). SIMT -Einheiten werden von einer gemeinsam genutzten synchronisierten Einzelsendungsanweisungseinheit ausgeführt. Die "Vektorregister" sind sehr breit und die Pipelines sind in der Regel lang. Der "Threading" -Teil von SIMT beinhaltet die Art und Weise, wie Daten unabhängig von den Recheneinheiten behandelt werden.

Darüber hinaus GPUs wie das Broadcom Videokore IV und andere externe Vektorprozessoren wie die NEC SX-Ourora Tsubasa Kann weniger Vektoreinheiten verwenden, als die Breite impliziert: Anstatt 64 Einheiten für ein 64-nummer-Register zu haben, kann die Hardware stattdessen eine Pipeled-Schleife über 16 Einheiten für einen hybriden Ansatz durchführen. Das Broadcom Videokore IV ist auch zu diesem hybriden Ansatz in der Lage: Nominal erklärt, dass der SIMD-QPU-Engine 16-langen FP-Array-Vorgänge in seinen Anweisungen unterstützt, und sie erledigt sie tatsächlich 4 gleichzeitig, als (eine andere) Form von "Threads".[17]

Beispiel für Vektoranweisungen

Dieses Beispiel beginnt mit einem Algorithmus ("ixpy"), zeigt es zuerst in skalarischen Anweisungen, dann SIMD, dann voraussichtlich SIMD und schließlich Vektoranweisungen. Dies veranschaulicht inkrementell den Unterschied zwischen einem herkömmlichen Vektorprozessor und einem modernen Simd. Das Beispiel beginnt mit einer 32-Bit-Ganzzahlvariante der "Daxpy" -Funktion in C:

Leere iaxpy(size_t n, int a, Const int x[],, int y[]) {   zum (size_t i = 0; i < n; i++)   y[i] = a * x[i] + y[i]; } 

In jeder Iteration hat jedes Element von y ein Element von x multipliziert mit A und hinzugefügt. Das Programm wird in skalarer linearer Form zur Lesbarkeit ausgedrückt.

Scalar Assembler

Die Skalarversion davon würde eine von jedem von x und y laden, eine Berechnung verarbeiten, ein Ergebnis speichern und Schleifen haben:

Schleife:  last32  R1, x  ; Laden Sie eine 32 -Bit -Daten  last32  R2, y  mul32  R1, a, R1  ; R1: = R1 * a  Add32  R3, R1, R2 ; R3: = R1 + R2  store32 R3, y  Addl  x, x, $ 4  ; x: = x + 4  Addl  y, y, $ 4  Subl  n, n, $ 1  ; n: = n - 1  Jgz  n, Schleife  ; zurückbleiben Sie zurück, wenn n> 0 aus:  ret 

Der sternähnliche Code bleibt präzise, ​​aber da die Vektorisierung des Stern-100 auf dem Entwurf auf dem Speicherzugriff basierte, ist jetzt ein zusätzlicher Speicherschlitz erforderlich, um die Informationen zu verarbeiten. Das zweifache Latenz wird auch aufgrund der zusätzlichen Anforderung des Speicherzugriffs benötigt.

  ; Angenommen  vmul TMP, a, x, n ; tmp [i] = a * x [i]  vadd y, y, TMP, n ; y [i] = y [i] + tmp [i]  ret 

Reine (nicht geputzte, gepackte) SIMD

Eine moderne SIMD -Architektur, bekannt unter vielen Namen (aufgeführt in Flynns Taxonomie), kann den größten Teil des Betriebs in Chargen ausführen. Der Code ähnelt größtenteils der Skalarversion. Es wird angenommen, dass sowohl x als auch y sind richtig ausgerichtet Hier (starten Sie nur ein Vielfaches von 16) und das n ist ein Vielfaches von 4, da sonst ein Setup -Code erforderlich wäre, um eine Maske zu berechnen oder eine Skalarversion auszuführen. Der Einfachheit halber kann auch angenommen werden, dass die SIMD -Anweisungen die Option haben, Skalaroperanden automatisch zu wiederholen, wie bei wie Arm Neon Can.[18] Wenn dies nicht der Fall ist, muss ein "Splat" (Sendung) verwendet werden, um das skalare Argument in einem SIMD -Register zu kopieren:

  splatx4  v4, a  ; v4 = a, a, a, a 

Die benötigte Zeit wäre im Grunde genommen die gleiche wie eine Vektorumsetzung von y = mx + c oben beschrieben.

Vloop:  last32x4  v1, x  last32x4  v2, y  mul32x4  v1, a, v1  ; v1: = v1 * a  add32x4  v3, v1, v2 ; v3: = v1 + v2  store32x4 v3, y  Addl  x, x, $ 16  ; x: = x + 16  Addl  y, y, $ 16  Subl  n, n, $ 4  ; n: = n - 4  Jgz  n, Vloop  ; Geh zurück, wenn n> 0 aus:  ret 

Beachten Sie, dass sowohl X- als auch Y-Zeiger um 16 erhöht sind, da so lange (in Bytes) vier 32-Bit-Ganzzahlen sind. Die Entscheidung wurde getroffen, dass der Algorithmus soll Nur mit einer 4-weiten SIMD fertig werden, daher ist die Konstante in das Programm fest codiert.

Unglücklicherweise für SIMD war der Hinweis in der obigen Annahme, dass N ein Vielfaches von 4 "sowie" ausgerichteter Zugriff "ist, was eindeutig ein begrenzter spezialisierter Anwendungsfall ist.

Realistisch gesehen kann für allgemeine Schleifen wie in tragbaren Bibliotheken, in denen N auf diese Weise nicht begrenzt werden kann die Schleife selbst. Unter der Annahme, dass die Hardware für den Worst-Case nicht falsch ausgerichtet ist, wird ein realer Algorithmus mit SIMD-Speicher nicht falsch ausgerichtet.

  • Müssen zuerst einen vorbereitenden Abschnitt haben, der an den anfänglichen nicht ausgerichteten Daten funktioniert, bis zum ersten Punkt, an dem SIMD-Speicher-ausgerichtete Operationen übernehmen können. Dies beinhaltet entweder (langsamere) skalare Operationen oder kleinere gepackte SIMD-Operationen. Jede Kopie implementiert den vollständigen Algorithmus Innenschleife.
  • Führen Sie die ausgerichtete SIMD -Schleife mit maximaler SIMD -Breite bis zu den letzten Elementen durch (die verbleibenden, die nicht zur festen SIMD -Breite passen)
  • Haben Sie eine Reinigungsphase, die wie der vorbereitende Abschnitt genauso groß und genauso komplex ist.

Acht-breites SIMD erfordert das Wiederholen des inneren Loop-Algorithmus zuerst mit vier breiten SIMD-Elementen, dann zwei breit Elemente (0 <= n <= 7).

Das mehr als Dreifach Die Größe des Code, in der Tat in extremen Fällen, führt er zu einem Größenordnung Erhöhung der Anweisungszahl! Dies kann leicht nach dem Kompilieren des IAXPY -Beispiels für gezeigt werden AVX-512mit den Optionen "-O3 -march=knl" zu GCC.

Im Laufe der Zeit, mit der sich die ISA entwickelt, um die Leistung zu steigern, führt dies dazu, dass ISA-Architekten 2-weite SIMD, dann 4-weite SIMD, dann 8-Breite und nach oben hinzufügen. Es kann daher gesehen werden, warum AVX-512 existiert in x86.

Ohne Prädikation, desto breiter ist die SIMD -Breite, desto schlechter werden die Probleme, was zu einer massiven Opcode -Proliferation, einer verschlechterten Leistung, zusätzlichem Stromverbrauch und unnötiger Softwarekomplexität führt.[19]

Vektorprozessoren dagegen dienen dazu, Berechnungen der variablen Länge für eine willkürliche Zählung N auszugeben, und somit nur sehr wenig Setup und keine Reinigung erfordern. Auch im Vergleich zu diesen Simd -ISAs, die Masken haben (aber nein setvl Anweisung), Vektorprozessoren erzeugen viel kompakterer Code, da sie keine explizite Maskenberechnung durchführen müssen, um die letzten paar Elemente (unten dargestellt) abzudecken.

Vorhergesagt SIMD

Unter der Annahme einer hypothetischen vorherigen (Maske fähig) SIMD -ISA und erneut angenommen, dass die SIMD -Anweisungen mit falsch ausgerichteten Daten fertig werden können, würde die Anweisungsschleife so aussehen:

Vloop:  # Maske vorbereiten. Nur wenige ISAs haben min  Mindest  t0, n, $ 4  ; t0 = min (n, 4)  Wechsel  m, $ 1, t0  ; M = 1 << T0  Sub  m, m, $ 1  ; m = (1 << t0) -1  # Treiben Sie nun den Betrieb, maskiert von M -Bits  last32x4  v1, x, m  last32x4  v2, y, m  mul32x4  v1, a, v1, m  ; v1: = v1 * a  add32x4  v3, v1, v2, m ; v3: = v1 + v2  store32x4 v3, y, m  # Update X, Y und N für die nächste Schleife  Addl  x, t0*4  ; x: = x + t0*4  Addl  y, t0*4  Subl  n, n, t0  ; n: = n - t0  # Schleife?  Jgz  n, Vloop  ; Geh zurück, wenn n> 0 aus:  ret 

Hier ist zu erkennen, dass der Code viel sauberer, aber etwas komplex ist: Zumindest gibt es jedoch kein Setup oder Aufräumarbeiten: Bei der letzten Iteration der Schleife wird die Prädikatmaske auf entweder 0B0000, 0B0001, 0B0011 eingestellt, auf entweder 0B0000, 0B0001, 0B0011,. 0B0111 oder 0B1111, was zu den Operationen zwischen 0 und 4 SIMD -Elementen führt. Eine zusätzliche potenzielle Komplikation: Einige RISC -ISAs haben keine "min" -Bericht, die stattdessen einen Zweig oder einen skalar vorherrschenden Vergleich verwenden müssen.

Es ist klar, wie vorherrschend SIMD den Begriff "Vektor fähig" zumindest verdient, da er mit Vektoren mit variabler Länge durch Verwendung von Prädikatmasken fertig werden kann. Der endgültige sich entwickelnde Schritt zu einem "echten" Vektor -ISA besteht jedoch darin, keine Beweise in der ISA zu haben überhaupt einer SIMD -Breite, die das ganz der Hardware belassen.

Reine (wahre) Vektor ISA

Für ISAs im Cray-Stil wie RVV wird eine Anweisung namens "SETVL" (festgelegte Vektorlänge) verwendet. Die Hardware definiert zunächst, wie viele Datenwerte sie in einem "Vektor" verarbeiten kann: Dies kann entweder tatsächliche Register oder eine interne Schleife sein (der oben erwähnte Hybridansatz). Dieser maximale Betrag (die Anzahl der Hardware "Spuren") wird als "MVL" bezeichnet (maximale Vektorlänge). Beachten Sie, dass MVL, wie in SX-Aurora und Videokore IV zu sehen ist oder eine virtuelle. (Hinweis: Wie im Arm Sve2 Tutorial erwähnt, Programmierer muss Machen Sie nicht den Fehler, eine feste Vektorbreite anzunehmen: Folglich ist MVL keine Menge, die der Programmierer kennen muss. Dies kann nach Jahren der SIMD -Denkweise ein wenig beunruhigend sein.[Ton]

Wenn Sie SETVL mit der Anzahl der zu verarbeitenden ausstehenden Datenelemente aufrufen tatsächlich Nummer, die von der Hardware in nachfolgenden Vektoranweisungen verarbeitet werden kann und das interne spezielle Register "VL" auf denselben Betrag festgelegt wird. ARM bezeichnet diese Technik als "Vektorlänge Agnostische" -Programmierung in seinen Tutorials auf SVE2.[20]

Unten finden Sie den Vektor-Assembler im Cray-Stil für die gleiche SIMD-Style-Schleife oben. Beachten Sie, dass T0 (der eine bequeme Kopie von VL enthält, die variieren kann) anstelle von hartcodierten Konstanten verwendet wird:

Vloop:  setvl  t0, n  # Vl = t0 = min (mvl, n)  vld32  v0, x  # Vektor laden x  vld32  v1, y  # Vektor laden y  VMADD32 v1, v0, a  # v1 += v0 * a  VST32  v1, y  # Store y  hinzufügen  y, t0*4  # Advance y von Vl*4  hinzufügen  x, t0*4  # Advance x by Vl*4  Sub  n, t0  # n -= vl (t0)  Bnez  n, Vloop  # wiederholen Sie, ob n! = 0 

Dies unterscheidet sich im Wesentlichen nicht sehr von der SIMD -Version (Prozesse 4 Datenelemente pro Schleife) oder von der anfänglichen Skalarversion (Prozesse nur die eine). n enthält immer noch die Anzahl der verbleibenden Datenelemente, die verarbeitet werden sollen, aber T0 enthält die Kopie von VL - die Nummer, die ist gehen in jeder Iteration verarbeitet werden. T0 wird nach jeder Iteration von N abtrahiert, und wenn n Null ist, wurden alle Elemente verarbeitet.

Eine Reihe von Dingen zu beachten, wenn Sie mit der vorherigen SIMD -Assembly -Variante verglichen werden:

  1. Das setvl Anweisung hat in ihn eingebettet a min Anweisung
  2. Wobei die SIMD-Variante sowohl die Breite (4) in die Schaffung der Maske fest codierte und In der SIMD -Breite (Load32x4 usw.) haben die Vektor -ISA -Äquivalente keine solche Grenze. Dies macht Vektorprogramme sowohl tragbar, Lieferanten unabhängig als auch zukunftssicher.
  3. VL effektiv einstellen erstellt eine versteckte Prädikatmaske Das wird automatisch auf die Vektoren angewendet
  4. Wenn die Maskenbitlänge mit einem vorherigen Simd auf das beschränkt ist, was in einem Skalar- (oder speziellen Masken-) Register gehalten werden kann, haben die Maskenregister von Vector ISA keine solche Einschränkung. Cray-i-Vektoren könnten etwas mehr als 1.000 Elemente (1977) betragen.

Daher ist sehr deutlich zu sehen, wie Vektor -ISAs die Anzahl der Anweisungen verringern.

Beachten Sie auch, dass die Zeiger auf x und y genau wie die vorherige SIMD -Variante um T0 -mal vier erweitert werden, da beide auf 32 -Bit -Daten verweisen, aber dass n durch geradlinige T0 verringert wird. Im Vergleich zum SIMD-Assembler mit fester Größe gibt es nur sehr wenig offensichtliche Unterschied: x und y werden durch hartcodierte Konstante 16 vorgezogen. N wird durch eine hart codierte 4 abgeschlossen. Anfangs ist es zunächst schwierig, die Bedeutung zu schätzen. Der Unterschied kommt in der Erkenntnis, dass die Vektor -Hardware möglicherweise 4 gleichzeitige Operationen ausführen kann, oder 64 oder 10.000, es wäre genau der gleiche Vektor -Assembler für alle von ihnen Und es würde immer noch keinen SIMD -Reinigungscode geben. Selbst im Vergleich zum Prädikat-fähigen SIMD ist es noch kompakter, klarer, eleganter und verwendet weniger Ressourcen.

Es ist nicht nur ein viel kompakteres Programm (Speichern von L1 -Cache -Größe), sondern wie bereits erwähnt, kann die Vektorversion den Alus weitaus mehr Datenverarbeitung ausstellen, wodurch der Strom gespeichert wird, da das Dekodieren und die Ausgabe von Anweisungen im Leerlauf sitzen können.

Darüber hinaus kann die Anzahl der Elemente, die in die Funktion gehen, bei Null beginnen. Dadurch wird die Vektorlänge auf Null gesetzt, was alle Vektoranweisungen effektiv deaktiviert und sie in die Umgebung verwandelt No-Ops, zur Laufzeit. Im Gegensatz zu nicht geprägter SIMD gibt es daher, selbst wenn es keine Elemente gibt, die zu verarbeiten sind, immer noch keinen verschwendeten Reinigungscode.

Beispiel für Vektorreduktion

Dieses Beispiel beginnt mit einem Algorithmus, der eine Reduktion beinhaltet. Genau wie beim vorherigen Beispiel wird es zuerst in Skalaranweisungen, dann in Simd und schließlich Vektoranweisungen angezeigt, beginnend in c:

Leere (size_t n, int a, Const int x[]) {   int y = 0;   zum (size_t i = 0; i < n; i++)   y += x[i];   Rückkehr y; } 

Hier wird ein Akkumulator (y) verwendet, um alle Werte im Array x zusammenzufassen.

Scalar Assembler

Die Skalarversion davon würde jedes von x laden, es zu Y hinzufügen und Schleife:

  einstellen  y, 0  ; y in Null initialisiert Schleife:  last32  R1, x  ; Laden Sie eine 32 -Bit -Daten  Add32  y, y, R1 ; y: = y + r1  Addl  x, x, $ 4 ; x: = x + 4  Subl  n, n, $ 1 ; n: = n - 1  Jgz  n, Schleife  ; zurückbleiben Sie zurück, wenn n> 0 aus:  ret y  ; Rückgabeergebnis, y 

Dies ist sehr einfach. "y" beginnt bei Null, 32 -Bit -Gauner werden nacheinander in R1 geladen, zu Y hinzugefügt, und die Adresse des Arrays "X" wurde zum nächsten Element im Array fortgesetzt.

SIMD -Reduktion

Hier beginnen die Probleme. SIMD by Design ist nicht in der Lage, arithmetische Operationen "interelement" durchzuführen. Element 0 eines SIMD -Registers kann zu Element 0 eines anderen Registers hinzugefügt werden, aber Element 0 Mai Mai nicht zu allem hinzugefügt werden Sonstiges als ein anderes Element 0. Dies stellt einige schwerwiegende Einschränkungen für potenzielle Implementierungen ein. Der Einfachheit halber kann angenommen werden, dass N genau 8 ist:

  Addl  R3, x, $ 16 ; für 2. 4 von x  last32x4  v1, x  ; Erste 4 von x  last32x4  v2, R3  ; 2. 4 von x  add32x4  v1, v2, v1 ; 2 Gruppen hinzufügen 

Zu diesem Zeitpunkt wurden vier hinzugefügte hinzugefügt:

  • x[0]+x[4] - First Simd Add: Element 0 der ersten Gruppe zu Element 0 der zweiten Gruppe hinzugefügt
  • x[1]+x[5] - Zweite SIMD -Add: Element 1 der ersten Gruppe zu Element 1 der zweiten Gruppe hinzugefügt
  • x[2]+x[6] - Dritter Simd Add: Element 2 der ersten Gruppe zu Element 2 der zweiten Gruppe hinzugefügt
  • x[3]+x[7] - Viertes Simd Add: Element 3 der ersten Gruppe zu Element 2 der zweiten Gruppe hinzugefügt

Aber mit 4-weiten SIMD ist unfähig von Entwurf des Hinzufügens x[0]+x[1] Zum Beispiel gehen die Dinge schnell bergab, wie sie es mit dem allgemeinen Fall der Verwendung von SIMD für allgemeine IAXPY-Schleifen verwendet haben. Um die vier Teilergebnisse zusammenzufassen, kann zweiweite SIMD verwendet werden, gefolgt von einem einzelnen Skalar-Add, um schließlich die Antwort zu erzeugen, aber häufig müssen die Daten aus dedizierten SIMD-Registern übertragen werden, bevor die letzte Skalarberechnung durchgeführt werden kann .

Selbst mit einer allgemeinen Schleife (N nicht fest) besteht die einzige Möglichkeit, 4-weite SIMD zu verwenden, um vier separate "Streams" zu übernehmen, die jeweils um vier Elemente versetzt werden. Schließlich müssen die vier Teilergebnisse summiert werden. Andere Techniken beinhalten Shuffle: Beispiele online finden Sie für AVX-512 wie man "horizontale Summe" macht[21][22]

Abgesehen von der Größe des Programms und der Komplexität tritt ein zusätzliches potenzielles Problem auf, wenn die Berechnung der Schwimmpunkte beteiligt ist: Die Tatsache, dass die Werte nicht in strenger Reihenfolge (vier Teilergebnisse) zusammengefasst werden, kann zu Rundungsfehlern führen.

Vektor ISA -Reduktion

Vektoranweisungssätze haben eine arithmetische Reduzierung von Operationen eingebaut zum Isa. Wenn angenommen wird, dass N weniger oder gleich der maximalen Vektorlänge ist, sind nur drei Anweisungen erforderlich:

  setvl  t0, n  # Vl = t0 = min (mvl, n)  vld32  v0, x  # Vektor laden x  vredadd32  y, v0  # Reduzieren Sie in y 

Der Code, wenn n größer als die maximale Vektorlänge ist, ist nicht viel komplexer und ist ein ähnliches Muster wie das erste Beispiel ("IAXPY").

  einstellen  y, 0 Vloop:  setvl  t0, n  # Vl = t0 = min (mvl, n)  vld32  v0, x  # Vektor laden x  vredadd32 y, y, v0 # Fügen Sie alle x in y hinzu  hinzufügen  x, t0*4  # Advance x by Vl*4  Sub  n, t0  # n -= vl (t0)  Bnez  n, Vloop  # wiederholen Sie, ob n! = 0  ret y 

Die Einfachheit des Algorithmus ist im Vergleich zu SIMD stark. Genauso wie beim IAXPY-Beispiel ist der Algorithmus länge-agnostisch (selbst bei eingebetteten Implementierungen, bei denen die maximale Vektorlänge nur eins sein kann).

Implementierungen in Hardware können, wenn sie sicher sind, dass die richtige Antwort produziert wird, die Reduktion parallel durchführen. Einige Vektor -ISAs bieten einen parallelen Reduktionsmodus als explizite Option an, denn wenn der Programmierer weiß, dass potenzielle Rundungsfehler keine Rolle spielen und eine geringe Latenz von entscheidender Bedeutung ist.[23]

Dieses Beispiel zeigt erneut einen wichtigen kritischen grundlegenden Unterschied zwischen echten Vektorprozessoren und den SIMD -Prozessoren, einschließlich der meisten kommerziellen GPUs, die von Merkmalen von Vektorprozessoren inspiriert sind.

Einblicke aus Beispielen

Im Vergleich zu jedem SIMD -Prozessor, der behauptet, ein Vektorprozessor zu sein, ist die Größenreduzierung der Programmgröße nahezu schockierend. Diese Eleganzniveau auf ISA -Ebene hat jedoch einen ziemlich hohen Preis auf Hardwareebene:

  1. Aus dem Beispiel von IAXPY ist ersichtlich, dass ein Vektorprozessor im Gegensatz zu SIMD -Prozessoren, die ihre interne Hardware vereinfachen können, indem es den Umgang mit falsch ausgerichteten Speicherzugriff vermieden Erfolgreich, unabhängig von der Ausrichtung des Beginns des Vektors.
  2. Während aus dem Beispiel des Reduktionsbeispiels abgesehen davon ersichtlich ist Permute Anweisungen, SIMD vermeidet per Definition ein vollständiger Vorgänge (Element 0 kann nur zu einem anderen Element 0 hinzugefügt werden), Vektorprozessoren packen diese Frontal an. Was Programmierer in der Software (mit Shuffle und anderen Tricks) gezwungen sind, Daten in die rechte "Spur") Vektorprozessoren auszutauschen, müssen in Hardware automatisch ausführen.

Insgesamt gibt es die Wahl, beide zu haben

  1. Komplexe Software und vereinfachte Hardware (SIMD)
  2. vereinfachte Software und komplexe Hardware (Vektorprozessoren)

Diese starken Unterschiede unterscheiden einen Vektorprozessor von einem Simd.

Vektorprozessorfunktionen

Wenn viele SIMD -ISAs von der folgenden Liste ausleihen oder inspiriert sind, sind typische Funktionen, die ein Vektorprozessor hat, sind:[24][25][26]

  • Vektorlast und speichern -Vektorarchitekturen mit einem Register-Register-Design (analog zu Last-Store-Architekturen für Skalarprozessoren) haben Anweisungen zum Übertragen mehrerer Elemente zwischen dem Speicher und den Vektorregistern. In der Regel werden mehrere Adressierungsmodi unterstützt. Der Adressmodus der Einheitsstreicher ist unerlässlich. Moderne Vektorarchitekturen unterstützen typischerweise auch willkürliche konstante Fortschritte sowie die Streuung/Versammlung (auch genannt indiziert) Adressierungsmodus. Fortgeschrittene Architekturen können auch die Unterstützung für die Unterstützung für Segment Laden und Geschäfte und Fail-First Varianten der Standard -Vektorlast und -speicher. Segmentladungen Lesen Sie einen Vektor aus dem Speicher, wobei jedes Element a ist Datenstruktur mit mehreren Mitgliedern. Die Mitglieder werden aus der Datenstruktur (Element) extrahiert und jedes extrahierte Mitglied wird in ein anderes Vektorregister eingesetzt.
  • Maskierte OperationenPrädikatmasken Parallele if/then/else konstruiert, ohne auf Zweige zurückzugreifen. Auf diese Weise können Code mit bedingten Anweisungen vektorisiert werden.
  • Komprimieren und erweitern -Normalerweise werden die Daten linear komprimiert oder erweitert (umverteilt) basierend darauf, ob die Bits in der Maske eingestellt oder klar sind, während immer die aufeinanderfolgende Reihenfolge beibehalten und Werte niemals duplizieren (im Gegensatz zu Sammelstreuungs-AKA-Permut). Diese Anweisungen enthalten in AVX-512.
  • Registrieren Sie sich versammeln, streuen (auch bekannt als Permute)[27] - Eine weniger restriktivere generische Variation des Komprimierungs-/Erweiterungsthemas, das stattdessen einen Vektor benötigt, um die Indizes anzugeben, um einen anderen Vektor zu "neu zu ordnen". Sammeln/Streuung ist komplexer für die Implementierung als komprimieren/auszudehnen und kann, da von Natur aus nicht sequentiell, beeinträchtigt werden kann Vektorkettung. Nicht zu verwechseln mit Sammelstreuung Speicherlast-/Speichermodi, sammeln/Streuvektoroperationen auf die Vektorregister und werden häufig als a bezeichnet Permutanweisung stattdessen.
  • Splat und Extrakt - Nützlich für die Wechselwirkung zwischen Skalar und Vektor, übertragen diese einen einzelnen Wert über einen Vektor oder extrahieren einen Element aus einem Vektor.
  • Jota -Ein sehr einfacher und strategisch nützlicher Anweisungen, der nacheinander inkrementiert, um unmittelbar in aufeinanderfolgende Elemente zu inkrementieren. Normalerweise beginnt von Null.
  • Reduktion und Wiederholung - Operationen, die durchgeführt werden Karte verkleinern Auf einem Vektor (z. B. den einen maximalen Wert eines gesamten Vektors finden oder alle Elemente zusammenfassen). Iteration ist von der Form x [i] = y [i] + x [i-1] wo Reduktion der Form ist x = y [0] + y [1]… + y [n-1]
  • Matrix multiplizieren Unterstützung -Entweder durch algorithmisch ladenes Daten aus dem Speicher oder durch Neubestrafung (Neuzuordnung) des normalerweise linearen Zugriffs auf Vektorelemente oder die Bereitstellung von "Akkumulatoren", können matrizen in beliebiger Größe effizient verarbeitet werden. IBM Power10 bietet MMA -Anweisungen[28] Obwohl für willkürliche Matrixbreiten, die nicht zu den genauen Datenwiederholungstechniken der SIMD -Größe passen, sind erforderlich, was die Verschwendung von Registerdateiressourcen entspricht.[29][30] Nvidia bietet eine hochrangige Matrix CUDA API Obwohl die internen Details nicht verfügbar sind.[31] Die ressourceneffizienteste Technik ist die Umordnung des Zugriffs auf ansonsten lineare Vektordaten.
  • Erweiterte Mathematikformate - oft beinhaltet Galois Feld Arithmetik, kann aber einschließen Binärcodierte Dezimalzahl oder Dezimalfestpunkte und Unterstützung für viel größere (willkürliche Präzision) arithmetische Operationen durch Unterstützung parallel
  • Bitmanipulation -einschließlich vektorisierter Versionen von Bit-Level-Permutationsoperationen, Bitfield Insert und Extrakt, Zentrifugenoperationen, Bevölkerungszahl und viele andere.

GPU -Vektorverarbeitungsfunktionen

Mit vielen 3d Shader Anwendungen erforderlich trigonometrisch Operationen sowie kurze Vektoren für gemeinsame Operationen (RGB, ARGB, XYZ, XYZW) für Folgendes sind in der Regel im modernen GPUs vorhanden, zusätzlich zu denen, die in Vektorprozessoren zu finden sind:

  • Subvektoren -Elemente können typischerweise zwei, drei oder vier Subelemente (Vec2, Vec3, VEC4) enthalten, wobei ein bestimmtes Bit einer Prädikatmaske für das gesamte VEC2/3/4 gilt, nicht für die Elemente im Subvektor. Subvektoren werden auch in RISC-V RVV (als "lmul" bezeichnet) eingeführt.[32] Subvektoren sind ein kritischer integraler Bestandteil der Vulkan Spire-V Spezifikation.
  • Subvektor Swizzle -AKA "Lane Shufling", das die Interelementberechnungen von Subvektor ermöglicht, ohne zusätzliche (kostspielige, verschwenderische) Anweisungen zu benötigen, um die Subelemente in die richtigen Simd "Spuren" zu verschieben und auch Prädikat-Masken-Bits zu sparen. Effektiv ist dies ein Flucht Mini-Permute des Subvektors, starke Merkmale in 3D-Shader-Binärdateien und ist ausreichend wichtig, um Teil der Vulkan Spire-V Spezifikation. Das Broadcom Videokore IV verwendet die Terminologie "Lane Rotate"[33] wo der Rest der Branche den Begriff nutzt "Swizzle".[34]
  • Transzendententrigonometrisch Operationen wie Sinus, Kosinus und Logarithmus Offensichtlich viel überwiegend überwiegend in 3D als in vielen anspruchsvollen HPC Workloads. Von Interesse ist jedoch, dass die Geschwindigkeit in 3D für GPUs weitaus wichtiger ist als die Genauigkeit, wobei die Berechnung von Pixelkoordinaten einfach keine hohe Genauigkeit erfordert. Das Vulkan Die Spezifikation erkennt dies an und setzt überraschend geringe Genauigkeitsanforderungen fest, so dass GPU -Hardware den Stromverbrauch verringern kann. Das Konzept der Reduzierung der Genauigkeit, bei der es einfach nicht benötigt wird, wird in der untersucht MIPS-3D Verlängerung.

Fehler (oder scheitern) zuerst

In Arm SVE2 und RISC-V RVV wird das Konzept der spekulativen sequentiellen Vektorlasten eingeführt. ARM SVE2 hat ein spezielles Register mit dem Namen "First Fehler Register".[35] wobei RVV die Vektorlänge (VL) verändert (verkürzen).[36]

Das Grundprinzip des FFIRST besteht darin, eine große sequentielle Vektorbelastung zu versuchen, aber die Hardware zum willkürlichen Abschneiden der tatsächlich Betrag, der entweder auf den Betrag geladen wurde, der erfolgreich sein würde, ohne einen Speicherfehler zu erhöhen, oder einfach auf einen Betrag (größer als Null), der am bequemsten ist. Der wichtige Faktor ist das anschließend Anweisungen werden benachrichtigt oder können genau bestimmen, wie viele Lasten tatsächlich erfolgreich sind, und diese Menge, um nur die Arbeit an den tatsächlich geladenen Daten auszuführen.

Vergleichen Sie diese Situation mit SIMD, die eine feste (unflexible) Lastbreite und feste Datenverarbeitungsbreite ist, die nicht mit Lasten, die die Seitengrenzen überschreiten, nicht in die Lage versetzt werden können, und selbst wenn sie es auch nicht, können sie sich nicht an das anpassen, was tatsächlich erfolgreich war, und paradoxerweise. Wenn das SIMD -Programm überhaupt versuchen würde, im Voraus (in jeder inneren Schleife jedes Mal) herauszufinden, was möglicherweise optimal erfolgreich sein könnte, dienen diese Anweisungen nur dazu, die Leistung zu behindern, da sie zwangsläufig Teil der kritischen inneren Schleife sein würden.

Dies beginnt auf den Grund, warum fFirst so innovativ ist, und wird am besten durch Memcpy oder STRCPY illustriert, wenn es mit nicht verteilten nicht-fach-Simd mit 128-Bit-Standards implementiert wird. Für IBM Power9 beträgt die Anzahl der handoptimierten Anweisungen zur Implementierung von STRNCPY mehr als 240.[37] Im Gegensatz dazu ist die gleiche Strncpy-Routine in handtoptimierten RVV-Assembler nur 22 Anweisungen.[38]

Das obige SIMD -Beispiel könnte möglicherweise am Ende des Speichers scheitern und fehlschlagen, da versucht wird, zu viele Werte zu lesen: Es könnte auch eine erhebliche Anzahl von Seiten- oder falsch ausgerichteten Fehlern verursachen, indem sie die Grenzen ähnlich überqueren. Im Gegensatz dazu kann der erste Teil einer STRNCPY die Freiheit der Vektorarchitektur zulassen anschließend Iterationen der Schleife Die Stapel vektorisierten Speicherlesungen sind optimal mit den zugrunde liegenden Caches und virtuellen Speicheranordnungen ausgerichtet. Darüber hinaus kann die Hardware die Gelegenheit nutzen, um die Speicher der bestimmten Schleifen -Iteration zu beenden exakt Auf einer Seitengrenze (Vermeidung einer kostspieligen zweiten TLB -Suche), wobei die spekulative Ausführung die nächste virtuelle Speicherseite vorbereitet, während die Daten in der aktuellen Schleife noch verarbeitet werden. All dies wird durch die Hardware und nicht durch das Programm selbst bestimmt.[39]

Leistung und beschleunigen

Lassen r das Vektorgeschwindigkeitsverhältnis sein und f Sei das Vektorisierungsverhältnis. Wenn die Zeit, die die Vektoreinheit benötigt, um ein Array von 64 Zahlen hinzuzufügen (Nach der Vektorisierung), dann werden F = 0,9, d. H. 90% der Arbeiten von der Vektoreinheit durchgeführt. Es folgt der erreichbaren Geschwindigkeit von:

Also, auch wenn die Leistung der Vektoreinheit sehr hoch ist () Es gibt eine Beschleunigung weniger als , was darauf hindeutet, dass das Verhältnis f ist entscheidend für die Leistung. Dieses Verhältnis hängt von der Effizienz der Zusammenstellung wie der Adjazenz der Elemente im Gedächtnis ab.

Siehe auch

Externe Links

Verweise

  1. ^ Malinovsky, B.N. (1995). Die Geschichte der Computertechnologie in ihren Gesichtern (auf Russisch). Kiew: Firma "Kit". ISBN 5-7707-6131-8.
  2. ^ Vertikale Forschungsgruppe Miaow
  3. ^ Miaow GPU
  4. ^ Miyaoka, Y.; Choi, J.; Togawa, N.; Yanagisawa, M.; Ohtsuki, T. (2002). Ein Algorithmus der Hardwareeinheit Generierung für die Prozessor -Kernsynthese mit gepackten SIMD -Anweisungen. Asien-Pazifikkonferenz über Schaltkreise und Systeme. Vol. 1. S. 171–176. doi:10.1109/apccas.2002.1114930. HDL:2065/10689.
  5. ^ "RISCV-V-Spec/V-Spec.Adoc bei Master · RISCV/RISCV-V-Spec". GitHub.
  6. ^ Cray -Übersicht
  7. ^ RISC-V RVV ISA
  8. ^ SX-Arora-Übersicht
  9. ^ "Dokumentation - Armentwickler".
  10. ^ "Vektorarchitektur". 27. April 2020.
  11. ^ Vektor- und SIMD-Prozessoren, Folien 12-13
  12. ^ Array vs Vektorverarbeitung, Folien 5-7
  13. ^ SIMD vs Vektor GPU, Folien 22-24
  14. ^ Patterson, David A.; Hennessy, John L. (1998). Computerorganisation und Design: Die Hardware/Software-Schnittstelle Seite 751-2 (2. Aufl.). Morgan Kaufmann. p.751-2. ISBN 155860491X.
  15. ^ "RISCV-V-Spec/V-Spec.Adoc bei Master · RISCV/RISCV-V-Spec". GitHub.
  16. ^ Videocore IV -Programmierhandbuch
  17. ^ Videokore IV QPU -Analyse von Jeff Bush
  18. ^ "Codierung für Neon - Teil 3 Matrix -Multiplikation".
  19. ^ Simd hielt als schädlich an
  20. ^ Arm Sve2 Tutorial
  21. ^ "SSE-1-zu-4-Sendung und 4-zu-1-Reduzierung in AVX-512".
  22. ^ "Assembly - schnellster Weg, um die horizontale SSE -Vektorsumme (oder andere Reduktion) durchzuführen".
  23. ^ "RISCV-V-Spec/V-Spec.Adoc bei Master · RISCV/RISCV-V-Spec". GitHub.
  24. ^ Cray -Übersicht
  25. ^ RISC-V RVV ISA
  26. ^ SX-Arora-Übersicht
  27. ^ RVV-Register-Sammelstreuungsanweisungen
  28. ^ "IBMs Power10 -Prozessor - William Starke & Brian W. Thompto, IBM". Youtube. Archiviert vom Original am 2021-12-11.
  29. ^ Moreira, José E.; Barton, Kit; Schlacht, Steven; Bergner, Peter; Bertran, Ramon; Bhat, Puneeth; Caldeira, Pedro; Edelsohn, David; Fossum, Gordon; Frey, Brad; Ivanovic, Nemanja; Kerchner, Chip; Lim, Vincent; Kapoor, Shakti; Tulio Machado Filho; Silvia Melitta Mueller; Olsson, Brett; Sadasivam, satisch; Saleil, baptiste; Schmidt, Bill; Srinivasaraghavan, Rajalakshmi; Srivatsan, Shricharan; Thompto, Brian; Wagner, Andreas; Wu, Nelson (2021). "Eine Matrix -Mathematik -Einrichtung für Power ISA (TM) -Prozessoren". Arxiv:2104.03142 [cs.ar].
  30. ^ Krikelis, Anargyros (1996). "Ein modularer massiv paralleler Prozessor für die volumetrische Visualisierungsverarbeitung". Hochleistungs -Computing für Computergrafiken und Visualisierung. S. 101–124. doi:10.1007/978-1-4471-1011-8_8. ISBN 978-3-540-76016-0.
  31. ^ "CUDA C ++ Programmierhandbuch".
  32. ^ Lmul> 1 in RVV
  33. ^ Verlassenes US-Patent US20110227920-0096
  34. ^ Videokore IV QPU
  35. ^ Einführung in Arm SVE2
  36. ^ RVV-Fehler-First-Lasten
  37. ^ Patch zu LIBC6, um optimierte Power9 -Strncpy hinzuzufügen
  38. ^ RVV STRNCPY -Beispiel
  39. ^ Arm Sve2 Papier von N. Stevens