GPU-Computing, das jeder Entwickler kennen sollte
(codeconfessions.substack.com)- GPUs sind so aufgebaut, dass sie massiv parallelen Durchsatz gegenüber niedriger Latenz einzelner Befehle priorisieren. Deshalb sind sie stark bei Aufgaben, die große Mengen gleichartiger Operationen ausführen, etwa Deep Learning, Grafik und numerische Berechnungen
- CPUs reduzieren Latenz bei sequenzieller Ausführung durch Pipelining, Out-of-order Execution, spekulative Ausführung und mehrstufige Caches. GPUs hingegen verbergen Latenz mit vielen ALUs und Threads und erhöhen so den Durchsatz
- Bei 32-Bit-Präzision erreicht die Nvidia Ampere A100 19,5 TFLOPS, während ein Intel-Prozessor mit 24 Kernen aus dem Jahr 2021 auf 0,66 TFLOPS kommt; die Durchsatzlücke bei numerischen Berechnungen wächst weiter
- Bei CUDA-Kerneln übernimmt der Host-Code auf der CPU die Ausführungsvorbereitung, während der Device-Code auf der GPU in einer Grid-, Block- und Thread-Struktur läuft. Threads werden in Gruppen zu 32, sogenannten Warps, gebündelt und im SIMT-Verfahren verarbeitet
- Die tatsächliche Performance hängt stark davon ab, wie Register, Shared Memory, Block-Slots und Thread-Slots eines SM aufgeteilt werden. Ist die Occupancy niedrig, lässt sich Latenz schwer verbergen und der maximale Durchsatz wird möglicherweise nicht erreicht
Unterschiedliche Designziele von CPU und GPU
- CPUs sind vor allem darauf ausgelegt, sequenzielle Befehlsausführung schnell zu verarbeiten
- Um die Latenz der Befehlsausführung zu reduzieren, nutzen sie Funktionen wie instruction pipelining, out-of-order execution, speculative execution und multilevel cache
- Eine einzelne Operation wie das Addieren zweier Zahlen oder kurze Operationsabläufe kann eine CPU mit geringerer Latenz verarbeiten als eine GPU
- GPUs sind auf massive Parallelität und hohen Durchsatz ausgelegt
- Aufgaben, bei denen viele lineare Algebra- und numerische Operationen schnell ausgeführt werden müssen, wie Videospiele, Grafik, numerische Berechnungen und Deep Learning, passen gut zu dieser Architektur
- Bei Millionen oder Milliarden gleichartiger Operationen kann eine GPU dank massiver Parallelität deutlich schneller arbeiten als eine CPU
- Die Leistung numerischer Berechnungen wird in FLOPS gemessen, also Gleitkommaoperationen pro Sekunde
- Die Nvidia Ampere A100 liefert bei 32-Bit-Präzision einen Durchsatz von 19,5 TFLOPS
- Ein Intel-Prozessor mit 24 Kernen lag 2021 bei 32-Bit-Präzision bei etwa 0,66 TFLOPS
- Die Durchsatzlücke zwischen GPU und CPU wächst von Jahr zu Jahr
Wie GPUs Latenz verbergen
- Auch wenn einzelne Befehle auf einer GPU eine hohe Latenz haben, erreicht sie durch viele Threads und Rechenressourcen Latenztoleranz
- Während ein Thread auf das Ergebnis eines Befehls wartet, führt die GPU andere Threads aus, die nicht warten müssen
- Durch dieses Scheduling bleiben Recheneinheiten möglichst kontinuierlich aktiv und können hohen Durchsatz aufrechterhalten
GPU-Compute-Architektur
- Eine GPU besteht aus einem Array mehrerer Streaming Multiprocessors (SMs)
- Jeder SM enthält mehrere Streaming Processors, Cores und Threads
- Die Nvidia H100 hat 132 SMs, jeder davon mit 64 Cores, also insgesamt 8.448 Cores
- Jeder SM verfügt über begrenzten On-Chip-Speicher, der von allen Cores gemeinsam genutzt wird
- Dieser Speicher wird Shared Memory oder Scratchpad genannt
- Auch die Ressourcen der Control Unit eines SM werden von den Cores gemeinsam genutzt
- Jeder SM besitzt einen hardwarebasierten Thread-Scheduler für die Thread-Ausführung
- Je nach Workload können außerdem spezielle Funktionseinheiten oder beschleunigte Recheneinheiten wie Tensor Cores oder Ray-Tracing-Units enthalten sein
GPU-Speicherhierarchie
-
Register
- Jeder SM verfügt über eine große Anzahl von Registern
- Nvidia A100 und H100 haben 65.536 Register pro SM
- Register werden von den Cores gemeinsam genutzt und je nach Bedarf der Threads dynamisch zugewiesen
- Register, die während der Ausführung einem bestimmten Thread zugewiesen sind, gehören exklusiv zu diesem Thread und können von anderen Threads weder gelesen noch beschrieben werden
-
Constant Cache
- Cachet konstante Daten, die vom auf dem SM ausgeführten Code verwendet werden
- Programmierer müssen Objekte im Code explizit als konstant deklarieren, damit die GPU sie im Constant Cache halten kann
-
Shared Memory
- Kleiner, schneller, latenzarmer, programmierbarer On-Chip-SRAM in jedem SM
- Wird von Thread Blocks gemeinsam genutzt, die auf demselben SM ausgeführt werden
- Wenn mehrere Threads dasselbe Datenstück verwenden, kann ein Thread es aus dem Global Memory lesen und die übrigen Threads können es gemeinsam nutzen, wodurch redundante Loads reduziert werden
- Wird auch als Synchronisationsmechanismus zwischen Threads innerhalb eines Thread Blocks verwendet
-
L1 Cache und L2 Cache
- Jeder SM hat einen L1 Cache, der häufig aus dem L2 Cache abgerufene Daten zwischenspeichert
- Der L2 Cache wird von allen SMs gemeinsam genutzt und cachet häufig aus dem Global Memory abgerufene Daten, um Latenz zu reduzieren
- L1 und L2 Cache arbeiten für den SM transparent; aus Sicht des SM sieht es so aus, als kämen die Daten aus dem Global Memory
-
Global Memory
- Eine GPU verfügt über Off-Chip Global Memory, einen großen DRAM mit hoher Bandbreite
- Die Nvidia H100 hat 80 GB HBM und 3000 GB/s Bandbreite
- Global Memory ist weit von den SMs entfernt und hat daher hohe Latenz, doch die On-Chip-Speicherhierarchie und viele Recheneinheiten helfen, diese Latenz zu verbergen
CUDA-Kernel und Thread-Struktur
- CUDA ist eine Programmierschnittstelle zum Schreiben von Programmen für Nvidia-GPUs
- Berechnungen, die auf der GPU ausgeführt werden sollen, werden als Kernel in einer Form ähnlich einer C/C++-Funktion ausgedrückt
- Das Beispiel ist ein Kernel zur Vektoraddition, der zwei Vektoren als Eingabe erhält, sie elementweise addiert und das Ergebnis in einen dritten Vektor schreibt
- Beim Ausführen eines Kernels werden mehrere Threads gestartet; diese gesamte Gruppe wird Grid genannt
- Ein Grid besteht aus einem oder mehreren Thread Blocks
- Jeder Thread Block besteht aus einem oder mehreren Threads
- Die Anzahl der Blocks und Threads hängt von der Datengröße und der gewünschten Parallelität ab
- Bei einer 256-dimensionalen Vektoraddition kann man einen Block mit 256 Threads erstellen, sodass jeder Thread ein Element des Vektors verarbeitet
- Bei größeren Problemen reichen die verfügbaren Threads der GPU möglicherweise nicht aus, sodass jeder Thread mehrere Datenpunkte verarbeiten kann
- Eine CUDA-Implementierung ist in zwei Teile gegliedert
- Host Code läuft auf der CPU und ist für das Laden der Daten, die Allokation von GPU-Speicher und den Start des Kernels mit dem konfigurierten Thread Grid verantwortlich
- Device Code läuft auf der GPU und definiert die eigentliche Kernel-Funktion
Schritte bei der Ausführung eines Kernels auf der GPU
-
Daten vom Host auf das Device kopieren
- Vor der Kernel-Ausführung müssen benötigte Daten aus dem CPU-Speicher in das GPU Global Memory kopiert werden
- Auf moderner GPU-Hardware kann auch Unified Virtual Memory verwendet werden, um direkt aus dem Host Memory zu lesen
-
Thread Blocks auf SMs schedulen
- Sobald die benötigten Daten im GPU-Speicher bereitstehen, werden Thread Blocks SMs zugewiesen
- Alle Threads innerhalb eines Blocks werden gleichzeitig auf demselben SM verarbeitet
- Vor der Ausführung muss die GPU die für diese Threads benötigten SM-Ressourcen reservieren
- In der Praxis können mehrere Thread Blocks gleichzeitig demselben SM zugewiesen sein
- Da die Anzahl der SMs begrenzt ist und große Kernel sehr viele Blocks haben können, werden nicht alle Blocks sofort ausgeführt
- Die GPU hält eine Liste wartender Blocks vor und weist einen wartenden Block der Ausführung zu, sobald ein anderer Block fertig ist
-
SIMT und Warp
- Threads, die einem SM zugewiesen sind, werden erneut in Gruppen zu 32 gebündelt; eine solche Gruppe heißt Warp
- Bei Nvidia-GPUs der aktuellen Generation beträgt die Warp-Größe 32, sie kann sich bei künftiger Hardware jedoch ändern
- Der SM holt denselben Befehl und gibt ihn an alle Threads im Warp aus
- Die Threads führen denselben Befehl gleichzeitig aus, verarbeiten aber unterschiedliche Datenbereiche
- Dieses Modell wird single instruction multiple threads (SIMT) genannt und ähnelt SIMD-Befehlen auf CPUs
- Moderne GPUs seit Volta unterstützen außerdem independent thread scheduling, das vollständige Gleichzeitigkeit zwischen Threads unabhängig vom Warp erlaubt
-
Warp-Scheduling und Latenztoleranz
- Selbst wenn alle Processing Blocks innerhalb eines SM Warps verarbeiten, führt zu einem bestimmten Zeitpunkt nur ein Teil der Warps tatsächlich Befehle aus
- Der Grund ist, dass die Anzahl der Ausführungseinheiten eines SM begrenzt ist
- Wenn ein Warp auf das Ergebnis eines lang laufenden Befehls wartet, setzt der SM diesen Warp in den Wartezustand und führt einen anderen Warp aus, der nicht warten muss
- Da jeder Thread jedes Warps über seinen eigenen Registersatz verfügt, entsteht beim Wechsel zwischen Warps kein zusätzlicher Overhead
- Prozess-Kontextwechsel auf CPUs sind teuer, weil Register in den Hauptspeicher gespeichert und der Zustand eines anderen Prozesses wiederhergestellt werden muss
-
Ergebnisdaten vom Device zum Host kopieren
- Sobald die Ausführung aller Threads des Kernels beendet ist, werden die Ergebnisse zurück in den Host Memory kopiert
Ressourcenaufteilung und Occupancy
- Die Nutzung von GPU-Ressourcen wird mit der Kennzahl Occupancy gemessen
- Occupancy ist das Verhältnis der einem SM zugewiesenen Warps zur maximalen Anzahl von Warps, die dieser SM unterstützen kann
- Für maximalen Durchsatz ist 100 % Occupancy wünschenswert, wegen verschiedener Einschränkungen aber nicht immer erreichbar
- Ein SM besitzt eine feste Menge an Ausführungsressourcen wie Register, Shared Memory, Thread-Block-Slots und Thread-Slots
- Diese Ressourcen werden je nach Anforderungen der Threads und Grenzen der GPU dynamisch aufgeteilt
- Beispiel Nvidia H100
- Jeder SM kann 32 Blocks, 64 Warps, also 2048 Threads verarbeiten
- Pro Block werden maximal 1024 Threads unterstützt
- Wird mit einer Blockgröße von 1024 Threads ausgeführt, werden die 2048 Thread-Slots auf 2 Blocks aufgeteilt
- Dynamische Aufteilung kann Rechenressourcen effizienter nutzen als feste Aufteilung
- Bei fester Aufteilung erhält jeder Thread Block eine feste Menge an Ausführungsressourcen
- In manchen Fällen bekommen Threads mehr Ressourcen zugewiesen als nötig, was zu Ressourcenverschwendung und geringerem Durchsatz führen kann
- Beispiele für niedrigere Occupancy
- Wenn die Blockgröße auf 32 Threads gesetzt ist und insgesamt 2048 Threads benötigt werden, entstehen 64 Blocks
- Da jeder SM jedoch nur 32 Blocks gleichzeitig verarbeiten kann, laufen tatsächlich nur 1024 Threads und die Occupancy beträgt 50 %
- Wenn pro SM 65.536 Register vorhanden sind, darf bei 2048 gleichzeitig laufenden Threads jeder Thread höchstens 32 Register verwenden
- Benötigt ein Kernel 64 Register pro Thread, können pro SM nur 1024 Threads laufen, sodass die Occupancy erneut 50 % beträgt
- Niedrige Occupancy verhindert, dass Latenz ausreichend verborgen wird, und kann auch den Rechendurchsatz senken, der nötig ist, um den maximalen Hardwaredurchsatz zu erreichen
- Um effiziente GPU-Kernel zu schreiben, müssen Ressourcen sorgfältig verteilt werden, damit hohe Occupancy erhalten bleibt und Latenz reduziert wird
- Viele Register zu verwenden kann den Code selbst schneller machen, aber die Occupancy senken; daher ist ein ausgewogenes Optimieren wichtig
Weitere Ressourcen
- Programming Massively Parallel Processors: Die 4. Auflage ist das aktuellste Referenzwerk, ältere Auflagen sind ebenfalls nutzbar
- Programming Massively Parallel Processors: Online-Vorlesung von Prof. Hwu
- Nvidia’s CUDA C++ Programming Guide
- How GPU Computing Works
- GPU Programming: When, Why and How?
1 Kommentare
Hacker-News-Kommentare
Jemand hat wegen dieses Beitrags eine Beschwerde-Mail geschickt: https://twitter.com/abhi9u/status/1715753871564476597
Das ist ein Verstoß gegen die HN-Regeln. Tatsächlich ist es der einzige Punkt, der so wichtig ist, dass er sowohl in den Site Guidelines als auch in den FAQ steht, und HN-Nutzer reagieren auf dieses Thema sehr empfindlich.
F: Darf ich andere bitten, meinen Beitrag hochzuvoten?
A: Nein. Nutzer sollen abstimmen, wenn sie etwas intellektuell interessant finden, nicht weil jemand Inhalte hat, die er bewerben möchte. Wenn du gegen diese Regel verstößt, können Beitrag, Account oder Site mit Penalties belegt oder gesperrt werden; lass es also.
https://news.ycombinator.com/newsfaq.html
Bitte nicht um Upvotes, Kommentare oder Einreichungen. Nutzer sollen abstimmen und kommentieren, wenn sie etwas, dem sie selbst begegnet sind, persönlich interessant finden – nicht zu Werbezwecken.
https://news.ycombinator.com/newsguidelines.html
Jetzt weiß ich es und werde es nicht wieder tun.
Ich war überrascht, dass im Abschnitt „Daten vom Host auf das Gerät kopieren“ asynchrone Kopien fehlen. Wenn man eine GPU maximal ausnutzen will, sollte sie nicht untätig sein, während Daten zwischen Host und GPU kopiert werden.
Viele Frameworks bieten Mechanismen zum Planen asynchroner Kopien, die parallel zu asynchron eingereichten Jobs laufen können. Der Artikel selbst ist eher eine GPU-Einführung, aber in der realen GPU-Programmierung gibt es darüber hinaus allerlei Tricks und Techniken, um teure GPUs wirklich auszureizen. Wie bei den meisten Optimierungen heutzutage gibt es viele versteckte Klippen und Nichtlinearitäten, daher sind Profiling-Tools eine große Hilfe.
Nutzt man allerdings eine GPU mit vielen FP64-Einheiten, kann es deutlich schneller werden. Normalerweise sind das keine Gaming-GPUs, aber wenn eine 4060 einfach vorhanden ist, liegt ihre FP64-Leistung bei etwa 300 GFLOPS und damit wahrscheinlich über der einer CPU. Moderne CPUs sind in diesem Bereich ebenfalls stark und können pro Kern mehrere FP64-Operationen pro Takt ausgeben.
Der erste Satz „Die meisten Programmierer verstehen CPUs sehr gut“ ist so offensichtlich unwahr, dass es schwerfällt, den Rest ernst zu nehmen – auch wenn der Artikel vielleicht großartig ist.
Ich habe an der Uni aus Spaß einen Philosophiekurs besucht und dort gelernt, eine Aussage nicht sofort zu verwerfen, sondern sie in eine bessere Form umzulesen. Inzwischen übersetzt mein Gehirn überzogene Verallgemeinerungen oder offenkundige Unwahrheiten automatisch in vernünftige, nahe an der Wahrheit liegende Aussagen. Während sich die Argumentation entfaltet, kann ich die Ideen rekonstruieren und den gesamten Text als logisch konsistent bewerten.
Dadurch bleiben selbst beim Lesen schlechter Texte neue wahre oder falsche Prämissen und Behauptungen zu Themen hängen, die mich interessieren, und mein geistiger Horizont erweitert sich entsprechend.
Ich habe an der Uni die Grundlagen der CPU-Architektur gelernt, kenne die Landschaft insgesamt sehr rudimentär und bekomme gelegentlich begrenzte Updates zu meinem Wissen, aber das würde ich nicht „tiefes Verständnis“ nennen. Eher passt „ein grundlegendes Verständnis dafür, wie CPUs funktionieren, entworfen und genutzt werden“.
Wenn man in Assembly versiert ist, könnte man vielleicht sagen, dass man auf Low-Level-Ebene „tief versteht“, wie man CPUs nutzt, aber selbst das klingt etwas übertrieben. Es ist auch etwas anderes, als Experte für CPU/GPU-Design zu sein.
Daher stimme ich zu. Trotzdem ist der Artikel interessant, besonders die Diagramme sind gut.
Bei „Register, die einem laufenden Thread zugewiesen sind, sind exklusiv für diesen Thread, sodass andere Threads sie nicht lesen oder schreiben können“ gibt es Ausnahmen.
Wave Intrinsics in HLSL und ähnliche Funktionen in CUDA können Register anderer Threads innerhalb der aktuellen Wavefront lesen. Außerdem wäre im Abschnitt zur Speicherarchitektur erwähnenswert, dass Caches zwar keine Kohärenz zwischen Threads innerhalb desselben Dispatch/Grid garantieren, es aber spezielle, chipweit globale Funktionsblöcke gibt, die atomare Operationen auf globalem Speicher implementieren.
SIMD-Programmierung ist wirklich ruppig.
Du willst für jedes Pixel auf dem Bildschirm eine Berechnung ausführen? Kein Problem.
Du willst eine Verzweigungsbedingung einbauen? Autsch.
Warum nennen wir es immer noch GPU? PPU (Parallel Processing Unit) klingt nach einem besseren Namen.
Bei drone und quad-copter ist es ähnlich.
Großartiger Artikel. Und GPUs sind in dem, was sie tun, weiter entwickelt und leistungsfähiger als alles andere, was mir einfällt.
Aber SIMD würde ich in die Kategorie „nicht unbedingt nötig“ einordnen, sobald man andere, flexiblere Paradigmen kennengelernt hat. Ich bevorzuge MIMD und Cluster/Transputer, die um die 2000er herum verschwunden zu sein scheinen. Der heutige Zustand verlangt von Entwicklern, Daten selbst zu verschieben, Shader unter willkürlichen Beschränkungen dafür zu schreiben, auf wie viele Speicherstellen gleichzeitig zugegriffen werden kann, Arbeit durch getrennte Sprachen für GPU/CPU zu duplizieren, zu wissen, welche Hardware es für Funktionen wie Raytracing gibt, und sich an stark meinungsgetriebene Frameworks wie OpenGL/Metal/Vulkan zu binden. GPUs sind ein Seitenzweig, der mich niemals dorthin bringen kann, wo ich hinwill; die letzten 25 Jahre fühlten sich daher an, als lebte man in der falschen Zeitlinie.
Grob gesagt ist eine skalierbare Allzweck-CPU unter den Einschränkungen nach dem Ende von Moores Gesetz ein Multicore-System mit lokalem Speicher, das Daten über Copy-on-Write-content-adressierbaren Speicher oder andere Caching-Verfahren teilt und einen einzigen, einheitlichen Adressraum bereitstellt, damit Nutzer in einer Desktop-Computing-Umgebung alle Arten des Rechnens frei erkunden können. Es verwendet eine Standard-Assemblersprache, wird aber normalerweise in funktionalen Programmiersprachen wie Erlang/Go, Octave/MATLAB und idealerweise Julia programmiert. 3D-Rendering- und AI-Bibliotheken sind Schichten darüber, nicht die grundlegenden Elemente.
Interessanterweise sind GPUs ungefähr bei der Multicore-Konfiguration angekommen, die ich meine, aber die Treiber trennen die Nutzer von dem Bare-Metal-Zugriff, der für allgemeines MIMD nötig wäre. Ich dachte, FPGAs seien der einzige Weg, die GPU-Dominanz zu brechen, aber vielleicht gibt es auch die Chance, Treiber zu schreiben, die GPU-Hardware wie MIMD mit gemeinsamem Speicher aussehen lassen. Ich weiß nicht, wie gut GPU-Kerne Integer-Operationen verarbeiten, aber man könnte es wohl über den 32-Bit-Integer-Teil von 64-Bit-Gleitkommazahlen annähern. Durch solche Kompromisse könnte eine MIMD-Maschine zwar 10- bis 100-mal langsamer sein als eine GPU, aber 10- bis 100-mal schneller als eine CPU. Gleichzeitig wäre sie skalierbar, ohne sich übermäßig auf große Caches und schnelle Busse zu verlassen, die CPUs seit etwa 2007 ausgebremst haben, als der Mobilmarkt die Führung übernahm und Preis sowie Energieeffizienz wichtiger wurden als Leistung. MIMD-Maschinen ließen sich clustern und ohne Codeänderungen auch zu verteilten Rechennetzen wie SETI@home ausbauen. Um ein Gefühl dafür zu bekommen, wie viel Macht das normalen Nutzern geben würde: Es ist ungefähr wie BitTorrent gegenüber FTP für Berechnungen, nicht für Daten.
Ich verstehe nicht so recht, wie sich die Apple-Silicon-Architektur von NVIDIA unterscheidet.
Wenn man den Satz liest: „Die Nvidia H100 GPU hat 132 SMs, 64 Kerne pro SM, also insgesamt 8448 Kerne“, dann sind 8448 Kerne definitiv beeindruckend. Aber der Apple M2 Ultra hat nur 76 Kerne?
Wie kann die NVIDIA H100 GPU mehr als 110-mal so viele Kerne haben? Sie ist offensichtlich nicht 110-mal schneller als der M2 Ultra – was passiert hier?
Siehe dieses Diagramm im NVIDIA-Blog: https://developer-blogs.nvidia.com/wp-content/uploads/2021/g...
(https://developer.nvidia.com/blog/nvidia-ampere-architecture...)
Natürlich kann man das Gefühl haben, es gebe eine Rechtfertigung, sie „Threads“ zu nennen, weil jede Lane einen eigenen Program Counter unterstützt; am Ende zählen aber Geschwindigkeit und Durchsatz der ALUs.
Jetzt verstehe ich, warum Machine Learning bei der Präzision Gleitkommazahlen verwendet. Es war keine Wahl, sondern weil Grafik-Code so arbeitet
Ein weiteres Puzzleteil der Frage „Warum ist Machine Learning so ineffizient?“
Ich frage mich, wie groß der Overhead durch Speicherkopien in der Praxis ist. Wenn es wie üblich funktioniert, dürfte er ziemlich brutal sein. Man lagert ja sogar die TCP-Verarbeitung an Hardware aus, um genau das zu vermeiden. Hier gibt es zwar viel mehr Daten, aber sie werden auch in größeren Blöcken verarbeitet
Das heißt: Das Kopieren eines Mini-Batches aus Gleitkomma-Bildern ist immer noch schnell genug. Die Gradienten-/SGD-Iterationen sind langsam und rechnerisch sehr aufwendig. Selbst bei gemischter Präzision ist das so
Bei flachen Netzwerken kann es von Vorteil sein, nur die ursprünglichen komprimierten Daten in den GPU-Speicher zu kopieren und Dekomprimierung usw. auf der GPU zu erledigen. Dass moderne GPUs PCIe 5 aber noch nicht übernommen haben, liegt daran, dass rohe Rechenleistung wichtiger ist
Schließlich hatten auch Tensor Cores großen Einfluss, und je nach Netzwerk können sie so schnell sein, dass die Auslastung sehr niedrig wird
Auch die Mathematik des Trainings nimmt an, dass Zahlen kontinuierlich sind
Allerdings habe ich mich gefragt, warum CPU-basierte LLMs Quantisierung verwenden. Soweit ich es verstehe, ist das ein Prozess, bei dem die Präzision der Gewichte reduziert wird, um weniger Speicher zu verbrauchen
Ob mangelnde Präzision einen Unterschied macht, ist unklar. Falls ja, warum verwendet man dann überhaupt Gleitkommazahlen? Wenn Präzision nicht wichtig ist, sorgt zusätzliche Präzision nur ohne echten Grund für höheren Ressourcenverbrauch, vermutlich sogar um mehrere Größenordnungen mehr als nötig
Dieses Feld wurde nicht von Leuten begonnen, die Performance verstanden haben. Sie haben mit Tools etwas gebaut, aber ohne ein „Warum“. Sie haben es so gemacht, weil die Tools so funktionieren
Warum das wichtig ist: Selbst auf einer normalen CPU kann eine Art, auf Daten zuzugreifen, um mehrere Größenordnungen schneller sein als eine andere, aber man muss das wissen. Will man die Kosten von LLMs nicht um mehrere Größenordnungen senken?
Sehenswert sind auch dieser Vortrag und die Folien von vor ein paar Jahren zu den kniffligen Seiten von CPUs und GPUs
Alexander Titov — Know your hardware: CPU memory hierarchy https://youtu.be/QOJ2hsop6hM
https://github.com/alexander-titov/public/blob/master/confer...
Know Your Hardware - CPU Memory Hierarchy -- Alexander Titov -- C%2B%2B Moscow Meetup March 2019.pdf
https://github.com/alexander-titov/public/blob/master/confer...
GPGPU - what it is and why you should care -- Alexander Titov -- CoreHard 2019.pdf