1 Punkte von GN⁺ 2 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • WASTE ist eine in C geschriebene Inferenz-Engine, die das vollständige Open-Weights-Modell Kimi K3 mit 2,78 Billionen Parametern ohne Verkleinerung in einen 982-GiB-Container umwandelt und auf Consumer-Laptops ausführt
  • Nur der residente Trunk des Modells bleibt im Speicher; etwa 4 % der pro Token aktivierten Expertengewichte werden von NVMe gelesen, und der restliche RAM dient als größenbegrenzter Experten-Cache
  • Kimi K3 lässt sich bei 4K-Kontext mit mindestens 29,05 GB RAM öffnen, eine praktikable Konfiguration ist jedoch ein Budget von 46 GB auf einem MacBook Pro mit 64 GB, wo 0,45–0,62 Tok/s erreicht werden
  • Durch Überlappung von Experten-Lesevorgängen und Berechnung ergibt sich etwa ein 1,6-facher Gewinn; zudem läuft der Router der nächsten Schicht einen Residual-Schritt im Voraus, was die Cache-Trefferrate von 14 % auf 38 % erhöht, ohne die gesamte Lesemenge oder die Logits zu verändern
  • Sehr große Modelle lassen sich lokal ohne Internetverbindung, Token-Kosten oder externe Datenübertragung ausführen, allerdings sind internes NVMe und etwa 1 TB Speicherplatz nötig; bei einem RAM-Budget von mehr als 52 GB kann es durch OS-Paging sogar drastisch langsamer werden

Ziel und Aufbau von WASTE

  • WASTE (Weight-Aware Streaming Tensor Engine) ist eine einbettbare C-Inferenz-Engine ohne externe Runtime-Abhängigkeiten
    • Verwendet werden nur libwaste.a und die ausführbare Datei waste; außer libc und pthreads sind weder BLAS, CUDA, ONNX noch Python erforderlich
    • Python wird nur für die Modellkonvertierung und die Referenzprüfung gegen PyTorch verwendet und ist nicht Teil des Inferenzpfads
    • Die öffentliche API besteht aus 26 Funktionen und unterstützt das Öffnen von Modellen, das Setzen von RAM-Obergrenzen, Generierung, Speichern von Sessions und Beenden
  • Derzeit validiert wird das vollständige Modell Kimi K3 2.78T
    • Das veröffentlichte Original umfasst 1,42 TB, der konvertierte Container 982 GiB
    • Es handelt sich nicht um eine destillierte, beschnittene oder verkleinerte Version
    • Kimi-Linear 48B erreicht mit derselben Engine und demselben Format einen 19-GiB-Container, mindestens 1,87 GB RAM und 10,7 Tok/s
  • Der Projektname leitet sich vom Ziel ab, die Situation zu verringern, dass Modelle, die auf Hardware auf dem Schreibtisch laufen könnten, stattdessen in Cloud-Rechenzentren laufen und dabei sowohl Token-Kosten als auch Strom verbrauchen

Architektur des Disk-Streamings

  • Da K3 als Mixture-of-Experts-Modell pro Token nur etwa 4 % des Modells aktiviert, müssen inaktive Gewichte nicht im RAM resident bleiben, sondern nur bei Bedarf zugreifbar sein
  • Der .waste-Container besteht aus einem JSON-Manifest, einem residenten Trunk und schichtweisen Experten-Bänken
    • Jeder Experten-Datensatz ist auf 4 KiB ausgerichtet
    • Gate-, Up- und Down-Matrizen liegen direkt nebeneinander, sodass ein Experte mit genau einem pread gelesen wird
    • Der Page-Cache wird mit F_NOCACHE unter macOS, O_DIRECT unter Linux und FILE_FLAG_NO_BUFFERING unter Windows umgangen
  • Ohne Umgehung des Page-Cache können Test-Container, die kleiner als der RAM sind, im OS-Cache landen und Trefferraten erzeugen, die sich beim 982-GiB-Modell nicht reproduzieren lassen
  • Beim Lesen von Datensätzen werden Magic, Experten-ID und Offset-Bereich immer geprüft, damit abgeschnittene oder falsch zusammengefügte Bänke nicht mit falschen Gewichten antworten
    • Die crc32-Prüfung der Payload wird mit --verify aktiviert
    • Die Kosten der Prüfung liegen bei Kimi-Linear bei etwa 5 % und bei K3 bei etwa 1 %; standardmäßig ist sie deaktiviert
    • Für Container, die kopiert, heruntergeladen oder auf nicht vertrauenswürdigen Datenträgern gespeichert wurden, wird eine einmalige Verifikation empfohlen
    • Für Trunk und Codebook gibt es keine Checksummen

