OpenCL im Handel - Seite 5

 

6. Superskalar und VLIW



6. Superskalar und VLIW

Das Video untersucht, wie Prozessoren die superskalare Ausführung verwenden, um Parallelität zwischen binären Anweisungen zu erkennen und zu extrahieren, um die Leistung zu verbessern. Es erörtert die Bedeutung der Steuerlogik beim Identifizieren von Fällen, in denen Anweisungen gleichzeitig ausgeführt werden können, beispielsweise wenn keine Abhängigkeiten zwischen ihnen bestehen. Das Video stellt auch zwei Beispiele für Prozessordesign vor, Superskalar und VLIW, wobei letzteres die Verantwortung für die Erkennung von Abhängigkeiten auf Compiler verlagert und lange Befehlswörter generiert, die parallel ausgeführt werden. Während VLIW die Laufzeitprüfung reduziert, können ungenutzte Stellen im langen Befehlswort immer noch Verschwendung in der Ausführungseinheit verursachen.

  • 00:00:00 In diesem Abschnitt erklärt das Video, wie Prozessoren die superskalare Ausführung nutzen, um die Gesamtleistung in Programmen mit binären Anweisungen zu verbessern. Programmierer verlassen sich auf gut konzipierte Prozessoren, um ihre Programme korrekt auszuführen, und daher fällt die Verantwortung auf den Prozessor, Parallelität aus den Anweisungen zu identifizieren und zu extrahieren, um die Leistung zu steigern. Das Video zeigt ein Beispiel für einen Abhängigkeitsgraphen zwischen Anweisungen, und obwohl es Abhängigkeiten zwischen bestimmten Anweisungen gibt, können Prozessoren andere gleichzeitig ausführen, da keine Abhängigkeiten zwischen ihnen bestehen. Es ist die Aufgabe der Steuerlogik innerhalb des Prozessors, diese Instanzen zu identifizieren und Anweisungen so effizient wie möglich auszuführen, um die Leistung zu maximieren.

  • 00:05:00 In diesem Abschnitt behandelt das Video zwei Beispiele für architektonische Designs in Prozessoren – Superskalar und VLIW. Das erste Beispiel zeigt, wie der Prozessor Abhängigkeiten zwischen Anweisungen erkennen und sie entsprechend planen kann, um Zeit zu sparen. Das Video hebt auch die Möglichkeit der spekulativen Ausführung von Verzweigungsanweisungen hervor. Das zweite Beispiel behandelt das VLIW-Design, das die Verantwortung für das Erkennen von Abhängigkeiten auf Compiler verlagert. Der Compiler generiert lange Befehlswörter, die mehrere Befehle umfassen, die parallel ausgeführt werden können, wodurch das Prozessordesign einfacher wird.

  • 00:10:00 In diesem Abschnitt wird das Konzept eines sehr langen Anweisungsworts (VLIW) erklärt. Dadurch können mehrere Befehle in ein langes Befehlswort gepackt werden, das zusammen abgerufen und decodiert wird. Das VLIW verlagert die Verantwortung auf Compiler, Möglichkeiten zum gleichzeitigen Ausführen von Anweisungen zu entdecken, bevor das Programm ausgeführt wird, und reduziert die Notwendigkeit einer Laufzeitüberprüfung. Wenn es jedoch leere Stellen in dem langen Befehlswort gibt, kann die Ausführungseinheit immer noch eine gewisse Verschwendung erfahren.
 

7. SIMD und Hardware-Multithreading



7. SIMD und Hardware-Multithreading

Das Video erklärt zwei Möglichkeiten, Herausforderungen der Parallelität anzugehen: Single Instruction, Multiple Data (SIMD) und Hardware-Multithreading (SMT). SIMD ermöglicht die parallele Ausführung von Hardwarebefehlen auf mehreren Datenelementen, wodurch die Planungs- und Dekodierungslogik vereinfacht wird. SMT nutzt die Parallelität auf Thread-Ebene, indem es unabhängige Befehlsströme gleichzeitig ausführt, zusätzliche Registerdateien erfordert und eine sorgfältige gemeinsame Nutzung des Caches erfordert. Das Video diskutiert auch die Implementierung von Time-Sliced-Thread-Scheduling, bei dem Threads abwechselnd den Datenpfad des Prozessors in Round-Robin-Manier belegen, die Latenz reduzieren und mehreren Threads den gleichzeitigen Zugriff auf Recheneinheiten und Speichersysteme ermöglichen. Letztendlich kann der Prozessor so viele Threads wie erforderlich aufnehmen, obwohl der Leistungsgewinn bei einem Single-Thread-Prozessor möglicherweise nicht so signifikant ist.

  • 00:00:00 In diesem Abschnitt wird das Konzept von Single Instruction Multiple Data (SIMD) erläutert, bei dem Hardwarebefehle für die parallele Ausführung von Operationen an mehreren Datenelementen verwendet werden können. SIMD vereinfacht die Planungs- und Dekodierungslogik, da nur eine Anweisung geplant werden muss, um dieselbe Operation auf jedes Element der Daten anzuwenden. Die Verwendung von SIMD ist vorteilhaft, wenn das zu lösende Problem eine erhebliche Datenparallelität beinhaltet, andernfalls ist es möglicherweise keine effiziente Lösung. Außerdem wird die Ähnlichkeit von SIMD und Vektorberechnung erläutert, bei der Vektorbefehle auf Daten angewendet werden können, die über verschiedene Teile des Speichers verstreut sind, um virtuelle Operationen auszuführen.

  • 00:05:00 In diesem Abschnitt erklärt das Video, wie Hardware-Multi-Threading oder simultanes Multi-Threading (SMT) verwendet werden kann, um Parallelität auf Thread-Ebene auszunutzen. Indem mehrere Programme oder Threads auf demselben Prozessor abgelegt werden, können verschiedene Befehlsströme gleichzeitig ausgeführt werden, wenn sie unabhängig voneinander sind. Hardware-Multithreading kann für große Maschinen und einzelne CPUs nützlich sein, da es die einfache Extraktion von Anweisungen aus zwei unabhängigen Threads ermöglicht. Dies erfordert jedoch zusätzliche Registerdateien und eine sorgfältige Überlegung, wie Caches von den verschiedenen Threads gemeinsam genutzt werden.

  • 00:10:00 In diesem Abschnitt des Videos erläutert der Moderator, wie die Arithmetic Logic Unit (ALU) durch die Implementierung von Time-Sliced-Thread-Scheduling ausgelastet bleibt. Diese Methode ermöglicht es Threads, abwechselnd den Datenpfad des Prozessors in einer Round-Robin-Manier zu belegen, was die Latenz erheblich reduziert, indem mehr Threads geplant werden. Indem die nächste Anweisung ausgeführt wird, während auf einen blockierten Thread gewartet wird, ermöglicht dieses Verfahren, dass Recheneinheiten und Speichersysteme von mehreren Threads gleichzeitig verwendet werden. Das Ergebnis ist letztendlich, dass keine Zeit verschwendet wird und der Prozessor so viele Threads wie nötig aufnehmen kann. Die Leistung eines einzelnen Threads auf einem Single-Thread-Prozessor wird jedoch möglicherweise nicht so stark verbessert wie auf einem Multi-Thread-Prozessor.
 

