Originaltitel: Glue- und Coprozessor-Architekturen
Autor: Vitalik, Gründer von Ethereum; Compiler: Deng Tong, Golden Finance
Besonderer Dank geht an Justin Drake, Georgios Konstantopoulos, Andrej Karpathy, Michael Gao, Tarun Chitra und verschiedene Flashbots-Mitwirkende für ihr Feedback und ihre Kommentare.
Wenn Sie ressourcenintensive Berechnungen, die in der modernen Welt stattfinden, mit mäßiger Detailliertheit analysieren, werden Sie immer wieder feststellen, dass die Berechnung in zwei Teile unterteilt werden kann:
Eine relativ kleine Menge komplexer, aber nicht rechenintensiver „Geschäftslogik“;
Viel intensive, aber sehr strukturierte „teure Arbeit“.
Diese beiden Formen des Rechnens werden am besten auf unterschiedliche Weise gehandhabt: Erstere, deren Architektur möglicherweise weniger effizient ist, aber sehr allgemein sein muss, und letztere, deren Architektur möglicherweise weniger allgemein ist, aber sehr effizient sein muss.
Welche Beispiele für diesen unterschiedlichen Ansatz gibt es in der Praxis?
Schauen wir uns zunächst die Umgebung an, mit der ich am besten vertraut bin: die Ethereum Virtual Machine (EVM). Hier ist der Geth-Debug-Trace einer kürzlich von mir durchgeführten Ethereum-Transaktion: Aktualisierung des IPFS-Hash meines Blogs auf ENS. Die Transaktion verbrauchte insgesamt 46924 Gas und kann wie folgt klassifiziert werden:
Grundkosten: 21.000
Anrufdaten: 1.556
EVM-Ausführung: 24.368
SLOAD-Opcode: 6.400
SSTORE-Opcode: 10.100
LOG-Opcode: 2.149
Andere: 6.719
EVM-Trace von ENS-Hash-Updates. Die vorletzte Spalte ist der Gasverbrauch.
Die Moral der Geschichte lautet: Der Großteil der Ausführung (etwa 73 %, wenn man nur EVM betrachtet, etwa 85 %, wenn man den Grundkostenanteil für die Berechnung mit einbezieht) konzentriert sich auf eine sehr kleine Anzahl strukturierter teurer Vorgänge: Speicherlesevorgänge und schreibt, protokolliert und verschlüsselt (die Grundkosten umfassen 3000 für die Überprüfung der Zahlungssignatur, EVM umfasst außerdem 272 für das Zahlungs-Hashing). Der Rest der Ausführung ist „Geschäftslogik“: Austauschen der Anrufdatenbits, um die ID des Datensatzes, den ich festlegen möchte, und den Hash, auf den ich ihn festlege, usw. zu extrahieren. Bei einer Token-Übertragung würde dies das Addieren und Subtrahieren von Guthaben umfassen, bei fortgeschritteneren Anwendungen könnte dies Rotationen usw. umfassen.
Im EVM werden diese beiden Ausführungsarten unterschiedlich gehandhabt. Geschäftslogik auf hoher Ebene wird in einer höheren Sprache geschrieben, normalerweise Solidity, die in die EVM kompiliert wird. Die teure Arbeit wird immer noch durch EVM-Opcodes (SLOAD usw.) ausgelöst, aber mehr als 99 % der tatsächlichen Berechnungen werden in dedizierten Modulen durchgeführt, die direkt im Client-Code (oder sogar in Bibliotheken) geschrieben sind.
Um unser Verständnis dieses Musters zu verbessern, untersuchen wir es in einem anderen Kontext: KI-Code, der in Python mit Torch geschrieben wurde.
Vorwärtsdurchlauf eines Blocks des Transformatormodells
Was sehen wir hier? Wir haben relativ wenig in Python geschriebene „Geschäftslogik“ gesehen, die die Struktur der ausgeführten Vorgänge beschreibt. In einer realen Anwendung gibt es eine andere Art von Geschäftslogik, die Details bestimmt, z. B. wie die Eingabe abgerufen wird und was mit der Ausgabe geschehen soll. Wenn wir jedoch einen Drilldown in jede einzelne Operation selbst durchführen (die einzelnen Schritte in self.norm, Torch.cat, +, *, self.attn...), sehen wir vektorisierte Berechnungen: Dieselben Operationen werden massiv im Parallelwert berechnet . Ähnlich wie im ersten Beispiel wird ein kleiner Teil der Berechnungen für die Geschäftslogik verwendet, und der Großteil der Berechnungen wird zur Durchführung großer strukturierter Matrix- und Vektoroperationen verwendet – tatsächlich handelt es sich bei den meisten davon nur um Matrixmultiplikationen.
Genau wie im EVM-Beispiel werden diese beiden Arten von Arbeiten auf zwei unterschiedliche Arten gehandhabt. High-Level-Geschäftslogikcode wird in Python geschrieben, einer äußerst vielseitigen und flexiblen Sprache, aber auch sehr langsam, und wir nehmen die Ineffizienz einfach in Kauf, da sie nur einen kleinen Bruchteil der gesamten Rechenkosten ausmacht. In der Zwischenzeit werden intensive Vorgänge in hochoptimiertem Code geschrieben, häufig CUDA-Code, der auf der GPU ausgeführt wird. Zunehmend sehen wir sogar, dass LLM-Inferenzen auf ASICs durchgeführt werden.
Moderne programmierbare Kryptographie wie SNARKs folgt wiederum auf zwei Ebenen einem ähnlichen Muster. Erstens kann der Prüfer in einer Hochsprache geschrieben werden, wobei die Hauptarbeit über vektorisierte Operationen erfolgt, wie im obigen KI-Beispiel. Der kreisförmige STARK-Code, den ich hier habe, demonstriert dies. Zweitens können die Programme selbst, die innerhalb der Kryptographie ausgeführt werden, so geschrieben werden, dass zwischen allgemeiner Geschäftslogik und hochstrukturierter, kostspieliger Arbeit unterschieden wird.
Um zu verstehen, wie das funktioniert, können wir uns einen der neuesten Trends von STARK ansehen. Um vielseitig und benutzerfreundlich zu sein, entwickeln Teams zunehmend STARK-Prüfer für weit verbreitete minimale virtuelle Maschinen wie RISC-V. Jedes Programm, dessen Ausführung nachgewiesen werden muss, kann nach RISC-V kompiliert werden, und der Prüfer kann dann die RISC-V-Ausführung dieses Codes nachweisen.
Diagramm aus der RiscZero-Dokumentation
Das ist sehr praktisch: Wir müssen die Beweislogik nur einmal schreiben und von da an kann jedes Programm, das einen Beweis benötigt, in jeder „traditionellen“ Programmiersprache geschrieben werden (z. B. unterstützt RiskZero Rust). Es gibt jedoch ein Problem: Dieser Ansatz verursacht einen hohen Overhead. Programmierbare Verschlüsselung ist bereits unerschwinglich teuer; der zusätzliche Aufwand für die Ausführung von Code im RISC-V-Interpreter ist zu hoch. Deshalb haben sich die Entwickler einen Trick ausgedacht: Identifizieren Sie die spezifischen teuren Vorgänge, die den Großteil der Berechnung ausmachen (normalerweise Hashes und Signaturen), und erstellen Sie dann spezielle Module, um diese Vorgänge sehr effizient zu beweisen. Dann kombinieren Sie einfach ein ineffizientes, aber allgemeines RISC-V-Beweissystem mit einem effizienten, aber spezialisierten Beweissystem und erhalten das Beste aus beiden Welten.
Andere programmierbare Verschlüsselungen als ZK-SNARK, wie z. B. Multi-Party Computation (MPC) und Fully Homomorphic Encryption (FHE), können mit ähnlichen Methoden optimiert werden.
Wie ist das Phänomen insgesamt?
Modernes Computing folgt zunehmend dem, was ich „Glue“- und Coprozessor-Architekturen nenne: Es gibt eine zentrale „Glue“-Komponente, die äußerst vielseitig, aber ineffizient ist und für die Ausführung von Aufgaben zwischen einer oder mehreren Coprozessorkomponenten verantwortlich ist. Diese Coprozessorkomponenten weisen eine geringe Allgemeingültigkeit, aber eine hohe Effizienz bei der Übertragung auf Daten zwischen ihnen.
Dies ist eine Vereinfachung: In der Praxis weist die Kompromisskurve zwischen Effizienz und Vielseitigkeit fast immer mehr als zwei Ebenen auf. GPUs und andere Chips, in der Branche oft als „Coprozessoren“ bezeichnet, sind weniger vielseitig als CPUs, aber vielseitiger als ASICs. Der Spezialisierungskompromiss ist komplex und hängt von Vorhersagen und der Intuition darüber ab, welche Teile des Algorithmus in fünf Jahren gleich bleiben und welche Teile sich in sechs Monaten ändern werden. In der ZK-Proof-Architektur sehen wir oft ähnliche mehrere Spezialisierungsebenen. Für umfassende mentale Modelle reicht es jedoch aus, zwei Ebenen zu berücksichtigen. Ähnliche Situationen gibt es in vielen Bereichen der Informatik:
Aus den obigen Beispielen geht hervor, dass es sicherlich ein Naturgesetz zu sein scheint, dass Berechnungen auf diese Weise aufgeteilt werden können. Tatsächlich gibt es Beispiele für eine jahrzehntelange Computerspezialisierung. Allerdings denke ich, dass diese Trennung zunimmt. Ich denke, dafür gibt es einen Grund:
Wir sind erst vor kurzem an die Grenzen der CPU-Taktgeschwindigkeitsverbesserungen gestoßen, sodass weitere Fortschritte nur durch Parallelisierung erzielt werden können. Parallelisierung lässt sich jedoch nur schwer nachvollziehen. Daher ist es für Entwickler oft praktischer, die Überlegungen sequentiell fortzusetzen und die Parallelisierung im Backend geschehen zu lassen, verpackt in spezialisierten Modulen, die für bestimmte Vorgänge entwickelt wurden.
Die Rechengeschwindigkeiten sind erst in letzter Zeit so hoch geworden, dass die Rechenkosten der Geschäftslogik wirklich vernachlässigbar geworden sind. In dieser Welt ist es auch sinnvoll, die VMs, auf denen die Geschäftslogik läuft, zu optimieren, um andere Ziele als die Recheneffizienz zu erreichen: Entwicklerfreundlichkeit, Vertrautheit, Sicherheit und andere ähnliche Ziele. In der Zwischenzeit können dedizierte „Coprozessor“-Module weiterhin auf Effizienz ausgelegt sein und ihre Sicherheit und Entwicklerfreundlichkeit aus ihrer relativ einfachen „Schnittstelle“ zum Klebstoff beziehen.
Es wird immer klarer, was die teuersten Operationen sind. Dies zeigt sich am deutlichsten in der Kryptographie, wo am wahrscheinlichsten bestimmte Arten teurer Operationen zum Einsatz kommen: modulare Arithmetik, lineare Kombinationen elliptischer Kurven (auch bekannt als multiskalare Multiplikation), schnelle Fourier-Transformationen und so weiter. Dies wird auch immer deutlicher in der künstlichen Intelligenz, wo die meisten Berechnungen seit mehr als zwei Jahrzehnten „hauptsächlich Matrixmultiplikationen“ waren (wenn auch mit unterschiedlichem Präzisionsgrad). Ähnliche Trends zeichnen sich auch in anderen Bereichen ab. Im (rechenintensiven) Rechnen gibt es weitaus weniger unbekannte Unbekannte als noch vor 20 Jahren.
was bedeutet das?
Ein wichtiger Punkt ist, dass Klebegeräte so optimiert werden sollten, dass sie gute Klebegeräte sind, und dass Coprozessoren so optimiert werden sollten, dass sie gute Coprozessoren sind. Wir können die Auswirkungen davon in mehreren Schlüsselbereichen untersuchen.
EVM
Eine virtuelle Blockchain-Maschine (z. B. EVM) muss nicht effizient, sondern nur vertraut sein. Allein durch das Hinzufügen der richtigen Coprozessoren (auch „Vorkompilierung“ genannt) können Berechnungen in einer ineffizienten VM tatsächlich genauso effizient sein wie Berechnungen in einer nativ effizienten VM. Beispielsweise ist der durch die 256-Bit-Register der EVM verursachte Overhead relativ gering, während die Vorteile der Vertrautheit der EVM und des bestehenden Entwickler-Ökosystems erheblich und dauerhaft sind. Entwicklungsteams, die das EVM optimieren, haben sogar festgestellt, dass mangelnde Parallelisierung oft kein großes Hindernis für die Skalierbarkeit darstellt.
Der beste Weg zur Verbesserung von EVM könnte darin bestehen, (i) bessere vorkompilierte oder spezialisierte Opcodes hinzuzufügen, beispielsweise könnte eine Kombination aus EVM-MAX und SIMD sinnvoll sein, und (ii) das Speicherlayout, beispielsweise von Verkle-Bäumen, zu verbessern. Die Änderung Als Nebeneffekt werden die Kosten für den Zugriff auf benachbarte Speicherplätze erheblich reduziert.
Speicheroptimierung im Ethereum-Verkle-Tree-Vorschlag, indem benachbarte Speicherschlüssel zusammengefügt und die Gaskosten angepasst werden, um dies widerzuspiegeln. Optimierungen wie diese, gepaart mit einer besseren Vorkompilierung, sind möglicherweise wichtiger als die Optimierung der EVM selbst.
Sicheres Computing und offene Hardware
Eine der Herausforderungen bei der Verbesserung der Sicherheit moderner Computer auf Hardwareebene ist deren übermäßig komplexe und proprietäre Natur: Chips sind auf Effizienz ausgelegt, was eine proprietäre Optimierung erfordert. Hintertüren sind leicht zu verbergen und es werden ständig Schwachstellen im Seitenkanal entdeckt.
Die Bemühungen streben weiterhin aus verschiedenen Blickwinkeln nach offeneren und sichereren Alternativen. Einige Computer werden zunehmend in vertrauenswürdigen Ausführungsumgebungen durchgeführt, auch auf den Telefonen der Benutzer, was die Sicherheit der Benutzer verbessert hat. Der Drang nach mehr Open-Source-Consumer-Hardware geht weiter, mit einigen jüngsten Erfolgen wie RISC-V-Laptops mit Ubuntu.
RISC-V-Laptop mit Debian
Allerdings bleibt die Effizienz ein Problem. Der Autor des oben verlinkten Artikels schreibt:
Neuere Open-Source-Chipdesigns wie RISC-V werden wahrscheinlich nicht mit der bereits vorhandenen und über Jahrzehnte verfeinerten Prozessortechnologie konkurrieren können. Fortschritt hat immer einen Ausgangspunkt.
Paranoidere Ideen wie dieser Entwurf, einen RISC-V-Computer auf einem FPGA zu bauen, sind mit einem größeren Aufwand verbunden. Was aber, wenn dieser Overhead aufgrund von Kleben und Coprozessor-Architektur eigentlich keine Rolle spielt? Wenn wir akzeptieren, dass offene und sichere Chips langsamer sind als proprietäre, verzichten wir bei Bedarf sogar auf gängige Optimierungen wie spekulative Ausführung und Verzweigungsvorhersage, versuchen aber, dies durch das Hinzufügen (falls erforderlich) proprietärer ASIC-Module zu kompensieren, die in den meisten Fällen verwendet werden bestimmte Arten von Berechnungen, was ist damit? Sensible Berechnungen können in einem „Master-Chip“ durchgeführt werden, der hinsichtlich Sicherheit, Open-Source-Design und Seitenkanalwiderstand optimiert wird. Intensivere Berechnungen (z. B. ZK-Beweise, KI) werden in ASIC-Modulen durchgeführt, die weniger Informationen über die durchgeführten Berechnungen kennen (möglicherweise durch kryptografisches Blinding in einigen Fällen sogar keine Informationen).
Kryptographie
Ein weiterer wichtiger Punkt ist, dass dies alles sehr optimistisch ist, was die Kryptographie betrifft, insbesondere die programmierbare Kryptographie, die sich zum Mainstream entwickelt. Wir haben einige hyperoptimierte Implementierungen bestimmter hochstrukturierter Berechnungen in SNARK, MPC und anderen Umgebungen gesehen: Einige Hash-Funktionen sind nur ein paar hundert Mal teurer als die direkte Ausführung der Berechnung, und künstliche Intelligenz (hauptsächlich Matrixmultiplikation) ist der Overhead ist auch sehr gering. Weitere Verbesserungen wie GKR könnten dieses Niveau weiter senken. Eine vollständig generische VM-Ausführung, insbesondere wenn sie in einem RISC-V-Interpreter ausgeführt wird, würde wahrscheinlich weiterhin etwa zehntausendmal mehr Overhead verursachen, aber aus den in diesem Artikel beschriebenen Gründen spielt dies keine Rolle: solange effiziente Spezialtechniken vorhanden sind verwendet bzw. Durch die Handhabung der rechenintensivsten Teile sind die Gesamtkosten kontrollierbar.
Vereinfachtes Diagramm von MPC, das der Matrixmultiplikation gewidmet ist, der größten Komponente bei der KI-Modellinferenz. Weitere Informationen finden Sie in diesem Artikel, unter anderem dazu, wie Sie Ihr Modell und Ihre Eingaben privat halten.
Eine Ausnahme von der Idee, dass „Klebeschichten nur vertraut und nicht effizient sein müssen“, ist die Latenz und in geringerem Maße die Datenbandbreite. Wenn die Berechnung Dutzende Male schwere Operationen an denselben Daten erfordert (wie in der Kryptographie und der künstlichen Intelligenz), können Verzögerungen, die durch ineffiziente Klebeschichten verursacht werden, zu einem großen Engpass in der Laufzeit werden. Daher gelten auch für Klebefugen Anforderungen an die Effizienz, wenngleich diese Anforderungen spezifischer sind.
abschließend
Insgesamt halte ich die oben genannten Trends aus mehreren Perspektiven für sehr positive Entwicklungen. Erstens ist es eine logische Möglichkeit, die Recheneffizienz zu maximieren und gleichzeitig entwicklerfreundlich zu bleiben, und die Möglichkeit, mehr von beidem zu bekommen, ist für alle gut. Insbesondere verbessert es unsere Fähigkeit, sensible und leistungsintensive Berechnungen (z. B. ZK-Beweise, LLM-Inferenz) lokal auf der Hardware des Benutzers auszuführen, indem es eine Spezialisierung auf der Clientseite für mehr Effizienz ermöglicht. Zweitens schafft es ein riesiges Zeitfenster, um sicherzustellen, dass das Streben nach Effizienz andere Werte nicht beeinträchtigt, insbesondere Sicherheit, Offenheit und Einfachheit: Seitenkanalsicherheit und Offenheit in der Computerhardware, reduzierte Schaltungskomplexität in ZK-SNARKs und Reduzierung Komplexität in virtuellen Maschinen. Historisch gesehen hat das Streben nach Effizienz dazu geführt, dass diese anderen Faktoren in den Hintergrund gerückt sind. Mit der Kleber- und Coprozessor-Architektur ist dies nicht mehr erforderlich. Ein Teil der Maschine optimiert die Effizienz, ein anderer Teil optimiert die Vielseitigkeit und andere Werte, und beide arbeiten zusammen.
Dieser Trend ist auch sehr gut für die Kryptographie, die selbst ein Paradebeispiel für „teures strukturiertes Computing“ ist, und dieser Trend beschleunigt diesen Trend. Dies bietet eine weitere Möglichkeit zur Verbesserung der Sicherheit. Auch in der Blockchain-Welt ist eine verbesserte Sicherheit möglich: Wir können uns weniger um die Optimierung der virtuellen Maschine kümmern und uns mehr auf die Optimierung der Vorkompilierung und anderer Funktionen konzentrieren, die mit der virtuellen Maschine koexistieren.
Drittens bietet dieser Trend Möglichkeiten für kleinere, neuere Akteure, sich zu beteiligen. Wenn die Datenverarbeitung weniger monolithisch und modularer wird, wird dies die Eintrittsbarriere deutlich senken. Selbst die Verwendung eines ASIC für eine Art von Computer kann möglicherweise einen Unterschied machen. Dies gilt auch im Bereich ZK-Beweise und EVM-Optimierung. Das Schreiben von Code mit nahezu modernster Effizienz wird einfacher und zugänglicher. Die Prüfung und formelle Verifizierung eines solchen Codes wird einfacher und zugänglicher. Da sich diese sehr unterschiedlichen Bereiche der Informatik schließlich in einigen gemeinsamen Mustern annähern, gibt es zwischen ihnen mehr Raum für Zusammenarbeit und Lernen.