Read-Ahead und Router-Vorhersage

  • Sobald der Router einer Schicht 16 Experten-IDs bestimmt, wird jeder Lesevorgang in einem separaten Thread angefordert, und die Berechnung verarbeitet die eintreffenden Daten sofort
    • Die Überlappung von Lesen und Berechnung bringt bei K3 etwa 1,6× Verbesserung
    • Ausgeführte Arbeit und Cache-Statistiken sind vor und nach Aktivierung der Funktion identisch
  • Bevor der tatsächliche Hidden State der nächsten Schicht erzeugt wird, läuft der bereits residente nächste Router mit dem aktuellen Hidden State und lädt sechs Experten vorab
    • Diese um einen Residual-Schritt vorgezogene Vorhersage ist mit 92 % bei Rang 1 und 81 % für die Top 6 korrekt
    • Der tatsächliche Router bestimmt weiterhin die finalen Experten, daher bleibt die Ausgabe exakt gleich
    • Die Demand-Hit-Rate steigt von 14 % auf 38 %, während sich die insgesamt gelesenen Bytes nicht ändern
    • Mit WASTE_LOOKAHEAD=0 lässt sich das deaktivieren
  • Eine Implementierung derselben Technik für Prefill wurde wieder entfernt
    • Decode-Schichten belegen 16 Cache-Slots, Chunk-Schichten aber etwa 550
    • Vorab gelesene Datensätze wurden vor der Nutzung wieder verdrängt, wodurch die Lesemenge um 6,9 % stieg und die Laufzeit nicht sank

Quantisierung und Genauigkeit

  • Expertengewichte werden als residuale Vektorquantisierung in drei Stufen mit 256 Einträgen pro Codebook für 8-dimensionale Vektoren gespeichert und verwenden 3,00 Bit pro Gewicht
    • Anstatt die gesamte Matrix zu rekonstruieren, werden partielle Dot-Product-Tabellen aufgebaut, und jede Zeile wird mit drei Tabellen-Lookups und zwei Additionen verarbeitet
  • Der Trunk bleibt bei 4 Bit und 8 Bit
    • Da das Modell nur für quantisierungsbewusstes Training der Experten trainiert wurde, kollabiert die Ausgabe bei einem 3-Bit-Trunk
    • Cache-Vorhersage traf zwar zu, verbesserte aber den Durchsatz nicht und wurde daher entfernt
  • Alle Schichten werden mit einer PyTorch-Referenzimplementierung verglichen
    • Die Differenz der finalen Logits beträgt 3.6e-06
    • Der Vision Tower liegt bei 2.3e-06 gegenüber seiner eigenen Referenz
    • Die Konvertierung des latenten KV-Caches erhält identische Logits im Bereich von 1.2e-05