8. Multicore-Prozessorarchitektur



8. Multicore-Prozessorarchitektur

Dieses Video erklärt die Architektur von Multicore-Prozessoren und ihre Vorteile, wie z. B. mehrere Kerne, die unabhängig voneinander arbeiten und einige Komponenten gemeinsam nutzen, während jeder Kern über seine eigene Pipeline und seinen eigenen Datencache verfügt. Die Bedeutung der Cache-Hierarchie beim Überbrücken der Geschwindigkeitslücke zwischen Mikroprozessor- und Speicherzugriff wird unter Verwendung mehrerer Cache-Ebenen hervorgehoben, die die zeitliche und räumliche Lokalität ausnutzen. Das Video geht auch auf das System-on-Chip-Design ein, das verschiedene Funktionseinheiten und Schnittstellen in einem einzigen Chip kombiniert, um Kosten und Formfaktor zu reduzieren. Insgesamt bietet das Video eine nützliche Einführung in die Komplexität und die Kompromisse, die beim Design von Multicore-Prozessoren auftreten.

  • 00:00:00 In diesem Abschnitt lernen wir Mehrkernprozessoren und ihre Vorteile gegenüber Einkernprozessoren kennen. Multicore-Prozessoren verfügen über mehrere Kerne, die unabhängig voneinander arbeiten und einige Komponenten wie Befehlsabruf, Dekodierung und Gleitkomma-Scheduler gemeinsam nutzen. Jeder Kern hat jedoch seine eigene Pipeline und seinen eigenen Level-1-Daten-Cache. Multicore-Prozessoren benötigen Cache-Kohärenzprotokolle, um sicherzustellen, dass die in jedem Cache gespeicherten Daten mit den Daten im Hauptspeicher konsistent sind. System-on-Chip ist eine weitere Designoption, bei der mehrere Elemente zu einem einzigen Gerät auf demselben Chip kombiniert werden, um Kosten und Formfaktor zu reduzieren. Es verfügt über viele verschiedene dedizierte Funktionseinheiten und Schnittstellen, die über eine Unship-Verbindung mit dem Rest des Chips verbunden sind.

  • 00:05:00 In diesem Abschnitt erläutert der Referent das Konzept der Cache-Hierarchie in einer Multicore-Prozessorarchitektur. Der Hauptgrund für die Verwendung von Cache besteht darin, die Geschwindigkeitslücke zwischen dem Mikroprozessor und dem Speicherzugriff zu überbrücken, die mit unterschiedlichen Frequenzen ausgeführt werden und unterschiedliche Speicherkapazitäten haben. Die Level-1-, Level-2- und Level-3-Caches werden verwendet, um die Lücke zu überbrücken, und sie nutzen die zeitliche und räumliche Lokalität des Zugriffs auf eine kleine Anzahl von Anweisungen oder Daten in einem kurzen Zeitraum bzw. den Zugriff auf nahe gelegene Orte. Die Caches sind mithilfe von Blöcken organisiert, die zwischen den Speicherebenen verschoben werden, wodurch der Prozessor die zeitliche und räumliche Lokalität nutzen kann.
 

9. GPU-Architektur



9. GPU-Architektur

