85.30 GFLOPS Single-Core FP32 Matrix Multiplication on AMD Zen 3: A Systematic Study of Cache Blocking, Register Blocking, FMA Chaining, and On-the-Fly Packing
Diese Arbeit präsentiert eine systematische Optimierungsstudie zur AMD Zen 3-Mikroarchitektur, die durch die Evaluierung von 28 distinkten Konfigurationen aus Cache/Register-Blocking, FMA-Chaining und On-the-fly-Packing eine Leistung von 85,30 GFLOPS bei der Single-Core-FP32-Matrixmultiplikation erzielt und dabei ein Champion-Design identifiziert, das 63,5 % der theoretischen Spitzenleistung erreicht, während es gleichzeitig ein prädiktives Modell für zukünftige Optimierungen einführt.
Originalarbeit lizenziert unter CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Dies ist eine KI-generierte Erklärung des untenstehenden Papers. Sie wurde nicht von den Autoren verfasst oder gebilligt. Für technische Genauigkeit konsultieren Sie das Originalpaper. Vollständigen Haftungsausschluss lesen
Stellen Sie sich vor, Sie versuchen, einen riesigen Haufen Sand (Daten) von einer Seite eines riesigen Lagerhauses auf die andere zu bewegen, aber Sie müssen dies mit einem winzigen, superschnellen Roboterarm (dem Prozessor) tun. Das Ziel ist es, den Sand so schnell wie möglich mit einer speziellen Formel (Matrixmultiplikation) zu vermischen. Dieses Papier ist ein detailliertes Logbuch eines Forschers namens Lucas, der versucht, diesen Roboterarm auf einem spezifischen Typ von Computerchip, dem AMD Zen 3, so schnell wie menschlich möglich zu machen.
Das große Ziel: Wie schnell ist schnell?
Der Roboterarm hat eine theoretische Höchstgeschwindigkeit von 134,4 GFLOPS (das sind 134,4 Milliarden mathematische Operationen pro Sekunde). Denken Sie an dies als das Tempolimit auf einer Autobahn. Lucas wollte sehen, wie nah er an dieses Tempolimit herankommt, ohne ein brandneues Auto zu bauen, sondern nur indem er den Motor abstimmte.
Nach dem Testen von 28 verschiedenen Fahrstrategien fand er ein „Champion“-Setup (genannt MX24), das 85,30 GFLOPS erreichte. Das sind etwa 63,5 % der maximalen Geschwindigkeit. Es ist keine perfekten 100 %, aber es ist ein riesiger Sprung vom Startblock, der bei einer langsamen, tollpatschigen Methode lag, die nur 1,51 GFLOPS lief. Tatsächlich war seine beste Methode 57 Mal schneller als die einfache, nicht optimierte Version.
Die Gewinnstrategie: Der „4-Reihen, Kette-4“-Tanz
Um diese Geschwindigkeit zu erreichen, musste Lucas herausfinden, wie er den Sand und die Bewegungen des Roboters organisiert. Hier sind die Schlüsselzüge, die er entdeckte:
1. Der „On-the-Fly“-Pack-Trick
Stellen Sie sich vor, der Sand ist in einem Gitter gespeichert, bei dem man diagonal laufen muss, um das nächste Sandkorn zu greifen. Das ist langsam und ermüdend. Lucas fand heraus, dass das Kopieren eines kleinen Stücks des Sandes in eine ordentliche, gerade Linie kurz bevor der Roboter ihn braucht (genannt On-the-Fly-Packing), der magische Zug war. Es ist, als hätte man einen Helfer, der vorausläuft und die Steine in einer perfekten Reihe stapelt, damit der Roboter sie einfach nacheinander greifen kann, ohne zu stolpern. Dies schlug die alte Methode, sie einfach so zu greifen, wie sie waren, und war sogar besser als das gesamte Lagerhaus im Voraus umzuordnen.
2. Das „4-Reihen“-Stapeln
Der Roboter hat eine begrenzte Anzahl an Händen (Registern), um Sand zu halten, während er arbeitet. Lucas probierte aus, 2 Reihen Sand, dann 4, dann 8 zu halten.
- 2 Reihen: Zu wenig. Der Roboter musste zu oft anhalten, um neuen Sand zu holen.
- 8 Reihen: Zu viel! Die Hände des Roboters waren so voll, dass er Sand auf den Boden fallen ließ (Speicher) und ihn ständig wieder aufheben musste. Das war ein Desaster.
- 4 Reihen: Der „Sweet Spot“. Obwohl der Roboter ein paar Körner auf den Boden fallen lassen und wieder aufheben musste (ein Prozess namens „Spilling“), war die zusätzliche Arbeit es wert, weil er mehr Sand gleichzeitig verarbeiten konnte. Diese einzige Änderung machte den Roboter 5-mal schneller (59 % schneller) als die 2-Reihen-Methode.
3. Der „Kette-4“-Rhythmus
Der Arm des Roboters benötigt 4 Sekunden (Zyklen), um eine einzige mathematische Bewegung abzuschließen, bevor er mit demselben Stück Sand mit der nächsten beginnen kann. Wenn der Roboter nur eine Bewegung macht und dann wartet, würde er 3 Sekunden lang untätig sein.
Lucas fand heraus, dass er den Roboterarm ständig in Bewegung halten konnte, indem er 4 verschiedene Sandhaufen in seinen Händen hielt und sie in einer Schleife abarbeitete (Kette-4). Während ein Sandhaufen „kochte“, arbeitete er an den anderen. Dies passte perfekt zu der 4-sekündigen Kochzeit des Roboters und hielt den Motor auf voller Geschwindigkeit.
Was nicht funktionierte (Die „Nicht-machen“-Liste)
Manchmal ist das, was man denkt, dass funktionieren sollte, eigentlich schlechter. Lucas testete einige populäre Ideen und fand heraus, dass sie für diesen speziellen Roboter schrecklich waren:
- Der „Pre-fetch“-Fehler: Menschen sagen Robotern oft, sie sollen „voraussehen“ und das nächste Sandkorn greifen, bevor sie es brauchen. Lucas probierte dies aus, aber die eingebauten Augen des Roboters waren bereits so gut darin, das Muster zu erkennen, dass die zusätzlichen „Vorausschau“-Befehle nur im Weg standen. Dies verlangsamte den Robot um etwa 8 %.
- Der „Non-Temporal“-Dump: Es gibt einen Trick, bei dem man dem Roboter sagt, er solle den Sand direkt auf den Boden entleeren, ohne ihn vorher in einen Behälter zu legen. Das funktioniert großartig, wenn man nur Müll entsorgt. Aber hier muss der Roboter den Sand mischen, was bedeutet, dass er ihn wieder aufheben muss. Das direkte Entleeren führte dazu, dass der Roboter über seine eigenen Füße stolperte, was seine Geschwindigkeit auf erbärmliche 1,24 GFLOPS abstürzen ließ.
- Die „8-Reihen“-Überlastung: Wie bereits erwähnt, führte der Versuch, 8 Reihen Sand zu halten, dazu, dass der Roboter so viel Sand fallen ließ, dass er mehr Zeit damit verbrachte, ihn aufzuheben, als sich zu bewegen.
Wie sicher sind wir uns?
Das Papier ist sehr zuversichtlich bei diesen Zahlen, da sie gemessen und nicht nur geschätzt wurden. Lucas ließ den Code 15 Mal für jede Strategie laufen, warf die schnellsten und langsamsten Durchläufe heraus (um seltsame Computerfehler zu vermeiden) und bildete den Durchschnitt der restlichen Durchläufe. Er überprüfte die Mathematik auch gegen eine einfache, langsame Version, um sicherzustellen, dass die schnelle Version nicht geschummelt hat.
Er baute sogar ein mathematisches „Pre-Filter“-Modell – eine Art Kristallkugel – um vorherzusagen, wie schnell eine Strategie sein würde, bevor er sie tatsächlich ausführte. Diese Kristallkugel war ziemlich gut und lag bei den meisten Strategien innerhalb von 11,3 % der realen Geschwindigkeit. Sie war eher konservativ und sagte voraus, dass die beste Strategie 78,1 GFLOps erreichen würde, aber als sie die Strategie tatsächlich ausführten, erreichte sie 85,30 GFLOPS.
Das Faznehmen
Dieses Papier beweist, dass man kein Zauberer sein muss, der Code in „Assembly-Sprache“ (der Muttersprache des Roboters) schreibt, um eine unglaubliche Geschwindigkeit zu erreichen. Indem man Standardwerkzeuge (C++ Intrinsics) verwendet und die „Tanzschritte“ (Blocking, Chaining und Packing) sorgfältig abstimmt, kann man seinen Computer auf 63,5 % seiner theoretischen Höchstgeschwindigkeit bringen.
Die wichtigste Lektion? Rate nicht. Was für einen Typ von Roboter (oder Computerchip) funktioniert, kann bei einem anderen alles kaputt machen. Lucas testete 28 verschiedene Kombinationen, um diejenige zu finden, die funktionierte, was zeigt, dass manchmal die „offensichtlichen“ Tricks (wie das Voraussehen oder das direkte Entleeren) eigentlich die falschen Züge sind.
Ertrinken Sie in Arbeiten in Ihrem Fachgebiet?
Erhalten Sie tägliche Digests der neuesten Arbeiten passend zu Ihren Forschungsbegriffen — mit technischen Zusammenfassungen, in Ihrer Sprache.