RAM-Budget und enger Leistungsbereich

  • K3 nutzt über 92 Schichten jeweils 16 Experten und erzeugt damit pro Token ein Working Set von 17,0 GB
    • Ist der Cache kleiner als dieses Set, werden in einem Token gespeicherte Experten vor dem nächsten Token wieder verdrängt, wodurch die Trefferrate auf 0 % fällt
  • Messungen auf einem 64-GB-System zeigen, dass mehr zugewiesener RAM nicht immer schneller ist
    • 32-GB-Budget · 3,32-GB-Cache: 0 % Treffer, 0,50 Tok/s
    • 46-GB-Budget · 17,32-GB-Cache: bestehende Trefferquote 17 %, 0,53–0,55 Tok/s
    • 52-GB-Budget · 23,32-GB-Cache: 0,04–0,15 Tok/s, nicht reproduzierbar
    • 58-GB-Budget · 29,32-GB-Cache: 0,02–0,03 Tok/s
  • Router-Lookahead erhöht bei 46 GB die Trefferrate von etwa 14 % auf 38 %, doch der Einbruch ab 52 GB kommt nicht von Cache-Misses, sondern von OS-Paging
    • Bei 58 GB ist die Trefferrate höher, trotzdem ist das System etwa 20-mal langsamer als bei 46 GB
    • Wenn ein großes Budget das System einmal in Paging versetzt, kann selbst die 46-GB-Messung auf 0,02 Tok/s abfallen
  • Das Standardbudget wird unterhalb von 7/8 des physischen RAM gewählt und in Schritten des Token-Working-Sets nach unten angepasst
    • Auf einem MacBook Pro mit 64 GB werden 46,24 GB verwendet, davon 17,56 GB für den Experten-Cache
    • Liegt das angegebene Budget unter dem Minimum, verweigert der Start die Ausführung statt per Swapping fortzufahren
    • Auf einem 128-GB-System kann das vollständig empfohlene Budget genutzt werden, entsprechend dem Trunk plus dem 3-fachen Working Set

K3-Leistung und Hardware-Anforderungen

  • Das gemessene System ist ein MacBook Pro M5 Pro mit 64 GB und interner SSD
    • Minimaler RAM für 4K-Kontext: 29,05 GB
    • 32K: 30,54 GB, 128K: 35,63 GB, 1M: 83,21 GB
    • Residenter Trunk: 27,28 GB
    • Modell laden: 20 Sekunden
    • Decode: 0,45–0,62 Tok/s beim Standardbudget
    • Prefill: chunked 0,47 Tok/s, sequenziell 0,29 Tok/s
  • Das Modell lässt sich zwar mit minimal 29,05 GB öffnen, aber ein 32-GB-System kann stark in Paging geraten, daher sind 64 GB die realistische Empfehlung
  • Pro Token werden im Cold-Zustand 17,0 GB an Experten gelesen; bei 38 % Trefferquote durch Lookahead sind es 10,5 GB
  • Die interne SSD wurde mit 12,78 GB/s gemessen, ein externes USB-Gehäuse mit 0,94 GB/s
    • Da ein Token 17 GB an Experten liest, dauert dieselbe Verarbeitung auf externem Speicher etwa 13 Sekunden
    • Der ursprüngliche Download kann auf einer externen Platte liegen, der konvertierte Container muss jedoch auf internem NVMe liegen
  • Erforderlich sind 982 GiB für den konvertierten Container und 1,42 TB für das Staging der Original-Shards; der Staging-Speicher kann nach der Konvertierung freigegeben werden