Die Accelerated Processing Unit (APU) ist ein heterogener Prozessor mit stromsparenden Kernen und GPU-Einheiten, die sich alle auf demselben Chip befinden. GPUs verfügen über eine große Anzahl von Shaderkernen, die mit Anweisungen geplant werden können, und ihre Caches sind im Allgemeinen nicht kohärent, was ihr Design vereinfacht und eine viel höhere Leistung ermöglicht, wenn viele Kerne gleichzeitig arbeiten. AMD und Nvidia verwenden kleine Recheneinheiten, um den Betrieb mehrerer Datenelemente gleichzeitig zu unterstützen, und verfügen über große Registerdateien, um einen schnellen Kontextwechsel zu unterstützen. Der Redner erklärt auch, wie der Kontrollfluss in der GPU-Architektur verwaltet wird, insbesondere im Umgang mit Verzweigungsbefehlen, die möglicherweise ungültige Ergebnisse liefern, aber Programmierer müssen sich nicht viel um diese Probleme kümmern, da die Prozessoranbieter bereits Kontrolllogik in der Hardware bereitgestellt haben. Insgesamt sind GPUs beliebte Prozessoren für komplexe Workloads auf dem modernen Markt, insbesondere im Bereich KI und maschinelles Lernen.

  • 00:00:00 In diesem Abschnitt lernen wir etwas über die beschleunigte Verarbeitungseinheit (Accelerated Processing Unit, APU), die ein typischer heterogener Prozessor ist, der aus stromsparenden Kernen besteht, die für allgemeine Datenverarbeitung, Verwaltung und Konfiguration des Systems verwendet werden, und GPU-Einheiten, alles auf dem gleichen Chip. Die APU hat einen typischen x86-Kern mit zwei Cache-Ebenen, während die GPU-Kerne anders und nicht x86 sind, wobei ein geringerer lokaler Datenspeicher als privater Speicher gilt. Der Speicherbesitz ist in einem Diagramm sichtbar, das die Speicherorte, die Zugänglichkeit und die Größe des Speichers zeigt, wobei der private Speicher kleiner als der lokale Speicher und viel kleiner als der globale Speicher ist. Die aktuellen Laptop-Prozessoren von Intel oder AMD haben typischerweise eine kleine Anzahl von Allzweckkernen, integriertem Speicher und einer On-Chip-Grafikverarbeitungseinheit.

  • 00:05:00 In diesem Abschnitt erfahren wir mehr über die GPU-Architektur und wie sie im Bereich KI und maschinelles Lernen verwendet wird. GPUs verfügen über eine große Anzahl von Prozessoren, sogenannte Shader-Kerne, die mit Anweisungen geplant werden können. Sie können auf Hochgeschwindigkeits-GPU-Speicher zugreifen, der sich vom Speichersubsystem eines Allzweckprozessors unterscheidet, und ihre Caches sind im Allgemeinen nicht kohärent. GPUs verwenden kein Cache-Kohärenzprotokoll, um Konsistenz zu gewährleisten, was das Design vereinfacht und eine viel höhere Leistung ermöglicht, wenn viele Kerne gleichzeitig arbeiten. Insgesamt sind GPUs ein beliebter Prozessor für komplexe Workloads auf dem modernen Markt.

  • 00:10:00 In diesem Abschnitt erfahren wir, wie AMD und Nvidia kleine Recheneinheiten verwenden, die über cmd-Hardware verfügen, um die Operation mit mehreren Datenelementen gleichzeitig zu unterstützen. Beide Anbieter haben 16 breite cmds und können die Arbeitselemente in größere Gruppen gruppieren und sie je nach Chip und Konfigurationsparametern verschiedenen Stapeln zuordnen. Darüber hinaus verfügen sie über große Registerdateien, um einen schnellen Kontextwechsel zu unterstützen, und beide Anbieter verfügen über eine Kombination aus automatischem Level-1-Cache und benutzerverwaltetem Scratchpad, das stark durch hohe Bandbreite unterstützt wird, um schnelle Operationen auf ihren jeweiligen privaten Speichern zu unterstützen. Abschließend gehen wir kurz auf den Kontrollfluss und das Konzept der Ausführung mehrerer Daten mit einer Anweisung ein und darauf, wie Verzweigungsanweisungen zu Abweichungen bei den Ausführungspfaden führen, was eine Möglichkeit erfordert, den Rechenaufwand für ungültige Daten zu minimieren.

  • 00:15:00 In diesem Abschnitt erläutert der Referent, wie der Kontrollfluss in der GPU-Architektur verwaltet wird, insbesondere im Umgang mit Verzweigungsanweisungen, die ungültige Ergebnisse erzeugen können. Um dieses Problem zu lösen, können cmd-Spuren maskiert werden, um einige Berechnungen zu verwerfen, obwohl dies die Leistung beeinträchtigen kann. Ein weiteres Problem, das wir bei der Verwendung der SIMT-Technologie (Single Instruction Multiple Threads) angehen müssen, ist die Divergenz zwischen Software-Threads, die Rechenzyklen verschwenden kann, wenn sie nicht gut verwaltet wird. Glücklicherweise brauchen sich OpenCL-Programmierer um diese Probleme nicht zu kümmern, da die Prozessorhersteller bereits Steuerlogik in der Hardware bereitgestellt haben.
 

10. FPGA-Internals


10. FPGA-Internals

In diesem Video werden die Architektur und Funktionen von feldprogrammierbaren Gate-Arrays (FPGAs) erläutert. FPGAs verfügen über eine programmierbare Logik, mit der sie neu programmiert werden können, um neue Funktionalitäten aufzunehmen, und haben direkten Zugriff auf Daten durch riesige Mengen an Ein- und Ausgängen (I/Os). Die Lookup-Tabellenstruktur in FPGAs besteht aus mehreren Ebenen von Multiplexern, die zur Definition von Logikfunktionen programmiert werden können. FPGAs verwenden programmierbare Register, die für Zähler, Schieberegister, Zustandsmaschinen und DSP-Funktionen verwendet werden können. Jeder rechteckige Block auf dem Chip stellt einen Logic Array Block (LAB) dar, wobei jeder LAB zehn Adaptive Logic Modules (ALMs) enthält. FPGAs werden in Branchen wie Verbrauchergeräten, Automobilindustrie, medizinischer Instrumentierung sowie Kommunikation und Rundfunk eingesetzt.

  • 00:00:00 In diesem Abschnitt werden die Grundlagen von FPGAs eingeführt, einschließlich ihrer programmierbaren Logik, die umprogrammiert werden kann, um neue Funktionalitäten aufzunehmen, und ihres direkten Zugriffs auf Daten durch riesige Mengen an I/Os. Die Vorteile von FPGAs sind ihre bequeme Verbindung zu Speicherkomponenten und Koprozessoren, austauschbare Funktionalitäten ohne die Notwendigkeit, Hardware auszutauschen, und ihre Allgegenwart in Branchen wie Verbrauchergeräten, Automobilindustrie, medizinischer Instrumentierung sowie Kommunikation und Rundfunk. Die Architektur von FPGAs umfasst die Lookup-Tabelle, die programmiert werden kann, um Logikfunktionen zu definieren, und andere wichtige Teile wie Übertragsregister und adaptive Logikmodule, die in den nachfolgenden Abschnitten besprochen werden.

  • 00:05:00 In diesem Abschnitt des Videos erläutert der Moderator die Struktur einer Lookup-Tabelle in FPGAs, die aus mehreren Ebenen von Multiplexern mit wählbaren Eingängen besteht. Die Eingaben in die Nachschlagetabelle können verwendet werden, um eine beliebige kombinatorische Logikfunktion aufzubauen. Das Video behandelt dann programmierbare Register, die Speicherelemente in FPGAs sind, die für Zähler, Schieberegister, Zustandsmaschinen und DSP-Funktionen verwendet werden. Diese Register haben ein Taktsignal, das typischerweise von einem globalen Takt angesteuert wird, und können in die Nachschlagetabelle zurückgeführt werden. Darüber hinaus erklärt das Video, wie Logikelemente und adaptive Logikmodule durch Kettensignale verbunden werden
    und Übertragsbits und wie die Eingabe in Register von vorherigen Logikelementen kommen kann.

  • 00:10:00 In diesem Abschnitt lernen wir, wie die Logikelemente in einem FPGA-Chip organisiert werden. Jeder rechteckige Block auf dem Chip stellt einen Logic Array Block (LAB) dar, wobei jeder LAB zehn Adaptive Logic Modules (ALMs) enthält. Jedes ALM besteht aus arithmetischen Einheiten, lokalen Verbindungs- und Registrierungsverbindungen sowie dedizierten Ressourcen und einer adaptiven Nachschlagetabelle für eine flexible Organisation von Eingaben und eine spezifische Ausgabeerzeugung. Darüber hinaus haben wir Zeilen- und Spaltenverbindungen, die bestimmte LABs verbinden können, und Routingskalen, die abhängig von der Gerätedichte linear skaliert werden. Schließlich haben wir eingebettete Speicherblöcke, die verschiedene Arten von Speicherstrukturen unterstützen, wie z. B. Single- oder Dual-Port-RAM, Nur-Lese-Speicher oder kleine Abschnitte von Speicherstrukturen, die als eMLABs bezeichnet werden.

  • 00:15:00 In diesem Abschnitt lernen wir die verschiedenen Funktionalitäten von FPGAs kennen, darunter digitale Signalverarbeitungsblöcke (DSP) und Ein-/Ausgangskomponenten (IO). DSP-Blöcke sind nützlich für die Implementierung von Signalverarbeitungsfunktionen wie FFT-Transformationen und Hochleistungs-Multiplikations- und Akkumulationsoperationen. FPGAs können auch mit verschiedenen IO-Komponenten kommunizieren, wodurch die Ausgabe aktiviert, gesteuert und abgeschlossen werden kann. Die Logik des IO-Elements umfasst bidirektionale Pins und eine Ausgangsfreigabesignalsteuerung, und der Ausgangspfad erzeugt die Werte A und B durch das Taktsignal. Wenn die Ausgangssteuerung dagegen deaktiviert ist, durchlaufen die Eingangssignale das Eingangsregister.

  • 00:20:00 In diesem Abschnitt über FPGA-Interna wird die Bedeutung von Taktsignalen zusammen mit der Verwendung dedizierter Eingangstaktpins zur Unterstützung von FPGA-Operationen hervorgehoben. Es werden auch Hochgeschwindigkeits-Transceiver diskutiert, die für die Implementierung komplexerer Signalprotokolle in FPGAs nützlich sind, ohne dass eine komplexe Signalkonditionierung und -verarbeitung erforderlich ist. Die Verwendung von PLLs zur Erzeugung unterschiedlicher Taktsignale zur Verwendung im gesamten Gerät mit minimalem Versatz wird ebenfalls erläutert, zusammen mit der Verwendung von SRAM-Zellentechnologie und Nachschlagetabellen zur Konfiguration programmierbarer Bits, die die Konnektivität von Eingangs- und Ausgangssignalen steuern. Das Video behandelt auch Methoden zum Programmieren von FPGAs mit externem W-Prom, Cpl D oder einer CPU zur Steuerung von Programmiersequenzen sowie die Verwendung einer speziellen Hardware-JTAG-Verbindung für weitere Diagnose und Debugging.

  • 00:25:00 In diesem Abschnitt werden das Design und die Funktionen eines feldprogrammierbaren Gate-Arrays (FPGA) besprochen. Der größte Teil der Fläche in einem FPGA sind die Logik-Array-Blöcke, die durch Zeilen- und Spaltenverbindungen verbunden werden können. Andere Blöcke umfassen PR, Transceiver und einen Speichercontroller, der mit verschiedenen Speicherkomponenten verbunden werden kann. Als Beispiel wird ein PJ-Bereich 10g X FPGA mit 1 Million Logikelementen, 1,7 Millionen Registern, 54.000 Speicherblöcken mit je 22 Bit, 1.518 DSP-Blöcken, 367,4-Gigabit-pro-Sekunde-Transceivern, zwei harten PCIe-Blöcken, 492 allgemeinen IO-Pins und 12 Speichercontroller. Der Vorteil von FPGAs ist die hohe Dichte zum Erstellen komplexer Funktionen, die Integration mehrerer Funktionen, der Zugriff auf verschiedene IO-Standards und -Funktionen sowie der direkte Zugriff auf Daten in einem Chip.
 