Attention und multimodale Verarbeitung

  • Die K3-Attention kombiniert Kimi Delta Attention und gated Multi-Head Latent Attention im Verhältnis 3:1
    • KDA hält statt eines wachsenden KV-Caches einen rekurrenten Zustand fester Größe
    • MLA cached ein Latent mit Breite 512, ohne pro Head Key/Value zu expandieren
  • kv_b_proj wird in Query und Output absorbiert, wodurch der 4K-Kontext-Cache von 11,25 GB auf 0,21 GB sinkt
    • Das ist eine 53-fache Reduktion
    • Bei 128K benötigt das expandierte Layout 360 GB, das latente Layout 7,2 GB
  • Der multimodale Pfad unterstützt ein ViT mit 401 Mio. Parametern, 27 Schichten und Patch-Größe 14
    • Die Kodierung eines Bildes mit 1024 Patches dauert 15,7 Sekunden
    • Ein Bild mit 896×896 belegt in der Standardkonfiguration 256 Sequenzpositionen
    • Bild-Embeddings durchlaufen ebenfalls 92 MoE-Schichten, daher entspricht der Großteil der Kosten eher dem Text-Prefill als dem Vision Tower
    • Wird max_patches in vision.json halbiert, halbiert sich auch die Zahl der Prompt-Positionen
  • Unterstützt werden PNG, JPEG, GIF, BMP, TGA und PSD; Bilder können in run, chat und eval verwendet werden
    • Die Positionen kodierter Bilder bleiben während eines Gesprächs im Attention-State erhalten und werden in späteren Runden nicht neu kodiert
    • Der Vision Tower wird nur bei vorhandenen Bildern geladen und nutzt 434 MB Gewichte sowie 1,12 GB reservierten Gesamtspeicher

Konvertierung, Ausführung und Server

  • Für den Build werden nur ein C11-Compiler und make benötigt
    • make check besteht ohne echtes Modell 23 Prüfungen mit synthetischen Containern und überspringt 11
    • Mit zwei echten Containern umfasst die vollständige Testsuite 36 Prüfungen
  • Die K3-Konvertierung verwendet unverändert die 96 Safetensors-Shards von moonshotai/Kimi-K3
    • Mit drei Prozessen dauert das auf einem M5 Pro etwa 4,7 Stunden
    • Ein reiner PyTorch-Encoder benötigt 23,7 Stunden
    • Die Verarbeitung ist schichtweise fortsetzbar, sodass nach einem Abbruch nur die gerade laufende Schicht erneut verarbeitet werden muss
    • Der Downloader unterstützt Resume für Teil-Dateien, exponentielles Backoff mit Jitter, Content-Length-Prüfung und Statusverfolgung abgeschlossener Shards
  • Die CLI bietet unter anderem run, chat, eval und plan; mit --json gibt sie Ergebnisse von eval, tokenize, plan, info und bench maschinenlesbar aus
  • serve/ ist ein OpenAI-kompatibler HTTP-Server, der die öffentliche C-API per ctypes aufruft
    • Er bietet /v1/chat/completions, /v1/completions, /v1/models und /health
    • Unterstützt Streaming, Tool-Definitionen und -Ergebnisse, typed call arguments, JSON-Antwortschemas, tool_choice, Think-Channel, thinking_effort und Bilder
    • Der Prompt-Renderer ist eine Portierung von encoding_k3.py aus dem K3-Release und vergleicht 38 Gespräche segmentweise, sofern ein Gewichtsverzeichnis vorhanden ist

Plattformen und aktuelle Einschränkungen

  • macOS arm64, Linux arm64 und Linux x86_64 erreichen in denselben modellunabhängigen Tests 23 bestandene und 11 übersprungene Prüfungen und bestehen außerdem Sanitizer sowie 400 Fuzz-Fälle
  • Windows x86_64 wurde per MinGW-w64 querkompiliert; synthetische Container, CLI und Forward Pass wurden validiert, aber nicht mit einem echten Modell-Container ausgeführt
    • MSVC und Windows ARM64 werden nicht unterstützt
    • Die Umgehung des Windows-Page-Cache wurde nur auf dem CI-Dateisystem verifiziert, nicht unter echter Last mit Containern größer als der RAM
  • Auf x86 wählt SIMD je nach CPUID AVX-512 oder AVX2, aber der AVX-512-Pfad wurde auf echter unterstützter CPU noch nicht ausgeführt
  • Das Metal-Backend ist korrekt, aber wegen hunderter kleiner abhängiger Matvecs 22 % langsamer als die CPU und standardmäßig deaktiviert
  • Die API ist noch nicht stabil, und automatische Konvertierung von Chat-Formaten unterstützt derzeit nur K3
    • Kimi-Linear rät keine Templates und läuft im Raw-Modus
  • Eine ungleichmäßige Bit-Zuweisung pro Experte ist nicht geplant
    • Der Wert des dritten Bits unterscheidet sich zwischen Experten innerhalb einer Schicht nur um bis zu 1,15× und zwischen Schichten nur um 1,01×, sodass optimierte Zuweisung keinen Nutzen brachte
    • Eine Zuweisung nach Routing-Häufigkeit spart zwar Speicherplatz, reduziert aber den I/O-Flaschenhals kaum
  • Die Lizenz ist Apache 2.0