11. OpenCL-Speicher auf einem GPU-System



11. OpenCL-Speicher auf einem GPU-System

Der Kursleiter erklärt die Zuordnung von OpenCL-Speicher zu AMD-GPU und die verschiedenen Speicherebenen in einem GPU-System. Das Rechengerät hat einen Befehlsprozessor, der Anweisungen an die Recheneinheiten verwaltet, die als Kerne mit mehreren SIMD-Spuren, privaten Registerdateien und privatem Speicher fungieren. Das Kernel-Programm soll autonome Jobs bereitstellen, die es ermöglichen, alle verfügbaren Kerne zu nutzen und die Speicherzugriffslatenz zu verringern. Der Referent erwähnt auch das Konzept der arithmetischen Intensität, das sich auf das Verhältnis zwischen Berechnung und Bewegung der Speicherachse bezieht, und wie hoch es sein sollte, um zu vermeiden, dass die Speicherbandbreite der GPU der limitierende Faktor ist.

  • 00:00:00 In diesem Abschnitt diskutiert der Redner OpenCL in Bezug auf die Hardwarearchitektur verschiedener Prozessoren, wobei er sich speziell auf die AMD-GPU konzentriert. Das Diagramm zeigt den globalen Speicher, den konstanten Speicher und den lokalen Speicher, wobei der Kernel auf der linken Seite den OpenCL-Kernel darstellt, der beim Entwerfen eines datenparallelen Programms verwendet wird. Jede Arbeitsgruppe führt eine Teilmenge der Berechnung basierend auf den Daten durch, wobei der lokale Speicher für die Arbeitsgruppe lokal ist und mit den Ausführungseinheiten innerhalb des Prozessors geteilt wird. Die Arbeitselemente innerhalb der Arbeitsgruppe sind die tatsächlich durchgeführten Berechnungen, wobei jedes seinen eigenen Datensatz hat.

  • 00:05:00 In diesem Abschnitt erläutert der Kursleiter, wie OpenCL-Speicher AMD-GPU zugeordnet wird, und die verschiedenen Speicherebenen auf einem GPU-System. Die Rechenvorrichtung hat einen Befehlsprozessor, der Anweisungen an die Recheneinheiten plant, die einen Level-1-Cache haben und einen Level-2-Cache gemeinsam nutzen und mit dem globalen Speicher verbunden sind. Die Computereinheit fungiert als Kern mit mehreren SIMD-Spuren und privaten Registerdateien, GPRs genannt, die den privaten Speicher bilden. Es wird erwartet, dass das Kernel-Programm unabhängige Arbeitsteile bereitstellt, die so viele wie möglich sein sollten, um alle verfügbaren Kerne zu beschäftigen, und diese Teile sollten eine Hardware-Kontextumschaltung ermöglichen, um die Latenz beim Speicherzugriff zu minimieren. Der Kernel sollte auch eine hohe Rechenintensität haben, um die Hardware effizient zu nutzen.

  • 00:10:00 In diesem Abschnitt diskutiert der Sprecher das Konzept der romantischen Intensität, das im Wesentlichen das Verhältnis zwischen Berechnung und Bewegung der Gedächtnisachse ist. Das Ziel ist, mathematische Operationen für Speicherzugriffe so hoch wie möglich zu haben, um zu vermeiden, dass sie durch die Speicherbandbreite begrenzt werden.
 

12. OpenCL-Beispiel: Matrixmultiplikation



12. OpenCL-Beispiel: Matrixmultiplikation

Dieses Video stellt die Matrixmultiplikation als Beispiel für die OpenCL-Programmierung vor. Der Referent demonstriert, wie C-Code geschrieben wird, um unabhängige Schleifen zu erstellen, die Matrixzeilen und -spalten durchlaufen können. Arbeitselemente werden diskutiert und wie sie Matrixelementen in OpenCL zugeordnet werden können. Es wird eine Kernel-Implementierung erklärt, die die Kernel-Funktionsargumente, ihren Aufruf und ihren Rumpf behandelt. Der Sprecher zeigt, wie die Eingabematrix in einem eindimensionalen Array gespeichert wird, wobei Zeilen- und Indexnummern verwendet werden, um Indizes zu berechnen. Letztendlich berechnet die Kernel-Funktion das Skalarprodukt, um das Element in der Ausgabematrix zu erzeugen. Der lineare Ansatz zum Speichern von Matrizen im physikalischen Speicher wird betont.

  • 00:00:00 In diesem Abschnitt lernen wir die Matrixmultiplikation als Beispiel für die OpenCL-Programmierung kennen. Die Matrixmultiplikation ist ein klassisches Power-Computing-Beispiel, das in vielen verschiedenen Anwendungen verwendet wurde. Die Implementierung erfordert verschachtelte Schleifen mit der Anforderung, dass die Anzahl der Spalten der Matrix A gleich der Anzahl der Zeilen der Matrix B sein muss. Dies liegt daran, dass jedes resultierende Element in der Matrix C das Skalarprodukt eines Zeilenvektors von A ist mit einem Spaltenvektor von B. Wir sehen, wie C-Code geschrieben wird, um die Operation zu implementieren, und wie die Schleifen unabhängig arbeiten, sodass wir jede Zeile oder Spalte der resultierenden Matrix C auf zufällige Weise durchlaufen können.

  • 00:05:00 In diesem Abschnitt wird das Konzept der Arbeitselemente eingeführt und erklärt, wie Arbeitselemente Matrixelementen in OpenCL zugeordnet werden können. Arbeitselemente können für jedes Ausgabeelement einer unabhängig zu berechnenden Matrix erstellt werden und können daher auf Arbeitselemente mit zweidimensionalem Bereich abgebildet werden. Die Kernel-Implementierung für die Matrixmultiplikation in OpenCL wird ebenfalls besprochen, wobei die Argumente für die Kernel-Funktion und deren Aufruf aus der Hauptfunktion erklärt werden und der Hauptteil der Kernel-Funktion vorgestellt wird. Die Kernfunktion berechnet das Skalarprodukt eines Zeilenvektors und eines Spaltenvektors, um jedes Element der Ausgabematrix zu berechnen.

  • 00:10:00 In diesem Abschnitt erklärt der Referent den Prozess der Multiplikation von Matrizen mit der Programmiersprache OpenCL. Die Hauptidee besteht darin, die zweidimensionale Eingabematrix unter Verwendung der Zeilennummer und der Indexnummer in einem eindimensionalen Array zu speichern, um den richtigen Index zu berechnen, um das richtige Element zum Ausführen der Punktproduktoperation zu finden. Die Kernel-Funktion initialisiert die Summenvariable mit 0 und iteriert durch den Zeilenvektor von A und den Spaltenvektor von B, um das Skalarprodukt zu berechnen, und weist das Ergebnis schließlich dem entsprechenden Element in C zu. Diese Schritte veranschaulichen, wie Zeilen- und Spaltennummern verwendet werden Berechnen Sie Indizes auf lineare Weise, was für die Speicherung der Matrix im physischen Speicher unerlässlich ist.
 

13. Struktur eines OpenCL-Programms (Teil1)



13. Struktur eines OpenCL-Programms (Teil1)

Im Video „Aufbau eines OpenCL-Programms (Teil1)“ wird der Prozess zum Erstellen einer OpenCL-Anwendung erklärt. Das Programm muss zuerst die OpenCL-Plattform abfragen, um ihre Ressourcen zu verstehen und einen OpenCL-Kontext und eine Befehlswarteschlange zu erstellen. Anschließend werden Puffer für den Datenaustausch zwischen dem Host und dem Gerätespeicher erstellt, und das Kernelprogramm wird zur Ausführung auf dem Gerät in eine Binärdatei kompiliert. Das Video erklärt weiter, wie man schreibgeschützte und schreibgeschützte Puffer erstellt, Speicherplatz für Ausgabematrizen zuweist und Ergebnisse zurück auf den Host kopiert. Es wird betont, wie wichtig es ist, API-Aufrufe auf erfolgreiche Ausführung zu überprüfen.

  • 00:00:00 In diesem Abschnitt erläutert der Referent die Schritte zum Erstellen einer OpenCL-Anwendung. Zuerst muss das Programm die OpenCL-Plattform abfragen, um die auf der Plattform verfügbaren Ressourcen zu verstehen, und dann einen OpenCL-Kontext und eine Befehlswarteschlange erstellen, was für Pufferoperationen und Kernel-Starts unerlässlich ist. Anschließend werden Puffer erstellt, um Daten zwischen dem Host und dem Gerätespeicher auszutauschen. Anschließend muss das Kernelprogramm in eine Binärdatei kompiliert werden, die auf dem Beschleunigergerät entweder auf einem FPGA oder einer GPU ausgeführt werden kann. Der Kompilierungsprozess unterscheidet sich je nach Gerät.

  • 00:05:00 In diesem Abschnitt erläutert das Video, wie die Umgebung eingerichtet wird, um die Plattform und das Gerät zu erstellen, einen Kontext zu erstellen und Befehlswarteschlangen für die OpenCL-Programmierung zu erstellen. Dazu gehört das Abrufen der Plattform-ID, die es dem Programmierer ermöglicht, die Anzahl der verfügbaren Plattformen zu bestimmen und Speicherplatz für die Speicherung zuzuweisen. Das Video erklärt weiter, wie Sie die Geräte innerhalb der Plattform auswählen, Informationen über das ausgewählte Gerät abrufen, die richtigen Argumente festlegen und die Werte dieser Argumente an die Kernelfunktion übergeben, um den Kernel zu instanziieren. Schließlich zeigen sie, wie die Ergebnisse vom Gerät zurück in den Speicher des Hosts kopiert werden, sobald der Kernel fertig ist.

  • 00:10:00 In diesem Abschnitt erklärt das Video, wie ein OpenCL-Kontext erstellt wird und wie wichtig das Kontextobjekt ist, um alle für OpenCL-Vorgänge erforderlichen Ressourcen wie Befehlswarteschlangen und Puffer miteinander zu verknüpfen. Das Transkript beschreibt, wie Nur-Lese- und Nur-Schreiben-Puffer erstellt werden und wie Daten zwischen dem Host und dem Gerät mit CL Ink- und CL in Q-Schreibpufferbefehlen kopiert werden. Das verwendete Beispiel ist die Matrixmultiplikation, bei der die Matrizen A und B eingegeben werden und Matrix C eine Ausgabe ist. Das Video betont, wie wichtig es ist, nach erfolgreichen API-Aufrufen zu suchen.

  • 00:15:00 In diesem Abschnitt erklärt der Sprecher, wie Platz für Matrix C, die Ausgangsmatrix, zugewiesen wird. Sie sagen, dass Puffer C als CL-Speicher deklariert ist, der es dem Gerät ermöglicht, die Ergebnisse hineinzuschreiben. Dies verbietet jedoch nicht das Lesen dieses Puffers von der Hostseite, was notwendig ist, um die Ergebnisse vom Gerät abzurufen und die resultierende Matrix an eine Stelle im Host zu kopieren. Der Sprecher zeigt die vollständige Definition der Puffer-API, die fünf Argumente akzeptiert: Kontext, Flags, Größe, Hostzeiger und Rückgabewert.
 