1 Kommentare

 
GN⁺ 2 시간 전
Meinungen auf Hacker News
  • Wirklich beeindruckend. Das ist kein Projekt, das schon jetzt praktischer sein will als Cloud-Anbieter, sondern eines, das die Grenzen des Möglichen zeigt.
    Wenn Verbesserungen bei der Modelleffizienz und leistungsfähigere lokale Hardware zusammenkommen, könnten hochwertige lokale Modelle eines Tages auch wirtschaftlich betreibbar werden.

  • 0,5 Token pro Sekunde halte ich selbst für längere Aufgaben für nutzlos. Da würde ich lieber Geld ausgeben und zwei 16-GB-4060-Ti-Karten mit Tensor-Parallelisierung einsetzen.
    In 20 Jahren passt das vielleicht zu einem cyberpunkartigen langsamen Roboter, der mit Solarstrom läuft und nebenbei den Rasen mäht oder Gehwege reinigt, oder zu einem Roboter im Garten, der beim Beschneiden von Bonsai gerade so deren Wachstumstempo mithält.

    • Im Moment ist es praktisch kaum nutzbar, aber ich freue mich über solche Projekte, weil sie sich weiter verbessern müssen, bis am Ende eine praktische Version entsteht.
  • Es sei Verschwendung, pro Token zu zahlen und den Inferenzanbieter die Stromrechnung übernehmen zu lassen — aber ich sehe nicht, wie sich das davon unterscheidet, dass beim Kauf einer Gurke der Bauer für Wasser und Dünger bezahlt. Ich hoffe, das ist nur nachträglich zurechtgelegte LLM-Logik.
    Die Idee selbst ist interessant, und ich würde sie gern mit kleineren Modellen ausprobieren. Wenn bei 0,5 Token pro Sekunde mehrere GB pro Sekunde von der SSD gelesen werden, ist das für normale Consumer-Laptops immer noch zu groß, könnte aber bei 250–500-GiB-Modellen sogar eher praktikabel sein.

    • Wenn man selbst Tomaten anbaut, bekommt man kostenlose Tomaten. Für ein BLT reicht es vielleicht nicht, aber sie kommen nicht aus dem Supermarkt, also hat man die Welt ein kleines bisschen gerettet. /s
  • Angenommen, das System verbraucht dauerhaft 42 W und Strom kostet 20 Cent pro kWh, dann sind das etwa 5 Dollar pro Million Token, ohne Hardware und andere Kosten.

    • Ein Monat hat etwa 2,6 Millionen Sekunden, und bei 0,5 Token pro Sekunde erzeugt man 1,3 Millionen Token pro Monat. Rechnet man Nebenkosten mit ein, liegt man grob richtig, wenn man die monatlichen Betriebskosten der Maschine als Kosten pro Million Token ansetzt.
    • Mich würde interessieren, wie sich die Rechnung mit Solarstrom verändert.
  • Auch das Standard-llama.cpp kann GGUF per mmap einbinden, sodass Teile, die nicht in den Speicher passen, auf der Platte bleiben, während der Kernel-Page-Cache den häufig genutzten residenten Trunk vorhält. Ich frage mich, welchen Vorteil eine Eigenimplementierung hier hat.

    • Vor ein paar Tagen kam bei einem ähnlichen Projekt dieselbe Frage auf; dort hieß es, man habe zuerst mmap ausprobiert und sei dann mit einer eigenen Implementierung 10-mal schneller geworden.
      Das ist derselbe Grund, warum Datenbank-Engines eigene Caches implementieren. Kernel-Paging ist allgemein und anforderungsgetrieben, aber wenn man die tatsächlichen Zugriffsmuster kennt, kann man benötigte Daten vorab lesen und pipelinen.
    • Wenn man in dieser Größenordnung eine SSD als Swap-Speicher verwendet, ist die kumulative Schreibhaltbarkeit leicht schon nach wenigen Monaten aufgebraucht. Ich würde gern die kumulierten Schreibmengen und Verschleißstatistiken aus SMART sehen, wenn das länger als nur für kurze Tests läuft.
      Bei Modellen, die komplett in den RAM passen, war es besser, llama-server mit --no-mmap zu starten. Um allerdings das vollständige Kimi K3 plus einen Kontext von einer Million Token zu laden, bräuchte man natürlich einen 2-TB-Server.
  • Das README wirkt stark nach LLM-Text; ich frage mich, ob auch die Codebasis von einem LLM geschrieben wurde.

    • Ich will das nicht oberflächlich abtun, aber die Dokumentation widerspricht sich selbst darin, ob das Modell wirklich mit ursprünglicher Präzision läuft. Die behauptete 3-Bit-Quantisierung könnte interessant sein, aber K3 hat allein bei den dichten Parametern in Originalpräzision etwa 115 GB, die pro Token aktivierten Sparse-Experten liegen bei etwa 25 GB, dazu kommt noch der KV-Cache. Daher ist die Behauptung von 2 Sekunden pro Token bei 29 GB RAM schwer nachzuvollziehen.
    • Ich habe viel Software selbst geschrieben und auch eine Programmiersprache entwickelt: https://github.com/marcobambini/gravity
      Inzwischen nutze ich meine Fähigkeiten, um LLMs und Agenten zu orchestrieren und dadurch viel schneller besseren Code zu schreiben. Entwickler müssen sich entscheiden, ob sie sich an neue Technologien anpassen oder zurückfallen.
    • Ich wünschte, die Autoren hätten wenigstens das von einem LLM erzeugte README selbst einmal durchgelesen. LLMs fehlt das Verständnis für die Perspektive der Leser und sie setzen voraus, dass auch externe Leser den gesamten Kontext des Projekts und die Entscheidungsprozesse kennen.
      Interne Entscheidungen, die für Nutzer wichtig sein mögen, für Leser eines fertigen Projekts aber irrelevant sind, sowie Claude-typisch undurchsichtige Begriffe bleiben einfach stehen. Ich nutze LLMs häufig und erkenne an, dass sie für komplexe Programmieraufgaben sehr nützlich sind, aber die Qualität ihrer Textentwürfe ist miserabel.
    • In der Beitragendenliste steht claude, da muss man gar nicht raten. Wenn man Claude sogar Commits überlässt, erscheint es auch wenig wahrscheinlich, dass der Code eigenhändig geprüft wurde.
    • Im README ist Claudes typischer Stil besonders deutlich zu spüren. So wie man Schreibweisen einzelner Menschen erkennt, fühlt es sich inzwischen an, als hätte sich auch Claudes standardmäßig erzeugter kurzer, abgehackter und nur übertrieben rhythmischer Stil als eigener Typus im Kopf festgesetzt.
  • Wenn die Technik so weit ist, dass man das passende Modell für eine Aufgabe präzise auswählen kann, könnte das sehr wertvoll werden. Man kann sich eine Zukunft vorstellen, in der während eines automatischen Suchprozesses nur etwa 30 Minuten am Tag ein großes Modell läuft und in der restlichen Zeit kleine Modelle genutzt werden.

    • So eine Zukunft wird vermutlich nicht kommen. Selbst bei einem Backlog-Eintrag weiß man erst nach der Umsetzung, wie lange er gedauert hat; ohne ihn tatsächlich auszuführen, gibt es keine Möglichkeit, die Aufgabenkomplexität im Voraus zu kennen.