14. Struktur eines OpenCL-Programms (Teil2)



14. Struktur eines OpenCL-Programms (Teil2)

Der dritte Schritt bei der OpenCL-Programmierung umfasst die Kernel-Kompilierung, die bei FPGA-Geräten anders ist, da sie offline erfolgt. Das CL-Erstellungsprogramm mit Quelle und C TX wird verwendet, um ein Programm zu erstellen, gefolgt von einem CL-Erstellungsprogramm, um das Programm in Binärdateien zu erstellen. Die richtige Kernelfunktion wird unter Verwendung des geeigneten Einstiegspunkts ausgewählt, und Kernelargumente müssen initialisiert werden, indem das CL-Kernelargument mit dem richtigen Zeiger festgelegt wird. Der Referent geht detailliert auf den richtigen Aufbau der Argumente bei der Matrizenmultiplikation ein. Anschließend besprechen sie das Einrichten lokaler und globaler Arbeitsgruppengrößen, das Ausführen des Kernels und das Abrufen der Ergebnisse mithilfe der CL in der Warteschlangenpuffer-API. Abschließend erwähnt der Referent kurz Ereignisse in der OpenCL-Programmierung.

  • 00:00:00 In diesem Abschnitt wird der dritte Schritt in einem OpenCL-Programm besprochen, der die Kompilierung des Kernels beinhaltet. Dieser Vorgang ist bei FPGA-Geräten etwas anders, da die Kompilierung offline erfolgt. Unter der Annahme, dass der Programmquellcode in einem Zeichenpuffer gespeichert ist, wird das CL-Erstellungsprogramm mit Quelle und C TX verwendet, um ein Programm zu erstellen, und das CL-Erstellungsprogramm wird verwendet, um das Programm in Binärdateien zu erstellen. Als nächstes wird die richtige Kernel-Funktion aus dem Quellcode ausgewählt, indem ein Kernel unter Verwendung des geeigneten Einstiegspunkts für die spezifische ausgewählte Kernel-Funktion erstellt wird. Sobald der Kernel erstellt ist, müssen die Kernel-Argumente richtig initialisiert werden, indem das Kernel-Argument CL gesetzt wird, wobei ein Zeiger auf den tatsächlichen Wert zeigt. Beispielsweise müssen bei der Matrixmultiplikation sieben Argumente richtig eingerichtet werden, einschließlich des Zielpuffers, der Größe der Matrizen und der zwei Eingabematrizen.

  • 00:05:00 In diesem Abschnitt spricht der Sprecher über das Initialisieren mehrerer Kernel-Argumente und hebt die Wichtigkeit hervor, die Indizes dieser Argumente korrekt einzurichten, um Fehler zu vermeiden. Anschließend erklären sie, wie lokale und globale Arbeitsgruppengrößen festgelegt werden, indem sie die Anzahl der Arbeitselemente in einer Gruppe und die Anzahl der Arbeitsgruppen angeben. Schließlich beschreiben sie die Schritte zum Ausführen des Kernels, einschließlich Aufrufen der OpenCL-API und Abrufen der Ergebnisse vom Device-to-Host-Speicher mithilfe der CL-in-Queue-Puffer-API. Der Referent erwähnt auch kurz Events und wie sie in der OpenCL-Programmierung verwendet werden können, aber darauf wird in späteren Vorträgen noch eingegangen.
 

15. Demo zur OpenCL-Matrixmultiplikation



15. Demo zur OpenCL-Matrixmultiplikation

Das Video „OpenCL Matrix Multiplication Demo“ erklärt den Vorgang zum Ausführen eines Matrixmultiplikationsbeispiels mit dem OpenCL-Framework. Es enthält mehrere Quellcodedateien wie ein C-Hauptprogramm für die Hostseite, ein Kernelprogramm und ein Makefile. Das Video behandelt verschiedene Aspekte des OpenCL-Frameworks, das Abrufen von Plattform- und Geräte-IDs, das Erstellen eines OpenCL-Kontexts, Programm- und Kernel-Objekte, die Pufferverwaltung für den Host sowie das Erstellen und Initialisieren von Puffern auf dem Gerät. Der Moderator zeigt auch einen Beispiel-Kernel, der Punktproduktoperationen ausführt, und eine Demo des Endergebnisses auf einer AMD Radeon Pro 575-Rechen-Engine.

  • 00:00:00 In diesem Abschnitt erklärt der Referent, wie ein Matrixmultiplikationsbeispiel über OpenCL ausgeführt wird. Das Beispiel besteht aus mehreren Quellcodedateien, darunter ein C-Hauptprogramm als hostseitiges Programm, ein Kernelprogramm namens my kernel CL und ein Makefile, das beim Kompilieren des Projekts hilft. Das Hauptprogramm umfasst Standardbibliotheken, Makrodefinitionen für das OpenCL-Framework und Deklarationen für Eingabematrizen (Matrix A und Matrix B) sowie Gerätenamen, Plattformkennungen und Gerätenummern. Der Referent beschreibt auch verschiedene Aspekte des OpenCL-Frameworks, wie das Lesen und Kompilieren von Kontext, Programm, Kernel und Quellcode. Darüber hinaus erläutert der Referent die Bedeutung von Plattform- und Geräte-IDs sowie Matrixdimensionen im Code.

  • 00:05:00 In diesem Abschnitt erläutert der Referent den Vorgang zum Abrufen der Plattform- und Geräte-IDs und zum Erstellen des OpenCL-Kontexts für die Demo zur Matrixmultiplikation. Sie erläutern, wie die Plattformanzahl zurückgegeben und das Array zum Speichern der Plattform-IDs zugewiesen wird. Sie zeigen auch, wie Sie die Geräte-IDs für einen ausgewählten bestimmten Typ erhalten und seinen Namen abfragen. Das Video zeigt, wie Sie für jedes Gerät eine Befehlswarteschlange erstellen und das OpenCL-Programm kompilieren. Sie erklären außerdem, wie man die App Open verwendet, um die Kernel-Quellcodedatei zu öffnen und das Programm zu kompilieren.

  • 00:10:00 In diesem Abschnitt erklärt das Video, wie ein Programmobjekt aus dem Quellcode des OpenCL-Kernels erstellt wird. Dieser Prozess ist auf verschiedenen Plattformen unterschiedlich. Unter Mac OS mit nativer OpenCL-Unterstützung kann man ein Programmobjekt mit dem Quellcode erstellen. Auf dem Altera FPGA OpenCL SDK beinhaltet das Erstellen eines Programmobjekts jedoch das Kompilieren des Kernels und das Erstellen aus dem binären Ergebnis dieser Kompilierung unter Verwendung der spezifischen API von Altera. Nachdem das Programmobjekt erstellt wurde, zeigt das Video, wie das Kernelprogramm erstellt und das Kernelobjekt erstellt wird. Schließlich geht das Video in die Pufferverwaltung auf der Hostseite, wo ein Puffer zugewiesen wird, um die resultierende Matrix C zu speichern.

  • 00:15:00 In diesem Abschnitt erläutert der Moderator, wie Puffer auf der Geräteseite für die Matrixmultiplikation mit OpenCL erstellt und initialisiert werden. Sie zeigen dann, wie Kernel-Argumente richtig eingestellt werden, einschließlich der Einstellung globaler und lokaler Arbeitsgruppengrößen. Die Bedeutung der Überprüfung des Rückgabewerts des CL wird ebenfalls hervorgehoben. Der Präsentator demonstriert dann, wie die Ergebnisse in den Hostspeicher gelesen werden, gefolgt von der Freigabe der auf dem Host und OpenCL zugewiesenen Ressourcen. Schließlich zeigen sie einen Beispiel-Kernel, der get globale ID verwendet, um durch die Breite einer Matrix zu iterieren, Skalarproduktoperationen durchzuführen und die Ergebnisse im entsprechenden Element in Matrix C zu speichern.

  • 00:20:00 In diesem Abschnitt erörtert der Sprecher den Aufbau des Haupt-C-Programms und des Mike-Rinder-CL-Programms. Um das hostseitige Programm zu erstellen, müssen Benutzer eine einzelne C-Programmdatei kompilieren, und für den Kernel kann man den GPU-Compiler verwenden, um den Micra, der die CL kennt, in eine GPU-Binärdatei zu kompilieren. Nachdem das Programm sowohl auf der Host- als auch auf der Geräteseite erstellt wurde, steht den Benutzern eine ausführbare Datei mit dem Namen „main“ sowie verschiedene Binärdateien für verschiedene GPU-Versionen zur Verfügung. Beim Ausführen dieser Datei zeigt der Sprecher eine OpenCL-Plattform mit einer AMD Radeon Pro 575-Rechenmaschine, die einen Anfangswert der C-Matrix mit allen Elementen hat, die acht Punkte enthalten.