528 KiB
Inferenz-Parität: Gesamtabgleich und Arbeitsliste
Stand: 2026-09-05. Arbeitsgrundlage, keine Freigabe der Performance-Parität.
Sicherheitsunterbrechung 2026-09-09: WindowServer-Watchdog
Der direkte Lauf cargo test --release qwen_mtplx -- --include-ignored --test-threads=1 ist nicht als bestanden belegt. Der WindowServer-Bericht
von 18:13:56 +0200 identifiziert den Testprozess PID 47594 anhand der UUID
2D808BE5-E020-377D-B945-CF7D23FC7BD3 mit 99,07 GiB Footprint. Aktiv war
mtplx_connected_sparse_moe_matches_reference, CPU-Tensorerzeugung in
pattern_scaled. WindowServer hing im Metal-/IOGPU-/AGX-Pfad und wurde nach
121 Sekunden ohne Check-in vom Watchdog beendet. Ein Zusammenhang mit diesem
Test ist sehr wahrscheinlich; der genaue Grund des Speicheranstiegs und ein
bestimmter fehlerhafter GPU-Kernel sind dadurch noch nicht bewiesen.
Die Schutzüberwachung von model-eval wurde durch den direkten Cargo-Aufruf
umgangen. Serielle Ausführung ist kein Speicherlimit. Historische direkte
GPU-Testbefehle in diesem Dokument sind daher keine sicheren Wiederholungsbefehle.
Der zusätzliche Rust-Launcher test-supervisor verwendet dieselbe ausgelagerte
proc_pid_rusage-Messung wie model-eval (src/process_resources.rs). Er startet
das vorher gebaute Testbinary direkt, prüft alle 100 ms Footprint und
Lifetime-Peak, beendet bei fehlender Prozessmessung und überwacht Start sowie
ausbleibende Ausgabe statt der Gesamtlaufzeit. Grenzen sind explizit; für die
isolierte Fehlerdiagnose zunächst 8192 MiB und 15 Sekunden Start/Fortsetzung.
Er ist kein Cargo-/Build-Supervisor: Speicherwerte gelten für den Testprozess,
nicht beliebige von einem Build erzeugte Prozessbäume. Ausgabe ist nur
Testfortschritt, kein Nachweis tatsächlich fortschreitender GPU-Arbeit.
Vorbereitung ohne GPU-Ausführung:
cargo build --release --offline --bin test-supervisor -j 1
cargo test --release --offline --bin ds4-server --no-run -j 1
Danach ausschließlich den vom Build ausgegebenen tatsächlichen Testbinary-Pfad
an test-supervisor 8192 15 15 TEST_BINARY mtplx_connected_sparse_moe_matches_reference übergeben. Keine parallelen
GPU-Läufe. Die Speichergrenze ist ein extern geprüftes Abbruchbudget, keine
Garantie gegen kurzfristiges Überschießen oder einen nicht unterbrechbaren
Treiberfehler. Die unten genannten Leistungsmessungen werden nicht durch diese
diagnostischen Grenzen oder Instrumentierung ersetzt.
Der betroffene Test meldet vor Gewichtsaufbau, nach Aufbau, nach Verifikation
und nach Freigabe Prozess-Footprint, Metal-Allokation sowie aktive/gecachte
Allocator-Bytes. Cache, Kernel, Power und Chunkgröße bleiben unverändert.
Zusätzlich ist bei Bedarf der vorhandene DS4_METAL_TRACE_ALLOCS-Pfad nutzbar.
Fortsetzung:
- Wächter ohne GPU verifizieren: Speicherabbruch, Start-/Fortsetzungsabbruch, Exitfehler und erfolgreiche Fortsetzung über die Timeoutfenster hinaus. CPU-Selbsttest am 2026-09-09 bestanden (1 Test, fünf Szenarien, 1,66 s).
- Erst danach den Speicheranstieg mit isoliertem, überwachtem MoE-Test messen; anhand der vier Grenzwerte aktive Puffer, Cache und übrigen Footprint trennen.
- Belegte Ursache im Besitz-/Freigabepfad beheben und Referenzsemantik prüfen. Kein Cache-Leeren oder künstliches Verkleinern als Ersatz für die Diagnose.
- Vollständige Qwen-Integration und P16 bleiben offen, ebenso die gesamte Abnahme aller drei Modelle mit/ohne spekulatives Decoding innerhalb 2 %.
Reproduktion und belegte Ursache, 2026-09-09
Rohdaten: local-eval-results/moe-memory-20260909.UvC1wv/.
Der Sandbox-Versuch (test.*.log) scheiterte vor Ausführung mit „Metal device
not available“; alle folgenden Metal-Tests liefen mit freigegebenem Metal-Zugriff
und dem externen Wächter. Kein Modell wurde geladen oder heruntergeladen.
- Vor Korrektur (
gpu.*.log): der einzelne ursprüngliche MoE-Test erreicht nach 1,606 s den Speicherabbruch, gemessener Footprint 9.037.880.280 Bytes bei einem Budget von 8.589.934.592 Bytes. Das zeigt auch das mögliche Überschießen zwischen den 100-ms-Abfragen. Bereits der alte Encoderpfad akkumuliert Metal-Speicher; der kanonische Allocator ist noch nicht aktiv. - Zusätzliche vorhandene Allokationsspur (
trace.*.log, 1-GiB-Budget): Rust/native Tensor-Freigaben bringen den Tensor-Livezähler auf null, währendMTLDevice.currentAllocatedSizeweiter wächst. Kein fehlendes Rust-drop, kein MTPLX-Allocator-Cache und kein einzelner großer Kernel ist hierfür nötig. - Minimaler Test
mtplx_tensor_cpu_access_releases_native_storage, ohne GPU-Dispatch (cpu-red.*.log): acht 1-MiB-Allokationen pro Zugriffsart. Schreiben, Lesen undcontentshalten jeweils exakt 8.388.608 Bytes über die Tensor-Freigabe hinaus. Anlegen/Freigeben ohne Zugriff, Views, Allocation-Identität und Heap-Abfrage halten jeweils 0 Bytes zurück.
Ursache: MTLBuffer.contents liefert einen Interior-Pointer. Der mit ARC
kompilierte Objective-C-Bridgecode erzeugt dafür objc_retainAutorelease;
die zusätzliche Referenz bleibt auf einem Rust-Thread ohne passenden Pool-Drain
erhalten. Der erzeugte Maschinencode der drei Zugriffe wurde geprüft.
Der gepinnte MTPLX-Unterbau ruft Buffer::raw_ptr() dagegen über Metal-C++
auf (mlx/backend/metal/allocator.cpp:25) und hat diesen ARC-Zusatz nicht.
Clang dokumentiert genau diese implizite Lebensdauerverlängerung und ihre
Vermeidung durch einen präzise lebenden starken Empfänger:
ARC Interior pointers.
Korrektur in native/metal/ds4_metal.m: gemeinsamer
ds4_gpu_tensor_cpu_data-Zugriff mit objc_precise_lifetime für die temporäre
MTLBuffer-Referenz. Der ausdrücklich gehaltene Tensor bleibt Eigentümer des
Speichers. contents, Read, Write und mittelbar Fill benutzen denselben Pfad.
Keine neue Pool-Schleife, keine GPU-Synchronisation, kein Cache-Leeren und keine
Änderung von Kernel, Power, Chunkgröße oder Referenz-Testformen. Die Brücke
wird auch im Produkt/UI verwendet, nicht nur unter cfg(test).
Nach Korrektur:
- Identischer Minimaltest (
cpu-green.*.log) bestanden: alle sieben Zugriffsarten jeweils 0 Bytes zurückgehaltener Metal-Speicher. Im Maschinencode fehlt nunobjc_retainAutoreleasein den drei Zugriffen; das davon verschiedeneobjc_retainAutoreleasedReturnValuebleibt korrekt. - Ursprünglicher MoE-Test (
fixed.*.log), unverändertes 8-GiB-/15-s-Budget: 440 exakte Referenzvergleiche, 220 je Encoder, abgeschlossen in 13,322 s. Peak-Footprint 4.839.182.320 Bytes (4,51 GiB). Nach jedem der 220 alten Encoderfälle genau 1.769.472 Bytes Metal-Basisbelegung. Im kanonischen Encoder nach Freigabe 0 aktive Allocator-Bytes; am Ende 3.202.034.186 Bytes regulärer Cache. Dieser Cache wurde nicht künstlich geleert. - Originalquellprüfung bestanden: 17 Körper, 41 Custom-Einstiegspunkte, 22 Runtime-Einheiten / 203 Einstiege plus dynamische QSA-Quellen stimmen mit dem gepinnten Export überein.
- Alle drei Puffer-Eigentumstests bestanden (
ownership.*.log, 0,08 s): Completion hält Allokationen ohne Data-Donation zu verändern, leere Tensoren/Views behalten ihre Identität, CPU-Zugriffe behalten keinen Speicher. Release-Testbuild, warnings-denied Clippy für App und Tests sowiecargo fmt --all -- --checkundgit diff --checkbestanden.
Dies behebt die reproduzierte Retention, ist aber keine abgeschlossene UI-Responsiveness- oder 2%-Performance-Abnahme. Ein vollständiger neuer UI-/Harness-/Golden-Master-Vergleich und die übrige Qwen-Portierung bleiben offen.
Verbindliche Auftragspräzisierung vom 2026-09-06
Die bisherige Auswahl einzelner Optimierungen anhand von Mikrobenchmarks wird beendet. Der Nutzer verlangt für Qwen einen vollständigen MTPLX-Port, keine Sammlung ähnlich wirkender Rust-/Metal-Optimierungen. Diese Präzisierung hat Vorrang vor früheren Auswahl- und Rücknahmebegründungen in diesem Dokument.
- Kernel-Identität: Die im gepinnten MTPLX-Qwen-Pfad tatsächlich verwendeten Metal-Kernel übernehmen, einschließlich der von dessen gepinnten Abhängigkeiten bereitgestellten Kernel. Gleiche Typen, Layouts, Spezialisierungen, Geometrien, Rundungs-/Reduktionsfolgen und Dispatch-Bedingungen. Eigenständige MPP-QMM- Implementierungen sind kein Ersatz für die von MTPLX aufgerufenen Kernel, auch wenn einzelne Ausgabehashes passen. Nur erforderliche ABI-/Binding- Anpassungen separat ausweisen; keine stillen algorithmischen Änderungen.
- Rust-Funktionsidentität: Modellaufbau, Materialisierung/Fusion, Graphfolge, PLE-Streaming, Cache-/State-Lebenszyklus, Scheduling, Sampler, MTP-Draft/Verify/ Commit/Repair sowie EOS/Cancel und Fortsetzung vollständig nachbilden. Dazu gehören alle für das vorhandene Modell erreichbaren Form- und Fallbackzweige, nicht nur die von drei Beispielprompts zufällig ausgeführten Pfade.
- Zusammenhängende Umsetzung: P01–P12 sind Abdeckungs- und Portierungsaufgaben, keine optionalen Optimierungskandidaten. Zuerst deren vollständige Referenz- Zuordnung und Umsetzung samt Korrektheits-/State-Tests. Anschließend den integrierten Stand gegen MTPLX auf Gesamtlaufzeit, Durchsatz und Verzögerungen prüfen. Kein erneuter Performance-Auswahlzyklus nach jedem Kernel.
- Rücknahmen: Ein isoliert fehlender Geschwindigkeitsgewinn ist kein Rücknahmegrund für einen korrekten Referenzport. Nur belegte harte Regressionen rechtfertigen eine begründete Rücknahme; der betroffene Referenzbestandteil bleibt dann ausdrücklich unerledigt. Ein Eigenbau-Experiment zurückzunehmen beweist nicht, dass die entsprechende MTPLX-Implementierung verzichtbar ist.
- Abnahme: Erst vollständige funktionale und Kernel-Abdeckung, dann P16 mit den vereinbarten vollständigen Chats und Referenzvergleichen. DeepSeek/GLM behalten antirez/ds4 als Golden Master und bleiben Teil des Gesamtziels.
Insbesondere werden die früheren negativen Einzelversuche zu P07 (Gate/Up- Fusion), P09 (Matmul-Layouts) und P11 (lazy Target-Verteilungen) nicht als Freistellung von der entsprechenden MTPLX-Funktionalität verwendet. Historische Messbelege bleiben erhalten, entscheiden aber nicht über den Umfang des Ports.
Quellzuordnung für die zusammenhängende Qwen-Portierung
Dies sind geprüfte Einstiegspunkte, noch keine vollständige Kernel-Abdeckung. Für jeden Bereich ist die transitive Zuordnung bis zum tatsächlichen Kernel einschließlich aktivierter Laufzeit-/Formbedingungen zu schließen. Ein Import allein oder ein gesetztes Flag gilt nicht als Dispatch-Nachweis.
| Bereich / bestehender Task | MTPLX-Einstieg | Verbindlicher Umfang |
|---|---|---|
| Modell / Laden / Typen · P01/P09 | models/qwen4_exp.py: TextModel, Qwen4ExpTextModel, Sanitize-Fusionen |
Gewichte, BF16-Aktivierungen, FP32-Zustände, zusammengeführte Projektionen, Views und Lebensdauer |
| Hyper-Connections · P09 | GatedResidual, kernels/hyper_connection_v3.py, hyper_connection.py |
R1/R2, vorbereitete Quantisierung, Prefill- und Fallbackpfade, nicht nur Decode |
| Affine / Gather / Sorted Matmul · P07/P09 | _FusedGDNInProj, _FusedGateUpSwitchGLU, _FusedGateUpMLP; deren tatsächlich aufgerufene Quantized-Matmul-Kernel |
QMV/QMM/NAX/Split-K, Gather/Sort/Unsort, gemeinsame Gate/Up-Projektionen, Typ-/Formgrenzen |
| GDN · P06 | GatedDeltaNet.__call__, kernels/gdn_step_fused.py, gdn_conv_norm.py, gdn_out_fused.py; gated_delta_update aus der gepinnten Abhängigkeit |
Vollständige Branchfolge, Conv-/Delta-Zustände, Capture-Tape, Norm/Gate, Prefill/Decode/Verify |
| MoE / Shared Expert · P07 | SparseMoeBlock, _FusedGateUpSwitchGLU, _FusedGateUpMLP, kernels/moe_glu_decode.py |
Router, Top-k, Sortschwelle, fusionierte Decode-/Verify- und Prefillpfade, Shared-Expert-Kombination |
| QSA / KV / Attention · P08 | Attention, QSAIndexer, QSACache, QSA-Kernelmodule und tatsächlich selektierter Attention-Backendpfad |
Cache-Layout, Pooling/Indexer/Top-k/Masken, Dense-/Sparse-/Gather-/Flashzweige, Kontextgrenzen |
| PLE · P10 | NGramTable, _SidecarGather, NGramEmbedding, PLELayer |
Hashing, Vorab-Staging, LRU/Bypass, Gather-/IO-Reihenfolge, Faltung und History |
| Serving / Sampling / MTP · P02–P05/P11/P12 | server/openai.py, sampling.py, Modell-Capture und aufgerufene Generator-/Backendmodule |
Tokenisierung, laufender Chat, RNG/Verteilungen, Draft/Verify, Commit/Repair, Cache, Submission und Abschluss |
Der bestehende Rust-Pfad in src/engine/metal/qwen.rs und die Kernel in
metal/qwen38.metal sind gegen diese gesamte Kette zu ersetzen/anzugleichen.
Die Referenz bleibt MTPLX; seine verwendeten Bibliothekskernel sind Bestandteile
dieser Referenzausführung, kein Wechsel zu einem anderen Golden Master.
Portierungsstand: unveränderte Kernelkörper und direkte Bindung
2026-09-06: metal/mtplx_qwen.metal enthält erstmals direkt extrahierte,
unveränderte MTPLX-Kernelkörper, nicht nachgeschriebene Äquivalente.
tools/mtplx-kernel-source.py prüft den sauberen Referenzcommit und erzeugt
die deterministische Übersetzungseinheit. --check vergleicht die gesamte Datei;
ein gewöhnlicher Rust-Test schützt zusätzlich die neun eingebetteten Körperhashes.
Nur Einstiegspunkt-ABI und Templatespezialisierungen sind außerhalb der Körper
ergänzt. BF16 ist physisch BF16, der RMS-/Delta-Zustand bleibt wo vorgesehen FP32.
| MTPLX-Körper | Eingebundene Spezialisierungen | Korrektheitsbeleg | Produktgraph |
|---|---|---|---|
hyper_connection._SOURCE |
BF16, Injection0/1 | Zeilen1/4/8, Ausgabehashes exakt | Umstellung offen |
hyper_connection_v3._SRC_R1 / _SRC_R2 |
BF16, RMS FP32 | Gekoppelte R1/R2-Ausgabe exakt | Umstellung offen |
gdn_conv_norm._SRC |
BF16 | q/k/v und Folgezustand exakt | Umstellung offen |
gdn_conv_norm._SRC_ROWS |
BF16, S2–6 | Alle fünf Breiten, q/k/v und Folgezustand exakt | Umstellung offen |
gdn_step_fused._SRC |
BF16, Rekurrenz FP32 | Zwei aufeinanderfolgende Schritte einschließlich beider Folgezustände bitgenau | Umstellung offen |
gdn_out_fused._SRC |
Gruppen32/64, x BF16/FP32, Quantparameter BF16 | Alle vier Kombinationen bitgenau, synthetische gültige Q4-Packs | Umstellung offen |
mlx_lm 0.31.3/models/gated_delta.py · skalare Rekurrenz |
BF16 q/k/v/beta, FP32 g/Zustand; mit/ohne Maske | S1/4/7/32/2048, Ausgabe und FP32-Folgezustand bitgenau | Umstellung offen |
Die Metal-Bibliothek lädt diese 17 Einstiegspunkte. Die neue direkte Bridge bindet geordnete Ein-/Ausgabepuffer ohne eigenes Qwen-Argumentlayout, Typcasts, automatische Geometrieänderung oder zusätzliche Flushes. Ihre Bindungs-/Grid- Konvention wurde gegen den gepinnten CustomKernel-Dispatcher geprüft; das ist MTPLXs benutzte Runtime, kein anderes Modell-Orakel. R1/R2 samt Packvorbereitung bleiben im Test nachweislich in einem Command Buffer. Der vorhandene Stage-Profiler verwendet für alte/neue Aufrufe dieselbe Erfassungsfunktion. Allgemeine Submission-/Ressourcenparität P05 bleibt offen.
tools/mtplx-kernel-fixtures.py ruft die tatsächlichen MTPLX-Funktionen mit
modellfreien deterministischen Eingaben auf. Die 29 geprüften Fälle mit 65
Ausgabehashes stehen in
tests/fixtures/mtplx-custom-kernels.jsonl. GPU-Test und CPU-Quellhash-Test
bestanden; keine Benchmarks oder vollständigen Modellläufe. Apache-Lizenz und
NOTICE mitgeliefert; Attribution im CLI und verlinkt in den Modelleinstellungen.
Keine Fertigmeldung: Der Inferenzgraph ruft derzeit weiterhin die alten Kernel auf; die direkte ABI wird bisher vom Korrektheitstest genutzt. Die zusammenhängende Umstellung der Aktivierungen und Graphaufrufe auf BF16 sowie die übrigen MTPLX-Kernel und Rust-Funktionen sind weiterhin umzusetzen. Kein FP32/BF16-Konvertierungsadapter wurde als vermeintlich fertiger Port eingeführt. Diese Grundlage ist keine Performance- oder Gesamtparitätsabnahme.
Die Rekurrenzquelle stammt aus MTPLXs tatsächlich installiertem mlx-lm 0.31.3,
SHA256 79c8376a51c694b03e54d2f996ced6ea6c8c42868b8571529f97334db165a3e1.
Der Exporter wertet ausschließlich die String-/F-String-AST aus, nicht den
Python-Modellcode. Die tatsächlich generierte Referenzsignatur wurde separat
mit verbose=True geprüft: Skalar T als constant int32_t&, Grid32×128×48,
Threadgroup32×4×1. Ihre MIT-Lizenz ist mitgeliefert. Der FP32-Zustand wird im Test
nicht auf BF16 reduziert; die bisherigen 19 Fixture-Zeilen blieben unverändert.
Für die folgenden Matmul-Ports ist nun auch die exakte Runtime-Quelle0.32.2
lokal vorhanden: local-eval-results/mtplx-runtime-0.32.2, Commit
1f8e74e3f12f31365464a6867c6579f0e9b29d85. quantized.h stimmt byteweise mit
dem installierten Referenzheader überein. Die ältere Navigation über die lokale
0.32.3-Kopie ist keine Portierungsfreigabe. Der unveränderte Upstream-Generator
make_compiled_preamble.sh scheitert innerhalb und außerhalb der Sandbox an der
fehlenden separaten Metal-Toolchain; die Metal-Laufzeitkompilierung funktioniert.
Keine Toolchain installiert, kein Host-C/C++-Backend gebaut, keine Modelle geladen.
Die Runtime enthält außerdem ihre vorhandene mlx.metallib; deren Nutzung oder
quellidentische Neuerzeugung war zu diesem Zeitpunkt noch offen. Der folgende
Abschnitt dokumentiert die inzwischen geprüfte direkte Shader-Nutzung.
Runtime-Shader und verbundener BF16-GDN-Abschnitt
Die installierte Runtime wurde nicht nur anhand der Versionsnummer eingeordnet:
get_quantized_kernel in ihrer tatsächlichen libmlx.dylib ruft direkt
Device::get_kernel für die vorgefertigte Standardbibliothek auf (Disassembly
bei0xd8af40). Das entspricht nojit_kernels.cpp der gepinnten0.32.2-Quelle.
Die dort vorhandene Shader-Datei ist deshalb byteidentisch als
metal/mtplx-runtime-0.32.2.metallib übernommen; SHA256
dc59d1cceb1a5c7e578232e6e41e28e2c73c9463ac6dbc3886c3ee17ffc270ed,
182351120Bytes. Kein C/C++-Backend wird eingebunden. Lizenztext und Herkunft
stehen in metal/MLX-LM-LICENSE.txt und metal/MTPLX-RUNTIME.txt.
Die vorhandene Ressourcenverpackung nimmt die Datei mit auf; die Metal-Bridge
lädt sie erst beim ersten entsprechenden Dispatch. Keine Toolchain-Installation.
src/engine/metal/qwen_mtplx.rs enthält jetzt die direkten Rust-Aufrufe für
kontiguierliche, nicht gebatchte BF16-Affine-Projektionen auf dem M5Max:
- Referenzgrenzen33/25/13 nach Matrixdimension, QMV-Quad, normale/schnelle QMV, QMV-Wide inklusive Referenz-Tiling statt einer eigenen Zeilenheuristik.
- QMM, NAX und Split-K einschließlich BF16-Teilresultaten und den originalen
ein-/zweistufigen Reduktionskerneln. Integerparameter über
setBytes, explizite 3D-Threadgroups; keine CPU-Reduktion oder Typkonvertierung. - 78 gegen tatsächliche
mx.quantized_matmul-Aufrufe erzeugte Fälle bitgenau: Bits4/8, Gruppen32/64, Randgrößen, Variantengrenzen, beide Reduktionsstufen, NAX-/Steel-Pfade und 2048Zeilen. Diese Runtime-Aufrufe sind Bestandteile der MTPLX-Referenz, keine Änderung des Modell-Orakels. - Verbundener GDN-Decode-Abschnitt: fusionierte Eingangsprojektion → originaler
GDN-Step → Ausgangsprojektion, native BF16-Views und getrennte neue Conv-/Delta-
Zustände. Zwei Folgeschritte stimmen vollständig mit dem tatsächlichen
GatedDeltaNet.__call__aus MTPLX überein. Der Referenztest prüft ausdrücklich dessen Live-State-Branch; Kaltstart/Prefill/Verify sind damit nicht abgenommen. Jeder Rust-Schritt verbleibt nachweislich in einem Command Buffer.
Die direkte Bridge hält Datenbindung und Pipeline-Bool-Konstanten getrennt, prüft ungültige/überlappende Bindungen und verwendet die bestehenden Metal- Command- und Profiling-Funktionen. Temporäre Projektions-/Split-Puffer bleiben im Rust-Ergebnis bis zum Abschluss des Command Batches erhalten.
Produktstatus unverändert offen: Das neue Rust-Operationsmodul ist bis zur
zusammenhängenden BF16-Graphmigration ausdrücklich unter cfg(test) eingebunden.
Es ersetzt noch nicht den alten FP32-Inferenzgraphen. Es ist kein zweiter
Generator und keine abweichende Headless-Engine. MoE/Gather/Sort, QSA/Attention,
PLE, komplette GDN-Fallback-/Capture-Pfade sowie Sampling/MTP und der gemeinsame
Zustands-/Scheduling-Port sind weiterhin umzusetzen. Kein P01–P16 geschlossen,
keine Geschwindigkeitsmessung, Bundle-Auslieferung oder Paritätsabnahme.
Die Fixture-Datei enthält nun insgesamt 571 Fälle mit 797 Ausgabehashes. Die bisherigen 546 Fälle blieben beim ergänzenden Normmodul-Nachweis unverändert. Zusätzliche CPU-Tests prüfen den Shader-Dateihash und die Rust-Dispatch-Grenzen.
Gather-Dispatch: geprüfter Portabschnitt, keine Produktabnahme
qwen_mtplx::gather_bf16 bildet den normalisierten BF16-Gather-Pfad in Rust ab:
QMV normal/fast, Gather-QMM Steel/NAX sowie sortiertes RHS-QMM mit den originalen
Bool-Konstanten200/201/202. Es benutzt ausschließlich die unveränderte gepinnte
Runtime-Metallib. MTPLX sortiert ab64Routen; der Backendwechsel zum sortierten
RHS-Kernel erfordert separat M=1, mindestens16Routen und Routen/Experten>=4.
Die NAX-RHS-Tilehöhe wechselt bei Routen/Experten=64 von32 auf64. Diese Bedingungen
sind keine lokalen Performance-Heuristiken. GPU-Sortierung und Rücksortierung
sind dadurch ausdrücklich noch nicht implementiert.
40 echte mx.gather_qmm-Referenzaufrufe prüfen Q4/Q8, Gruppen32/64, allgemeine
und sortierte Indizes, die Schwellen unmittelbar darunter/darüber, N-Ränder sowie
512Experten. Alle40Ausgaben sind bitgenau. Der gemeinsame fokussierte Lauf
führte7Tests aus:7bestanden,0fehlgeschlagen,0ignoriert;149GPU-Fälle/189Hashes.
Referenzfehler im künstlichen K-Randfall: Bei sortiertem
X=33,M=1,N=81,K=160,E=8,R=33 liest der gepinnte NAX-RHS-Kernel über logische
Tensorgrenzen. Bereits MTPLX allein liefert bei unveränderten logischen Eingaben
andere Ergebnisse, wenn nur nachfolgender Speicher geändert wird. In
quantized_nax.h:1659 wird die letzte A-Tilebreite aus BK statt k_remain gebildet;
Eingangs-Padding allein genügte im gesamten Fixture-Lauf nicht, erst kontrollierte
physische Grenzen auch für W/Skalen/Biases machten beide Ausführungen identisch.
Die zwei betroffenen Q4/Q8-Fälle sind deshalb mit explizitem Nullpadding in beiden
Testläufern enthalten, nicht übersprungen oder toleranzgeweitet. Die übrigen
38Gather-Ausgabehashes blieben unverändert. Originalkernel und Produktionspuffer
wurden nicht geändert. Diese synthetische K=160-Form ist keine MoE-Form des
installierten Modells (K=2560 bzw.640). Beleg und ursprüngliche Hashes stehen in
local-eval-results/20260906-mtplx-port/gather-padding-investigation.md.
Der Produktgraph bleibt unverändert offen; diese Checks ersetzen weder die MoE-Kette noch die sechs abschließenden Gesamtmessungen.
GPU-Argsort und inverse Reihenfolge
Der normalisierte Rust-Argsort für zusammenhängende letzte Achsen verwendet die
originalen Runtime-Kernel für U32-, BF16- und FP32-Eingaben. Die Referenz führt
auch argpartition als vollständigen Sort aus. Übernommen sind die Auswahl der
32/64/128/256/512-Thread-Blöcke, Vierer-Tiles, Mehrblock-Sortierung mit Werte- und
Index-Pingpong, Partition/Merge-Reihenfolge und der abschließende Original-Copy.
Die Copy-Variante wechselt bei65536Elementen von1 auf2Elemente pro Thread.
Die Metal-Bindung unterstützt dafür zusätzlich dispatchThreads; aufgerundete
Threadgroups wären bei diesem ungeschützten Copy-Kernel nicht funktionsidentisch.
Bestehende Matmul-/Gather-Aufrufe verwenden weiter unverändert Threadgroups.
123 echte Referenzaufrufe prüfen jeweils argsort(x) und argsort(order):
20Breiten von1 bis65537 bei1/3Zeilen, dazu2048x512; jeweils U32/BF16/FP32.
Die Daten enthalten gleiche Werte, auch durch BF16-Rundung entstandene Gleichstände.
Alle246Index-Hashes sind bitgenau. Beide zusammenhängenden Sortierungen samt
Merge-/Copy-Schritten bleiben in jedem Rust-Test in genau einem Command Buffer;
kein CPU-Auslesen zwischen den Sortierungen. Der gemeinsame Lauf hat8Tests
ausgeführt:8bestanden,0fehlgeschlagen,0ignoriert,272Fälle/435Ausgabehashes.
Rohbeleg: local-eval-results/20260906-mtplx-port/runtime-sort-combined-check.log.
Damit ist die inverse Indexreihenfolge geprüft, nicht schon die vollständige
_gather_sort-/_scatter_unsort-Datenbewegung. Deren Division/Gather-Front-Aufrufe,
die verbundene MoE-Kette und die übrige Produktgraphmigration bleiben offen.
Keine Gesamtperformance-Abnahme, kein P01–P16 geschlossen.
Verbundene Sort/Gather/Unsort-Datenbewegung
Die zuvor offene Datenbewegung ist nun als zusammenhängender Rust-Abschnitt
implementiert: Experten-Argsort, inverse Reihenfolge, order // top_k, Gather
der BF16-Tokenzeilen und U32-Expertenindizes, anschließend Gather über die inverse
Reihenfolge für die Rücksortierung. Keine CPU-Auswertung der erzeugten Indizes.
Die Sortschwelle gehört weiterhin in den noch zu verbindenden MoE-Aufrufer.
MTPLXs Runtime erzeugt den Gather-Front-Kernel aus indexing/indexing.h und
indexing/gather_front.h zur Laufzeit. Diese Shader-Einheiten werden jetzt mit
gepinnten Datei- und Einheitshashes unverändert in die vorhandene kanonische
Quelldatei exportiert; nur Includes werden aufgelöst und Instanziierungen ergänzt.
Keine C++-Hostimplementierung übernommen. Die bestehende Bindung kann diese
Shader mit unmittelbaren Größen-/Stride-Parametern aufrufen und behält originale
dispatchThreads-Geometrie und Zwei-Elemente-Grenze bei BF16-Slicegröße>8 bei.
Die ganzzahlige Division nutzt die unveränderte Runtime-Metallib mit dem
Referenzwechsel der Arbeit pro Thread bei65536Elementen.
Sieben direkte Aufrufe der tatsächlichen MTPLX-Helfer _gather_sort und
_scatter_unsort sind mit vier Ausgaben pro Fall geprüft: sortierte Daten,
Expertenindizes, inverse Reihenfolge und zurücksortierte Daten. Fälle:1/6/7/205/
2048/6554Tokens bei Top-10, Breiten7/8/9/2560, darunter2048x10x2560 und eine
65540-Routen-Kette. Alle28Hashes sind bitgenau. Jede gesamte Rust-Kette bleibt in
einem Command Buffer. Der gemeinsame Lauf führt9Tests aus:9bestanden,0Fehler,
0ignoriert;279Referenzfälle/463Hashes. Alle bisherigen272Fixture-Zeilen waren
bei frischer Referenzerzeugung unverändert. Der Quellvergleich prüft außerdem
die9Custom-Bodies/17Einträge sowie2Runtime-Einheiten/8Gather-Instanziierungen;
die geketteten Tests betreffen BF16/U32 mit32-Bit-Offsets, nicht alle8Varianten.
Beleg: local-eval-results/20260906-mtplx-port/connected-gather-combined-check.log.
Weiter offen: verbundene Gate/Up-Aktivierung/Down-MoE-Kette, Router/Shared-
Expert-Integration, die übrigen Graphabschnitte und die vollständige BF16-
Produktmigration. Keine Performance-Abnahme oder Änderung der Abschlusskriterien.
Verbundene SwitchGLU-Rechenkette und tatsächlicher SiLU-JIT-Code
qwen_mtplx::switch_glu bildet jetzt den vollständigen Aufruf von
_FusedGateUpSwitchGLU mit bereits ausgewählten Experten ab: Sortierung ab64Routen,
gemeinsame Gate/Up-Gather-Projektion, nn.silu(gate) * up, Down-Gather-Projektion
und Rücksortierung. U32-Arange und Broadcast-Strides erhalten die implizite
Token-/Expertenzuordnung; kein zusätzliches Materialisieren broadcasteter
Tokenindizes, kein CPU-Auslesen erzeugter Indizes. Aktivierungen bleiben BF16.
Temporäre Puffer werden bis zum Abschluss des zusammenhängenden GPU-Batches gehalten.
Der SiLU-Code wurde nicht anhand seiner Formel neu geschrieben:
tools/mtplx-jit-reference.py beobachtet im isolierten Referenzprozess den
originalen Objective-C-Metal-Compileraufruf, leitet ihn unverändert weiter und
setzt den lokalen Beobachtungs-Hook abschließend zurück. Der gespeicherte
JIT-Receipt tests/fixtures/mtplx-silu-jit.json enthält alle19erzeugten Varianten.
Vollständiger beobachteter Compiler-Quellhash:
76cafb45db55a91efba66503dde59b37628ea360f220f35dd860f4ac3c3d0111.
Die Rank-2-Erzeugung wurde erneut exakt bestätigt; Rank3/5 der sortierten und
unsortierten SwitchGLU erzeugen nach Normalisierung der Symbolnamen denselben
Rechencode. Keine Rechenanweisung wird durch diese Normalisierung geändert.
Der bestehende Shader-Exporter übernimmt diese19Varianten sowie ihre originalen BF16-Mathematik-, Sigmoid-, Multiply-, Cast- und Stride-Helfer mit gepinnten Dateihashes. Nur die Hostnamen erhalten lokale Aliasse. Das ist Shadercode, kein übernommener C++-Hostcode. Die Rust-Auswahl erhält Contiguous/Strided-Pfade, die65536-Elemente-Grenze und den separaten ursprünglichen Up-Multiply-Dispatch. Der Quellcheck umfasst nun9Custom-Bodies/17Einträge sowie8Runtime-Einheiten mit 27Runtime-Einträgen (8Gather,19SiLU).
Nachweise:10Aktivierungsfälle mit zwei Ausgaben, darunter20480x640 und die
Vektorisierungsgrenzen;21direkte Aufrufe der tatsächlichen MTPLX-SwitchGLU-Klasse
mit synthetischen Q4-Gewichten, Gruppen32/64/gemischt. Ganze Ketten bei1/6/7/205/
2048Tokens mit K2560/I640/E16 sowie7/205Tokens mit K128/I64/E512. Alle41neuen
Ausgabehashes bitgenau; jede Rust-Kette ein Command Buffer. Der gemeinsame Lauf:
11Tests ausgeführt,11bestanden,0fehlgeschlagen,0ignoriert;310Fälle/504Hashes.
Beleg: local-eval-results/20260906-mtplx-port/connected-switch-combined-check.log.
Das ist keine Messung des vollständigen512Experten-Modells bei K2560.
P07 bleibt offen: Router/Softmax/Top-k, Gewichtung, Shared Expert und die
gesonderten fusionierten Decode-/Verify-Pfade von SparseMoeBlock sind nicht
durch den abgeschlossenen SwitchGLU-Untermodul-Nachweis abgedeckt. Auch die
übrigen Graphabschnitte, Produktintegration und Gesamtperformance-Abnahme bleiben
offen. Kein Rollback und keine Auswahl von Teiloptimierungen nach Geschwindigkeit.
Verbundener Router und SparseMoeBlock einschließlich Decode/Verify
Der kanonische Rust-Port umfasst jetzt den Standard-MoE-Block mit den Sanitize-fusionierten Expert-/Shared-Expert-Packs: Q8-Routerprojektion, präzises BF16-Softmax über alle Experten, vollständiges Argpartition/Argsort, Top-10-View, GatherAxis und optionale Normalisierung, SwitchGLU, gewichtete BF16-Summe, Shared-MLP, Sigmoid-Gate und Addition. Der Top-10-Stride bleibt erhalten; erst das originale Flatten vor Sortierung materialisiert ihn. Unsortiertes GatherQMM verarbeitet ihn direkt. Keine CPU-Indizes oder zusätzlichen Flushes/Wartepunkte innerhalb der verbundenen Kette.
Die vier unveränderten Kernelkörper aus moe_glu_decode.py sind zusätzlich
mit16BF16-Spezialisierungen eingebunden: Decode und Verify mit2/3/4Zeilen,
Gruppen32/64 für Gate-Up und Down unabhängig. Die beiden Referenzflags sind
standardmäßig aus; ihre aktivierten Zweige einschließlich BF16→FP32-Routengewichten,
Shared-Expert-Kombination und Rückfall bei mehr als4Zeilen sind im selben
Rust-Dispatcher portiert. Keine Auswahl anhand eines Teilbenchmarks.
- 16 Routerfälle mit 48 Hashes, einschließlich 2048x512 sowie 4096/4097-Softmaxgrenze.
- 48 vollständige Standard-MoE-Fälle gegen die tatsächliche MTPLX-Klasse.
- 64 weitere Klassenaufrufe mit beiden Fusionsflags aktiv: Decode/Verify, Gruppenkombinationen und5/7-Zeilen-Fallback. Optionale Normalisierung jeweils an/aus.
- Modellabmessungen K2560/I640/E512 sind im Standardpfad bei 1/7/2048 Zeilen und in den fusionierten Pfaden bei1/4Zeilen enthalten; synthetische Gewichte, kein vollständiger Modelllauf. Alle Ausgabehashes bitgenau.
Gemeinsamer Prüflauf:13Tests ausgeführt,13bestanden,0fehlgeschlagen,0ignoriert;
438Fälle/664Hashes. Jede verbundene Testkette bleibt in einem Command Buffer.
Der Quellcheck umfasst13Custom-Bodies/33Einträge und10Runtime-Einheiten mit
35Einträgen; GatherAxis und dessen Stride-Helfer werden unverändert übernommen.
Beleg: local-eval-results/20260906-mtplx-port/connected-moe-combined-check.log.
Weiter offen: Diese Operationen bleiben cfg(test). Der alte Produktgraph
wurde nicht auf diesen Stand umgestellt. P07 umfasst außerdem die nicht
Sanitize-fusionierten Modulpfade; die übrigen Graphabschnitte, State/Cache,
Submission und die zusammenhängende BF16-Produktmigration bleiben offen.
Exakte Blockausgaben beweisen weder Scheduling-Parität des vollständigen
Modells noch UI-Responsiveness oder Gesamtperformance. P01–P16 nicht geschlossen.
Getrennte MoE-Projektionen und verbundene Normmodule
Der kanonische MoE-Dispatcher bildet nun auch SwitchGLU und Qwen3NextMLP
ohne Sanitize-Fusion ab. Expert- und Shared-MLP können unabhängig zusammengepackt
oder getrennt vorliegen; getrennte Gate-/Up-Projektionen behalten ihre eigenen
Quantisierungsgruppen und ihre ursprüngliche Aufrufreihenfolge. Die fusionierten
Decode-/Verify-Kernel werden bei separaten Experten trotz aktivierter Flags wie
in MTPLX nicht gewählt. Keine Änderung an der Standard-Flagbelegung.
Der ursprüngliche swiglu-Compileraufruf wurde mit dem bestehenden lokalen
Beobachter erfasst. Receipt tests/fixtures/mtplx-swiglu-jit.json, voller
beobachteter Quellhash:
bf78eee5cf96ea7c112c4e61546c12bcacf57fe512e0572182604cb94137510b.
Alle 19 erzeugten Varianten sind unverändert mit lokalen Host-Aliassen exportiert.
Rank-3 und Rank-5 liefern nach reiner Symbolnormalisierung denselben Rechencode.
Anders als beim fusionierten Pack ist SwiGLU hier ein gemeinsamer kompilierter
Aktivierungs-/Multiply-Aufruf mit zwei separaten Projektionseingaben.
108 zusätzliche Aufrufe der tatsächlichen MTPLX-MoE-Klasse prüfen getrennte und gemischte Modulbelegungen, Gruppen 32/64, Normalisierung an/aus, Sort-/Matmul- Grenzen und aktivierte Fusionsflags. Darunter E512/K2560/I640 mit 1/7/2048 Zeilen. Alle 108 Ausgabehashes sind exakt; die bisherigen 438 Fixtures blieben unverändert.
Außerdem sind GroupedRMSNorm (HC/PLE) und SigmoidRMSNormGated (GDN) als
verbundene Rust-Operationen mit den unveränderten Runtime-Shadern portiert.
Erhalten bleiben ungewichtete Gruppen-RMS vor separater Vollbreitengewichtung,
BF16-Rundung vor dem FP32-Sigmoid-/Multiply-Epilog, fehlendes Gate sowie das
strided Z-View aus der fusionierten GDN-Eingangsprojektion. 25 direkte Aufrufe
der tatsächlichen Normklassen sind exakt, einschließlich 2K Zeilen, Loop-/
Vektorisierungsgrenzen und GDN-Zeilenstride 16480. Das ist noch nicht der komplette
gestufte GDN-Forward einschließlich Conv, compute_g, Rekurrenz und Capture-State.
Gemeinsamer Lauf: 14 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
571 Fälle / 797 exakte Hashes. Jede verbundene Kette bleibt in einem Command Buffer.
Quellcheck: 13 Custom-Körper / 33 Einträge, 11 Runtime-Einheiten / 54 Einträge.
Beleg: local-eval-results/20260906-mtplx-port/separate-moe-norm-combined-check.log.
P07 bleibt wegen der Produktintegration offen. P06/P08/P09/P10 sowie die übrigen
Host-/State-/Scheduling-Aufgaben bleiben offen; keine Gesamtperformance-Abnahme.
Verbundener gestufter GDN-Forward und compute_g
gated_delta_update ist einschließlich des tatsächlichen kompilierten
compute_g, BF16-Sigmoid, initialem FP32-Nullzustand, Maske und ursprünglicher
Rekurrenz verbunden. Das JIT-Receipt bewahrt alle 19 erzeugten Varianten;
BF16-Add/LogAddExp vor den FP32-Exponentialoperationen bleibt unverändert.
80 direkte Referenzaufrufe mit zwei aufeinanderfolgenden Updates prüfen
kalte/vorhandene Zustände, Masken und A/B-Zeilenstride 48/16480 bis 2K Zeilen.
Alle 320 Hashes sind exakt.
Der gestufte GatedDeltaNet-Forward mit fusionierter Eingangsprojektion ist
jetzt bis zur Ausgangsprojektion verbunden: QKV-Maske, Conv-Zustandskonkatenation,
Tail beziehungsweise geklippte Cache-Längen mit originalem INT32-GatherAxis,
ursprüngliche Depthwise-Conv1D, SiLU, FP32-L2-Normalisierung mit BF16-Grenze vor
Q-Skalierung, Rekurrenz, Sigmoid-RMS und Ausgangsprojektion. Die Conv-Norm-
Fusionen für S1/S2–6 und die Output-Fusion behalten ihre Flag-/Form-/Masken-/
Längenbedingungen. Kalte Broadcast-Zustände werden am tatsächlichen
General-Copy-Punkt materialisiert; zusammenhängende Ein-Zeilen-Views werden
nicht zusätzlich kopiert. Bestehende Bindungen und unveränderte Shader werden
wiederverwendet; kein mathematisch ähnlicher Ersatzkernel.
130 Aufrufe der tatsächlichen MTPLX-Klasse prüfen Zeilen 1/2/4/6/7/32/2048, kalte/vorhandene Zustände, Masken, Fusionsflags und Längen unterhalb/in/oberhalb des gültigen Bereichs. Jeder Fall führt einen zweiten Forward auf beiden zurückgegebenen Zuständen aus. Verglichen werden finaler Hidden-Output, Conv-Zustand, FP32-Delta-Zustand sowie die erfassten Q/K/V-Zeilen. Alle 780 Hashes sind bitgenau; beim Export blieben die vorherigen 651 Receipts unverändert.
Gemeinsamer Abschlusslauf: 16 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
781 Fälle / 1.897 exakte Ausgabehashes. Verbundene Ketten bleiben in einem
Command Buffer. Quellcheck: 13 Custom-Körper / 33 Einträge, 17 Runtime-Einheiten /
81 Einträge. Beleg:
local-eval-results/20260906-mtplx-port/staged-gdn-combined-check.log.
P06 bleibt offen. Diese Operationen sind weiterhin cfg(test) und ersetzen
noch nicht den produktiven FP32-Qwen-Graph. Separate GDN-Eingangsprojektionen,
vollständige Advance-/Capture-Commit-Zustandsführung, No-Cache-/Batch-Hostpfade
und gemeinsame Submission-/Concurrency-Semantik sind noch nicht vollständig
angebunden. QSA/HC/PLE, Sampling/MTP und die zusammenhängende BF16-Produktmigration
bleiben ebenfalls offen. Ausgabeidentität dieser Module ist weder eine
Scheduling- noch eine UI-/Harness- oder Gesamtperformance-Abnahme. Kein
Performance-Auswahlversuch, keine Rücknahme und kein Abschluss von P01–P16.
Gemeinsame GDN-Projektion und tatsächliche Forward-Auswahl
Die bisher doppelte Eingangsprojektion in gestuftem und fusioniertem Forward
ist durch gdn_project ersetzt. GdnInputWeights bildet sowohl den fusionierten
Pack als auch die vier separaten QKV-/Z-/B-/A-Module ab. Getrennte Module behalten
ihre eigene Quantisierung und Aufrufreihenfolge; ihr zusammenhängendes Layout
wird nicht wie ein fusioniertes View mit Zeilenstride 16480 behandelt. Die
bestehenden Affine-/GPU-Bindungen werden wiederverwendet, keine Shaderänderung.
gdn_forward übernimmt die Branch-Priorität für die installierte B=1-Geometrie:
fusionierter Schritt nur bei entsprechendem Flag, lebendem FP32-Delta, einer
unmaskierten Zeile, vorhandenem Cache, fehlenden Längen und inaktivem
Verify-Capture. Ein fehlender Conv-Zustand bei vorhandenem Delta wird wie in
der Referenz materialisiert. Ein vollständig kalter Aufruf startet gestuft;
der Folgeschritt kann mit dem zurückgegebenen Delta in den fusionierten Pfad
wechseln. Die Flags sind keine neu eingeführten Produktdefaults.
264 zusätzliche Aufrufe der tatsächlichen MTPLX-Klasse decken fusionierte, getrennte und gemischt Q4/Q8-quantisierte Eingänge mit Gruppen 32/64 ab; Zeilen 1/2/6/7/33/2048, kalte/vollständige/Conv-only/Delta-only-Zustände, Flags aus/an/ Step-only, Masken, Cache-Längen und Verify-Capture. Zwei aufeinanderfolgende Forwards behalten jeweils beide Zustände. Alle 792 Ausgabehashes und die tatsächlichen Step-/Conv-Branchentscheidungen sind exakt. Der Export prüfte außerdem alle bisherigen 781 Receipts unverändert.
Gemeinsamer Prüflauf: 17 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
1.045 Referenzfälle / 2.689 exakte Ausgabehashes. Belege:
local-eval-results/20260906-mtplx-port/gdn-forward-check.log und
gdn-forward-combined-check.log (kompakter Sammelbeleg; dessen erste Tool-Ausgabe
war gekürzt, der finale Teststatus ist vollständig). Quell-/Format-/Whitespace-
Prüfungen bestanden. Keine Performanceauswahl oder Rücknahme.
Die zuvor offene separate GDN-Eingangsprojektion ist damit auf Modulebene angebunden, nicht im Produktgraph. P06 bleibt für vollständige Advance-/ Capture-Commit-Zustandsführung, No-Cache-/Batch-Hostpfade und gemeinsame Submission-/Concurrency-Semantik offen. Das gesamte Modell bleibt auf dem alten Produktpfad; sämtliche übrigen Portierungs- und Gesamtperformancepflichten bleiben unverändert. Der bestehende Capture-Commit muss mit QSA-/PLE-Snapshots und gemeinsamer Validierung vor jeder Cache-Mutation portiert werden, nicht als isolierter GDN-Replay-Ersatz für den vollständigen Commit.
QSA-Indexer-Vorbereitung und verbindliche restliche Pfadabdeckung
Die tatsächliche QSA-Aufrufkette wurde in qwen4_exp.py von QSACache über
QSAIndexer bis Attention verfolgt. Die folgenden Teile gehören gemeinsam zu
P08; sie sind keine wahlweisen Performance-Optimierungen:
| Abschnitt | Referenzverhalten / verbleibende Verpflichtung |
|---|---|
| Raw-/Pool-/KV-Zustand | Geometrisches Wachstum, reservierte Kapazitäten, logische Frontier, Trim/Restore; FP32-transponierter Pool-Mirror einschließlich Neuaufbau/Invalidierung |
| Query-/Key-Vorbereitung | Quantisierte Projektion oder vorhandene QK-Zeilen, RMS/partielles RoPE, vollständige Key-Blöcke; fusionierte und Eager-Fallbackpfade |
| Auswahl | Cache-Updates vor Dense==Sparse-Rückgabe; ursprünglicher Eager-Score/Top-k, Legacy-Fusion für Decode/kleine Verify-Fenster, gekachelter Prefill-Selektor und expliziter Compiled-State-Pfad |
| Ergebnisformen | blocks, prefill_blocks, row_tokens, dense_mask, update_only; logische Grenzen und Scratch-/Kapazitätsbedingungen, kein stiller Retry nach Dispatchfehlern |
| Attention-Verbraucher | Decode-Flash-Skip, Prefill-Flash, gekacheltes Prefill-Gather, Rows-Gather, Decode-Gather und Dense-SDPA; Masken/kausaler Tail/KV-Stride und Output-Gate erhalten |
| Vision | M-RoPE und Dense-Causal-Verbrauch bei unverändert weiter gepflegtem QSA-Indexer-/Cache-Zustand |
Umgesetzt ist jetzt die fusionierte Indexer-Vorbereitung mit den beiden
unveränderten Körpern aus qsa_indexer_prepare.py: Query-RMSNorm/partielles RoPE
und FP32-Blockmittelwert/BF16-Rundung/RMSNorm/RoPE für Keys. Der Exporter liest
die Funktionsliterale als AST, schützt den Quelldateihash und löst nur Includes,
Headerparameter und Einstiegspunkt-ABI auf. Stride-Metadaten behalten den
ursprünglichen constant int64_t-Adressraum. Die Spezialisierung entspricht dem
vorhandenen Modell: H4/D128/Rotary64/Ratio4/Epsilon1e-6/Attention-Scale1.
Andere geometrische Konfigurationen sind dadurch nicht als portiert behauptet.
qsa_project_prepare verbindet die bestehende quantisierte Affine-Operation
mit dem ursprünglichen Query-Kernel; Raw-Key-Views behalten Zeilenstride 640.
105 zusätzliche Referenzfälle prüfen Query-Vorbereitung, Key-Pooling und die
verbundene Projektion/Vorbereitung/Pooling-Kette: bis 2K Zeilen, 512 Key-Blöcke,
strided und Stride-2-Views, große absolute Positionen, Q4g64/Q8g64/Q8g32. Die
Frequenzen stammen unverändert vom tatsächlichen MTPLX-Modell. Alle 129 Hashes
sind exakt; sämtliche vorherigen 1.045 Receipts blieben beim Export unverändert.
Gemeinsamer Prüflauf: 18 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
1.150 Referenzfälle / 2.818 exakte Ausgabehashes. Vollständiger Beleg:
local-eval-results/20260906-mtplx-port/qsa-prepare-combined-check.log.
Quellcheck: 15 Custom-Körper / 35 Einträge plus 17 Runtime-Einheiten / 81 Einträge.
Format- und Whitespace-Prüfungen bestanden.
P08 bleibt offen: Der verbundene Vorbereitungstest ist nicht der vollständige
Indexer mit Cache/Selektion und nicht der Attention-Forward. Die übrigen
Tabellenabschnitte, Eager-Fallback und Produktintegration sind noch ausstehend.
Der kanonische Rust-Pfad bleibt cfg(test); weder UI-/Harness-Verhalten noch
Gesamtlaufzeit oder das all-model ±2%-Ziel wurden hiermit abgenommen.
QSA-Cache-Lebenszyklus einschließlich Session-State-Aliasing
QsaCache verbindet Raw-Key-Schreibzugriffe, ursprüngliches Key-Pooling,
geometrisches Indexer-Wachstum, KVCache-Schrittwachstum, Reservierung, Trim,
State-Restore und den abgeleiteten FP32-Mirror. Strided KV-Slices werden am
ursprünglichen Copy-Punkt materialisiert. Nur vorhandene Original-Copy-/Cast-
und Pooling-Kernel werden verwendet. Die Speicherzählung entspricht
QSACache.nbytes, einschließlich Backing-Kapazitäten und ohne FP32-Mirror.
Der Referenztest hat eine falsche Annahme korrigiert: State-Leaves sind nicht
generell immutable. Der Setter übernimmt die Python-Array-Objekte; __setitem__
ersetzt deren Descriptor und ist über dieselben Objekt-Aliase sichtbar. Separate
Slices teilen dagegen nur Storage. Rust bildet beide Ebenen getrennt mit lokalen
Rc und RefCell ab; beim Wachstum wird wie in MTPLX ein neues Objekt gebunden.
Dieser Unterschied wird durch erhaltene Snapshots nach Restore/Trim/Write geprüft,
nicht durch angepasste Sollwerte verdeckt.
44 zusätzliche Zustandsübergänge mit 536 Ausgabehashes stimmen bitgenau überein:
kalter und vorreservierter Cache, mehrere Kapazitätsgrenzen, drei gleichzeitig
gehaltene Snapshots, Fortsetzung nach Restore, vollständiger Trim und erneuter
Aufbau. Verglichen werden auch ungenutzte Buffer-Bereiche und der Mirror.
Alle 1.194 Referenzfälle wurden erneut ausgeführt; vorherige Hashes unverändert.
Gemeinsamer Prüflauf: 19 bestanden, 0 fehlgeschlagen, 0 ignoriert;
1.194 Fälle / 3.354 exakte Hashes. Beleg:
local-eval-results/20260906-mtplx-port/qsa-cache-combined-check.log.
P08 und Produktintegration bleiben offen. Der Cache-Port bleibt zusammen mit
den bisherigen kanonischen Operationen cfg(test). Vollständige QSA-Selektion,
Attention und Compiled-Indexer-State-Commit sind noch anzubinden. Dies schließt
weder den Audit noch UI-/Harness- oder Gesamtperformance-Parität ab.
Ursprüngliche QSA-Selektion und verbundene Cache-Ausführung
qsa_indexer_select.py ist mit unverändertem gemeinsamen Header, Selektorkörper
und allen drei Epilogen (blocks, dense_mask, row_tokens) übernommen.
metal/mtplx-qsa-select.json enthält die AST-extrahierten Originalteile samt
Quelldatei-/Teilhashes. Rust setzt die ursprünglichen Header-Literale für die
jeweilige Backing-Kapazität ein; weder Laufzeitparameter statt Compile-Konstanten
noch feste Testkapazitäten ersetzen die Referenzspezialisierung. Die bestehende
native Pipeline-Bindung kompiliert diese Formen mit MTPLXs Safe-Math- und
Metal-Sprachversionsauswahl und verwendet ihren vorhandenen Cache weiter.
Die verbundene Host-Kette umfasst Raw-Key-Schreiben, ursprüngliches Pooling,
Query-Vorbereitung, Selektion und KV-Fortschreibung. _select_fused begrenzt
wie die Referenz den Score-Scratch pro Dispatch auf 32 MiB durch Query-Chunking,
nicht History-Kürzung. Chunk-Ausgaben werden mit den ursprünglichen typisierten
GeneralGeneral-Copies zusammengefügt; die dichte Maske bleibt ein logischer
Slice der kapazitätsbreiten Ausgabe. Die allgemeine Metal-Bindung verwirft keine
Byte-Offsets pauschal wegen einer nur für breitere Typen passenden Vierergrenze.
84 neue Referenzfälle / 168 Hashes sind exakt: BF16/FP32 und gemischte Operanden, TF32 an/aus, Strides, leere logische Historie, kausale Grenzen, Padding und All-zero-Ties; außerdem tatsächliches Host-Chunking bei 65.536 reservierten Blöcken sowie drei aufeinanderfolgende Cache-Forwards. Header und vollständiger Selektorkörper stimmen zusätzlich mit den tatsächlich erzeugten MTPLX-Quellen überein. Alle vorherigen 1.266 Receipts blieben beim erneuten Export unverändert.
Gemeinsamer Prüflauf: 21 bestanden, 0 fehlgeschlagen, 0 ignoriert;
1.278 Fälle / 3.522 exakte Hashes. Beleg:
local-eval-results/20260906-mtplx-port/qsa-select-combined-check.log.
Offen bleiben der große vektorisierte Prefill-Selektor, Eager- und Compiled-
Indexerzweige, Attention-Verbraucher und die zusammenhängende Produktintegration.
Der kanonische Pfad ist weiter cfg(test). Insbesondere nutzt das ursprüngliche
concatenate_gpu einen Concurrent-Bereich; Ressourcenabhängigkeiten, diese
Concurrency und automatische Commit-Grenzen sind gemeinsam in P05 zu portieren.
Die exakten Ergebnisse hier sind kein Scheduling- oder Gesamtperformance-Beleg;
kein P01–P16 geschlossen und keine Optimierung per Mikrobenchmark verworfen.
Ursprünglicher QSA-Prefill: beide Score-Produzenten, Top-k und Cache-Fortsetzung
Die beiden Prefill-Stufen aus qsa_indexer_prefill.py sind verbunden portiert:
der ursprüngliche H4/D128-TensorOps-Score-Kernel (16 Query-Zeilen × 32 Keys pro
Threadgroup) und der separate adaptive Insertion-/Radix-Top-k-Körper. Header,
Körper und Epiloge bleiben unverändert; mtplx-qsa-select.json enthält zusätzlich
die gepinnten Prefill-Quellen. Die vorhandene Pipeline-Kompilierung und typisierte
Ausgabe-Verkettung werden gemeinsam mit dem Legacy-Selektor benutzt.
MPP lädt über die ursprünglichen Strides ohne versteckte Contiguous-Copy. Der Top-k-Wrapper materialisiert dagegen nichtkontiguierliche FP32-Score-Views am ursprünglichen General-Copy-Punkt. Beide Fälle sind gegen echte Referenzaufrufe geprüft. Die producerabhängige 128-MiB-Planung samt Alignment-Abrundung ist übernommen: eine Score-Ebene für MPP, H4+1 für den allgemeinen FP32-Produzenten. Eine irreduzible Zeile darf wie in MTPLX das Budget überschreiten. Ein ausgewählter MPP-Kernel fällt bei Fehlern nicht auf einen anderen Pfad zurück.
Die gemeinsame Rust-Funktion qsa_prefill enthält jetzt auch MTPLXs allgemeinen
FP32-Score-Zweig: Cast, Matmul, ReLU pro Kopf, Kopf-Summe und Skalierung. Die
Rust-Dispatch-Auswahl übernimmt matmul.cpp der gepinnten Runtime für H4/D128
auf M5 Max einschließlich GEMV, regulärem Steel/NAX und beiden Split-K-Varianten.
Alle Shader stammen unverändert aus der gepinnten metallib. Vector-Casts erhalten
transponierte/gebroadcastete Speicherlayouts; General-Casts materialisieren Views.
Matmul prüft Transposition und bereits gebroadcastete Operanden vor der
Batch-Zusammenfassung. Der Pool-Cast wird einmal über alle Chunks gehalten;
Top-k und typisierte Verkettung sind für beide Produzenten gemeinsam.
384 neue Score-Fälle decken BF16/FP32-Queries, acht Layoutkombinationen, bis 2K
Query-Zeilen und den echten MLX_ENABLE_TF32=0/1-Runtime-Schalter in separaten
Prozessen ab. 160 der 192 Form-/Typ-Paare haben tatsächlich unterschiedliche
TF32-an/aus-Referenzergebnisse; beide Varianten sind jeweils bitgenau. Dazu kommen
96 verbundene Prefill-Fälle mit allen vier BF16/FP32-Operandenpaaren, allen drei
Ausgabeformen und erzwungenem Chunking einschließlich Alignment-Abrundung.
qsa_prefill_cached verarbeitet den gültigen Pool-Ausschnitt wie der große
MTPLX-Prefill-Zweig, nicht die reservierte Kapazität des Legacy-Selektors. Der
fortlaufende Cache-Test hängt nach 1/4/7 Zeilen einen vollständigen 2K-Prefill an;
Query-Vorbereitung, Raw-Writes, Pooling, Selektion und KV-Fortschreibung bleiben
verbunden. Alle drei Selektions-Ausgabeformen sind geprüft.
159 neue Fälle / 284 Hashes: Kachelränder, bis 2K Query-Zeilen, bis 65.536
Key-Blöcke, Stride-2-/gepaddingte Score-Views auch mit nichtkonstanten Werten,
kausale Grenzen, Null-/Einser-Ties, kurze/lange Radix-Kandidatenlisten, erzwungene
Chunk-/Concat-Grenzen und reale Cache-Fortsetzung. Die vorherigen Receipts
blieben bei den erneuten Referenzexporten unverändert. Gemeinsamer Prüflauf
einschließlich der 480 zusätzlichen FP32-/Producer-Fälle:
25 bestanden, 0 fehlgeschlagen, 0 ignoriert; 1.917 Fälle / 4.382 exakte Hashes.
Beleg: local-eval-results/20260906-mtplx-port/qsa-f32-prefill-combined-check.log.
Nicht abgeschlossen: vollständiger Eager-Indexer,
Compiled-State/Graph-Bank, Attention-Verbraucher, vollständige Branch-Auswahl,
Scheduling und Produktintegration. Die unterstützte M5-Prefill-Kette wird nicht
als Ersatz für diese Zweige ausgegeben. Der kanonische Port bleibt cfg(test);
keine Änderung der UI-Performance behauptet, kein P01–P16 geschlossen und kein
Gesamtbenchmark oder Rücknahmeentscheid vor der vollständigen Integration.
Eager-Indexer: Selektion, Kachel-Eval und sämtliche Ausgabeformen
Der kanonische Rust-Port enthält jetzt auch die untiled _select_eager-Kette:
kausale Blockgültigkeit, FP32-Matmul/ReLU/Kopf-Summe/Skalierung, where,
block_id * 1e-12-Tie-Break und die originale Runtime-ArgPartition-Ausführung
(vollständiger Argsort). Die letzte K-Spalten-View behält den ursprünglichen
Zeilenstride. Für flash_prefill folgen originale Int32-Sortierung,
Int64-Indexkonvertierung, Bool-GatherAxis und Nullsetzen ungültiger Slots.
Dense-Maske, Rows-Gather sowie beide Decode-Ausgaben (Flash-Blöcke und
Gather-Tokenliste) sind ebenfalls verbunden. Dense verwendet den originalen
Bool-ScatterAxis, Gültigkeit, Repeat/Concat und die Tail-/Kausalmaske. Rows-Gather
behält die Argsort-Reihenfolge, liefert K*4+4 gepaddingte Tokens mit Gültigkeit
und setzt ungültige IDs auf null. Decode sortiert chronologisch und hält die
Tail-Grenze auf dem Host; Flash hat wie in MTPLX Vorrang vor Gather. Die für diese
beiden lazy Ausgaben tote Dense-Maskenexpression wird nicht ausgeführt.
GatherAxis/ScatterAxis verwenden unveränderte Originalkörper mit den benötigten
Templatespezialisierungen; kein Ersatzkernel. Cast, Sort und Vektor-Dispatch
werden zwischen den Epilogen geteilt.
Die Referenzreceipts stammen aus tatsächlichen QSAIndexer._select_eager-
Aufrufen. Beobachter reichen where/argpartition unverändert weiter und lesen
die realen Zwischenwerte; die Blockausgabe wird über den echten Prefill-Phasen-
und Konfigurationspfad ausgewählt. 60 Zwischenwert- und 24 verbundene Blockfälle
prüfen BF16/FP32, Null-Ties, kausale Grenzen, bis 2K Queries und bis 65.536 Blöcke,
jeweils mit dem echten TF32-Runtime-Schalter an/aus. Hinzu kommen 144 Dense-,
108 Rows-Gather- und 72 Decode-Fälle, einschließlich Tail-Längen 0/1/3 und
gleichzeitig gesetzten Flash-/Decode-Gather-Schaltern. Insgesamt prüfen 408
Eager-Fälle die echten MTPLX-Ausgaben bzw. Zwischenwerte.
_tiled_topk ist an dieselbe Score-/Ranking-Kette angeschlossen. Block-/Tie-
Vektoren und der FP32-Pool werden geteilt. Jede Kachel wartet synchron auf das
Top-k-Ergebnis, bevor die nächste entsteht; kein Ersatz durch asynchrones Flush.
Score-Scratch wird nach der Kachel freigegeben, die ausgewerteten ArgPartition-
Views bleiben bis zum originalen GeneralGeneral-Concat erhalten. Der Indexstride
wechselt dabei von N auf K; Gültigkeit behält ihren N-Stride. Alle Epiloge beachten
beide Strides. Der ganze Blockgültigkeitsausdruck folgt erst nach den Kachel-Evals.
qsa_eager_output entscheidet die Rückgabe nun gemeinsam in Referenzreihenfolge:
Prefill-Blöcke, Decode-Flash, Decode-Gather, ungekächeltes Rows-Gather, Dense.
Die gemeinsame Large-Prefill-Berechtigung ist weiterhin ein Eingabeparameter;
ihre vollständige Verknüpfung mit Indexer/Compiled-Core gehört zur offenen
Indexer-Integration. Die neuen Tests wählen nicht selbst den erwarteten Epilog,
sondern übergeben dieselben Schalter wie der MTPLX-Aufruf. Insbesondere bleibt
Gather eingeschaltet, wenn der gekachelte Zweig trotzdem Dense zurückgeben muss.
132 zusätzliche Fälle / 198 Hashes prüfen echte Kachel-Eval-Aufrufe, 2K Queries,
65.536 Blöcke, Stride-2-FP32-Queries, Tail 0/1, Kachelreste und die Abschaltung
der Kachelung bei Kachelgröße >= Query-Zeilen. 108 Fälle sind tatsächlich
gekachelt; 24 prüfen diese Abschaltgrenze. Die Referenzreceipts erfassen die
unverändert weitergereichten mx.eval-Aufrufe. Das beweist nicht die allgemeine
Graph-Tape-/Allocator-/Concurrency-Parität innerhalb einer Eval-Grenze.
Gemeinsamer Korrektheitslauf: 26 bestanden, 0 fehlgeschlagen, 0 ignoriert;
2.457 Fälle / 5.240 Hashes, davon 540 Eager-Fälle. Quellenexport, Formatierung
und Diff-Whitespace-Prüfung bestanden. Erneute Originalexporte bestätigen alle
1.947 Default-/TF32-an- und 510 TF32-aus-Receipts unverändert. Beleg:
local-eval-results/20260906-mtplx-port/qsa-eager-tiled-combined-check.log.
Eager-Vorbereitung im Projektions- und Cache-Pfad
Die Eager-Query-/Pool-Vorbereitung ist für die installierte BF16-Geometrie (Q H4/D128, Pool H1/D128, Rotary64, Ratio4, Epsilon1e-6, Skalierung1) verbunden. Nichtkontiguierliche Projektionsslices werden vor RMSNorm mit der originalen General-Copy materialisiert. Pooling bleibt FP32-Summe mal 0,25 mit anschließendem BF16-Cast vor RMSNorm. RoPE verwendet die ursprünglichen Arange-/Cast-/Concat-, Cos/Sin-, BF16-Negative- und FP32-Multiply/Add-Schritte samt abschließendem BF16-Cast und unverändertem Pass-through-Anteil. Kein Ersatz durch den fusionierten Kernel; keine neuen Shaderkörper. General-Copy und die vorhandenen Norm-/Cast-/ Concat-Dispatcher werden gemeinsam genutzt.
qsa_project_prepare und QsaCache::extend_pooled besitzen jetzt beide
Vorbereitungszweige. Ihre Zwischenpuffer werden durch die verbundenen Operationen
bis zur Auswertung gehalten. 105 neue Originalfälle prüfen Query-, Pool- und
quantisierte Projektionsketten, einschließlich Padding/Stride2, hoher Positionen
und 2K-Zeilen. 44 zusätzliche echte QSACache-/KVCache-Übergänge prüfen Eager-
Pooling bei Wachstum, Reservierung, Trim, Snapshots/Restore und Spiegel-Neuaufbau.
Die bisherigen 2.052 Default-/TF32-an-Fälle blieben beim letzten vollständigen
Originalexport unverändert; hinzu kamen die 44 Eager-Cache-Fälle.
Der Eager-Selektions-Test prüft nun auch die tatsächliche Anzahl abgeschlossener
Command Buffer über die vorhandenen GpuBusyStats: genau ein Abschluss je
beobachtetem MTPLX-Kachel-Eval plus ein finaler Ausgabe-Batch. Dies ersetzt nicht
den weiterhin offenen Nachweis der allgemeinen Graph-/Scheduling-Parität.
Gemeinsamer Korrektheitslauf: 26 bestanden, 0 fehlgeschlagen, 0 ignoriert;
2.606 Fälle / 5.905 Hashes, davon 210 Vorbereitungsfälle und 88 Cache-Übergänge.
Quellenexport, Formatierung und Diff-Whitespace-Prüfung bestanden. Beleg:
local-eval-results/20260906-mtplx-port/qsa-eager-preparation-combined-check.log.
Verbundener nicht-kompilierter Indexer-Aufruf
qsa_indexer_rows_uncompiled bildet den Abschnitt von _call_rows nach der
Compiled-Entscheidung zusammenhängend ab: eigene quantisierte Projektion oder
mitgelieferte Q/K-Zeilen, Query-Vorbereitung, Raw-Write, Pool-Fortschreibung und
Selektion. Die bestehenden Ketten werden wiederverwendet. Im Dense==Sparse-
Bereich bleibt die ungenutzte Query-Vorbereitung wie in MTPLXs Lazy-Ausführung
unausgewertet. Der KV-Offset wird erst vom nachfolgenden Attention-Schritt erhöht,
nicht vor der Indexer-Selektion.
Die Zweigauswahl berücksichtigt Phase, früheste Query-Position, Prefill-Mindest-
breite, Gather-Schwellen und Decode-Gather-Ausschluss des Legacy-Fused-Zweigs.
Large-Prefill verwendet die logische Pool-Sicht, Legacy-Fused die reservierte
Backing-Kapazität; Eager verwendet den gespeicherten FP32-Spiegel. Die Rückgabe
beschränkt sich auf die vom Modell konsumierten Ausgaben und hält die übrigen
Kernel-Ausgabepuffer bis zur Auswertung. Der gemeinsame Rückgabetyp heißt deshalb
jetzt QsaIndexerSelection, nicht mehr QsaEagerSelection.
92 Originalaufrufe in 24 fortlaufenden Sequenzen prüfen kalten Start, den Budgetübergang, projizierte und mitgelieferte Q/K-Zeilen (704er Zeilenstride), 2K-Zeilen, 32K-Historie, Flash/Gather-Vorrang, aktivierte Kachelung und die Prefill-Schwelle auf beiden Seiten. Die Fixtures rufen den echten MTPLX-Indexer auf; Beobachter reichen seine Selektionsmethoden unverändert weiter. Rust prüft den tatsächlich gewählten Pfad, 82 Selektionshashes, 268 zusätzliche Raw-/Pool-/ Spiegelhashes, Kapazitäten/Offset und abgeschlossene Command Buffer. Die numerische Prüfung wertet Cache-Zustände explizit aus; sie ist kein Beleg für den vollständigen Lazy-Graph-Lebenszyklus einer Modellgenerierung.
Gemeinsamer Korrektheitslauf: 27 bestanden, 0 fehlgeschlagen, 0 ignoriert;
2.698 Fälle / 5.987 Ausgabehashes plus 268 Zustands-Hashes. Quellenexport,
Formatierung und Diff-Whitespace-Prüfung bestanden. Der erneute Originalexport
bestätigt alle 2.188 Default-/TF32-an-Fälle unverändert, einschließlich der
Indexer-Sequenzen und Zustands-Hashes. Beleg:
local-eval-results/20260906-mtplx-port/qsa-indexer-routes-combined-check.log.
Weiter offen: Compiled-Eignungsentscheidung und Compiled-State/Graph-Bank,
Attention, Scheduling und
Produktintegration. Insbesondere ist die breiteabhängige BFS-Tape-Planung aus
Runtime transforms.cpp nicht durch serielles Rust-Encoding nachgewiesen.
Der explizit nicht-kompilierte Einstieg ersetzt keinen geeigneten Compiled-Pfad.
P05 und P08 bleiben offen; keine Gesamtmodell-/Performance-Parität behauptet.
Compiled-Cache-Voraussetzungen sind anschließend gegen die Referenz geprüft:
qsa_replay_capacity übernimmt die Power-of-two-Buckets einschließlich des
festen ceil(S/4)-Stagingfensters; ensure_compiled_backings berücksichtigt
ausstehende Reservierungen und materialisiert unberührte Backings. 108 reine
Kapazitätsfälle und vier echte _ensure_compiled_backings-Übergänge prüfen
unter anderem S=1025 und die Übernahme vorhandener Daten, ohne KV-Offset oder
logische Pool-Länge vorzeitig zu verändern. Acht weitere Fälle prüfen die
originalen dynamischen BF16-Kopien mit int32-GPU-Startwerten, 128/704-Stride
und bis zu 2048 Zeilen. Keine Host-Auslese der Startwerte. Die gemeinsame
Kopierfunktion nutzt dieselben bisherigen Kernel/Geometrien für statische
Aufrufe; nur dynamische Aufrufe binden die originalen int64-Offset-Leaves.
tools/mtplx-jit-reference.py --operation qsa-update --check führt den echten
Compiled-Indexer aus und prüft drei unveränderte erfasste Shader: Fused Clamp,
Multiply und Dynamic Offset. Alle drei sind jetzt im verbundenen
qsa_compiled_cache_window verwendet: Raw-Update, dynamische Clamp-Grenze,
festes Raw-Fenster, originales Pooling und Pool-Update. Der unveränderte
Runtime-Header ist ebenfalls übernommen. Die drei originalen Constant-CSE-
Layouts (obere Grenze null / gleich max_new / verschiedene Konstanten) sind
separat erfasst; Rust spezialisiert nur Formkonstanten und exportierte Symbole.
Eine zusätzliche Originalvariante mit 257/255 prüft diese Spezialisierung.
26 echte QSACompiledIndexerCore.select_qk_rows-Aufrufe prüfen die komplette
Cache-Ausgabe und unveränderte Eingangs-Backings: 104 zusätzliche Hashes,
640/704-Zeilenstride, unvollständige Blöcke, rückwärts verschobenes Poolfenster,
Kapazitätsgrenzen und S=2048. Startwerte bleiben GPU-Leaves; kein Zwischen-Eval
oder Frontier-Readback. Die Referenz hält Eingangs-Leaves während der Auswertung
fest. Damit ist ausdrücklich der nicht-donierende Kopierzweig geprüft,
nicht der Allokator oder das vollständige Graph-Replay. Eignungsentscheidung,
Graph-Bank, Donation, BFS-Tape, Modell-Aufrufintegration und
Produktionsintegration bleiben offen. Keine Modell-/Performance-Parität.
Neue Referenzfälle: tests/fixtures/mtplx-qsa-compiled-state.jsonl;
gemeinsamer Lauf: local-eval-results/20260906-mtplx-port/qsa-compiled-state-check.log.
Dieser frühere Voraussetzungslauf besteht mit 29 Tests, 0 fehlgeschlagen, 0 ignoriert und deckt
insgesamt 2.818 Fälle / 6.019 Ausgabehashes plus 268 Zustands-Hashes ab.
Quellenexport, frische JIT-Referenzprüfung, Formatierung und Diff-Prüfung bestehen.
Der anschließende verbundene Cache-Fenster-Lauf besteht mit 31 Tests,
0 fehlgeschlagen, 0 ignoriert: 2.844 Fälle / 6.123 Ausgabehashes plus
268 Zustands-Hashes. Alle vier Compiled-Quellenproben einschließlich des
unveränderten Runtime-Headers sind frisch reproduziert. Neue Fälle:
tests/fixtures/mtplx-qsa-compiled-window.jsonl; vollständiger Beleg:
local-eval-results/20260906-mtplx-port/qsa-compiled-window-check.log.
Der verbundene BF16-Q/K-Einstieg umfasst jetzt alle fünf festen Ausgabemodi
(update_only, blocks, row_tokens, dense_mask, prefill_blocks). Die
Query-Vorbereitung sowie Legacy-/Prefill-Top-k binden echte int32-GPU-Leaves;
bestehende Host-Aufrufe verwenden dieselben Dispatch-Funktionen. Die originale
kompilierte Positionsaddition wird auch für +0 ausgeführt. Vier unverändert
erfasste Add-Kernel prüfen die reine Formkonstanten-Spezialisierung. Die
Selektionskachelung verwendet die gesamte Pool-Kapazität, das jeweilige
Scratch-/Workspace-Budget und die originale Prefill-Abrundung auf 32 Zeilen.
66 echte QSACompiledIndexerCore.select_qk_rows-Aufrufe vergleichen sämtliche
Selektionsausgänge und unveränderte/aktualisierte Cache-Backings: 144 zusätzliche
Ausgabehashes und 264 Zustands-Hashes. Darunter sind gekachelte Legacy-Ausgaben,
Prefill mit 2048 Zeilen, 640/704-Stride und die reine Update-Route. Rust bestätigt
jeweils einen abgeschlossenen Command Buffer ohne Zwischen-Eval. Das beweist
die verbundene Q/K-Arithmetik im Retained-Input-Zweig, nicht das noch offene
Graph-Replay oder identische BFS-Reihenfolge. Neue Fälle:
tests/fixtures/mtplx-qsa-compiled-indexer.jsonl; Beleg:
local-eval-results/20260906-mtplx-port/qsa-compiled-indexer-check.log.
Gemeinsamer Lauf: 32 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
2.910 Fälle / 6.267 Ausgabehashes plus 532 Zustands-Hashes. Originalquellen,
frische Compiled-Add-/Update-Proben, Formatierung und Diff-Prüfung bestanden.
Der Hidden-Einstieg ist anschließend an denselben Q/K-Pfad angeschlossen:
qsa_compiled_indexer_hidden_retained führt die originale affine Quantisierung
vor Cache-Aktualisierung und Selektion im selben asynchronen Aufruf aus. Es
gibt keinen Zwischen-Eval oder abweichenden Selektionspfad. 132 echte
QSACompiledIndexerCore.select_hidden-Aufrufe prüfen 4-/8-Bit-Projektionen mit
Gruppengröße 32/64, alle fünf Modi und dieselben Kachel-/2K-Prefill-Grenzen:
288 weitere Ausgabehashes und 528 Zustands-Hashes. Die ursprünglichen 66
Q/K-Referenzfälle sind frisch unverändert reproduziert. Zusammen prüft der
verbundene Test 198 Aufrufe. Dies schließt die arithmetische Projektion ein,
nicht die offene Eignungsentscheidung, Graph-Bank, Donation/BFS oder den
produktiven Modell-Aufruf. Neue Fälle:
tests/fixtures/mtplx-qsa-compiled-hidden.jsonl; Beleg:
local-eval-results/20260906-mtplx-port/qsa-compiled-hidden-check.log.
Gemeinsamer Lauf: 32 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
3.042 Fälle / 6.555 Ausgabehashes plus 1.060 Zustands-Hashes. Formatierung,
Originalquellenexport und Diff-Prüfung bestanden. Keine neuen Metal-Kernel,
Modelldownloads oder Produktions-/Performance-Abnahme in diesem Schritt.
Die Host-Routenauswahl ist jetzt für den installierten B1/BF16/Ratio4-Vertrag
mit Cache-Commit und Ausgabeadapter verbunden (heute qsa_indexer_rows).
QsaIndexerOptions übernimmt Compiled-Schalter und kanonische Compile-Breite;
Prefill-Eignung verwendet den frühesten Query und den echten Phasenwert.
Die Eignungsprüfung läuft vor Kapazitäts-Bucketing, berücksichtigt fehlende
Backings, Cache-Lücken und Flash-Vorrang gegenüber Decode-Gather. 720 Aufrufe
der unveränderten MTPLX-Hostmethoden (12 Optionssätze × 30 Cache-Zustände ×
Hidden/QK) stimmen überein, einschließlich nicht-potenzförmiger Kapazitäten.
Das ist die Cache-/Phasenentscheidung für feste Modelldatentypen, kein Nachweis
beliebiger Source-/Norm-/Projektions-Datentyp- und Shape-Eignung.
108 zusätzliche vollständige Original-Indexer-Aufrufe in 28 fortgesetzten
Sequenzen prüfen die Verbindung von Eignung, Backing-Reservierung, GPU-Frontiers,
Rechenpfad und Host-Commit: 38 Compiled-Aufrufe sowie tatsächliche Eager-,
Prefill- und Update-only-Alternativen. Cache-Raw/Pool und logischer Frontier
werden ohne Readback ersetzt; ein früherer FP32-Mirror wird invalidiert;
KV.offset bleibt bis zur anschließenden Attention-KV-Aktualisierung unverändert.
Flash-/Prefill-/Gather-Ausgaben und der logische Ausschnitt der kapazitätsbreiten
Dense-Maske stimmen mit dem Original überein. Dispatched Fehler werden nicht
durch einen Eager-Fallback verborgen. Die 92 bisherigen Aufrufe verwenden
jetzt denselben verbundenen Rust-Einstieg mit abgeschaltetem Compiled-Schalter;
der gemeinsame Test prüft 200 Aufrufe einschließlich echter Command-Buffer-Zahl.
Neue Referenzen: tests/fixtures/mtplx-qsa-compiled-routes.json und
tests/fixtures/mtplx-qsa-indexer-connected.jsonl (98 Ausgabe-/282 Zustands-Hashes).
Gemeinsamer Lauf: 33 Tests bestanden, 0 fehlgeschlagen, 0 ignoriert;
3.150 Rechenfälle / 6.653 Ausgabehashes plus 1.342 Zustands-Hashes, zusätzlich
720 Host-Routingentscheidungen. Beleg:
local-eval-results/20260906-mtplx-port/qsa-connected-routing-check.log.
Originalkernel unverändert. Weiterhin ausdrücklich offen: Graph-Bank und
Parameteridentität, Donation/BFS/Allocator, vollständige Modell-/Produktintegration
und danach die Gesamt-Performanceabnahme. Der verbundene Testpfad verwendet
noch die ausdrücklich benannte Retained-Input-Ausführung; er ist kein Ersatz
für die fehlende Runtime-Parität und bleibt außerhalb des Produktpfads.
Die direkte Compiled-Rechenkette ist danach durch eine echte QSA-Graph-Bank
ersetzt worden (src/engine/metal/qwen_mtplx/qsa_graph.rs). Ein struktureller
Schlüssel erzeugt einmal die Primitiv-Knoten und ihren Ausführungsplan;
Wiederaufrufe binden die zehn aktuellen Array-Eingaben. Frontier-Werte und
Q/K-Strides sind keine Trace-Schlüssel. Query-/Key-Views, dynamische Updates,
ursprüngliche skalare Compiled-Operationen, Pool-/Query-Vorbereitung, MPP-/Topk-
oder Legacy-Selektion und jede einzelne Concatenate-Ausgabe bilden explizite
Abhängigkeiten. Die bisherigen direkten Compiled-Hidden-/QK-/Selektionsketten
sind entfernt, nicht als zweite Ausführung daneben behalten.
99 vor dem Eval exportierte optimierte MTPLX-Graphen prüfen Primitiv-Abhängigkeiten
und Mehrfach-Ausgaben für alle Modi, Kachelgrenzen und beide Einstiege. Evaluierte
Konstanten werden im Struktur-Fingerprint ausgespart; Originalshader und
numerische Ergebnisse bleiben separate Prüfungen. Die 2K-Constant-CSE-Variante
ist enthalten. Der Plan verwendet den Degree-/BFS-Algorithmus des gepinnten
mlx/transforms.cpp:180 mit Breitenlimit 20, spezialisiert auf einen Stream und
bereits evaluierte Eingaben. Dies ist noch kein globaler Modellgraph oder
Nachweis der tatsächlich überlappenden Metal-Encoder-Zeitlinie.
Alle 198 bisherigen Compiled-Rechenfälle laufen jetzt durch diese Graph-Bank;
ein Q/K-Layoutwechsel 640→704 muss denselben Graphen wiederverwenden. Die
108 fortgesetzten Original-Indexer-Aufrufe wurden frisch um echte
compiled_calls-/traces-/Entry-Zähler ergänzt; sämtliche bisherigen Inhalte
und Hashes blieben unverändert. Rust stimmt auch mit diesen Zählern überein,
einschließlich vier Wiederaufrufen ohne neue Trace. Parameterersetzung verwirft
die Bank; ein zusätzlicher Austausch-/Rücktausch-Test prüft Invalidierung und
erneuten Layout-Replay. Die noch testgebundene Buffer-Identität verhindert dabei
Verwechslungen durch wiederverwendete native Adressen, ohne den gegenwärtigen
Produkt-Buffer um Laufzeitaufwand zu erweitern.
Gemeinsamer Lauf 33/33 bestanden, danach der ergänzte Identitäts-Test
bestanden. Die bestehende Rechenfall-/Hash-Zahl bleibt unverändert; neu sind
99 Graphstruktur-Referenzen in tests/fixtures/mtplx-qsa-compiled-graphs.jsonl
und die Engagement-Zähler im verbundenen Fixture. Originalquellenexport,
Formatierung, Diff-Prüfung und cargo check --release --bin ds4-server für
die Nicht-Test-Konfiguration bestanden. Beleg:
local-eval-results/20260906-mtplx-port/qsa-graph-replay-check.log.
Weiter offen sind insbesondere Donation, frühzeitige Freigabe/Allocator,
modellweiter lazy Graph mit passender Root-/Stream-/Encoder-Ausführung,
generische Tensor-Eignung und die Produktintegration. Intermediates bleiben
in dieser Retained-Lane noch bis zum Aufrufende gehalten. P05/P16 und das
vollständige 2%-Ziel bleiben offen; keine Performance-Abnahme aus diesen Tests.
Die Lebensdauer der Graph-Zwischenwerte folgt nun dem letzten Verbraucher: Der gecachte Plan enthält die Freigabestellen, einschließlich aller Geschwister einer Mehrfach-Ausgabe. Nach einem Primitiv werden nicht mehr benötigte Graph-Referenzen gelöst; nur die echten Ergebnisblätter bleiben im Resultat. Block-/Raw-Start-Scratch gehört nicht mehr zum Graph-Ergebnis. Die GPU-seitige Freigabe ist davon getrennt: Rust überträgt besessene Puffer an einen Completion-Handler des bereits offenen Command Buffers. Es wird weder ein zusätzlicher Command Buffer angelegt noch ein Flush oder Wait ausgelöst. Leere Batches nehmen keinen Besitz an; ohne offene/ausstehende Arbeit erfolgt die Freigabe unmittelbar. Ein eigener Test prüft diese Besitzübergabe vor und nach einem asynchronen Flush. Die 198 Rechenfälle prüfen zusätzlich, dass am Aufrufende nur Ergebnisblätter übrig sind und keine ausgemusterten Graph-Blätter als versteckte Temporaries zurückgegeben werden. Die gezählten Graph-Blätter sind ausdrücklich keine Messung physisch bereits freigegebenen GPU-Speichers.
Der verschärfte Lauf mit DS4_METAL_UNRETAINED_COMMAND_BUFFERS=1 deckte vier
Invalid Resource-Fehler auf (Cache-Lifecycle, Compiled-Indexer, verbundene
Cache-Selektion und Indexer-Routing). Ursache: Die gemeinsame kanonische
Metal-Dispatch-Grenze hielt gebundenen Speicher nicht selbst bis zum GPU-Ende;
ein kurzlebiges Argument konnte vor Batch-Commit verschwinden. Das war durch
Metals Standard-Retention verdeckt. Korrigiert ist die gemeinsame Dispatch-
Grenze, nicht jeder betroffene Aufrufer: gebundene Metal-Ressourcen werden
dedupliziert bis zum Completion-Callback gehalten und dort explizit freigegeben.
Das entspricht dem Lifetime-Vertrag des gepinnten GPU-Evaluators; die native
Bridge hält nur Plattform-Ressourcen, Modell-/Graph-Orchestrierung bleibt Rust.
Compile und Dispatch haben zudem eigene Autorelease-Pools wie das Original
gpu::eval, damit Foundation-Temporaries nicht am Lebensende des Worker-Threads
hängen. Keine Kernelquelle, Dispatch-Geometrie oder Host-/GPU-Synchronisation
wurde dadurch geändert.
Der normale vollständige Lauf besteht mit 34/34 Tests; der verschärfte Lauf
nach der gemeinsamen Ressourcen-Korrektur ebenfalls. Rechen-/Graph-Fixtures
bleiben unverändert. Rohfehler und erfolgreiche Verifikation werden in
local-eval-results/20260906-mtplx-port/qsa-lifetime-check.log getrennt bewahrt.
Aktuelle vollständige Sammlung ist nun cargo test --release qwen_mtplx -- --include-ignored --test-threads=1, damit der neue Lifetime-Test im Graph-Modul
nicht durch den alten engeren Filter ausgelassen wird.
Donation verlangt nach MTPLX exklusiven Array-Descriptor und
exklusiven Data-Besitz, passende Elementgröße und höchstens 16 KiB Überhang.
Dabei zählen auch die noch ausstehenden GPU-Evaluator-Referenzen. Weder der
letzte Graph-Verbraucher noch ein einzelner Rc::strong_count beweist diese
Bedingungen. Ebenso offen: vollständiger Allocator, modellweiter lazy Graph,
Root-/Stream-/Encoder-Parität und Produktintegration. Keine UI-Stall-Behebung
oder Performance-Parität wird aus diesem noch testgebundenen Port abgeleitet.
Getrennter Array-/Data-Besitz im kanonischen Port
Die gemeinsame testgebundene Buffer-Schicht unterscheidet jetzt eine eindeutige
Array-/View-Identität vom gemeinsam referenzierten Data-Besitz. Auch verschachtelte
native Views teilen denselben Rust-Data-Besitz; der native Root wird erst mit dem
letzten Data-Besitzer freigegeben. Der GPU-Completion-Transfer hält Data, nicht
mehr ausgemusterte Graph-/View-Descriptoren. Die Data-Referenz bleibt dadurch nach
Graph-Detach sichtbar. Buffer selbst bleibt nicht Send/Sync; nur der private,
nicht zugängliche Allocation-Besitz darf abschließend vom Completion-Thread über
die bereits mutex-geschützte native Freigabe zerstört werden.
Damit ist eine konkrete COW-Lücke an der gemeinsamen QsaArray.shared_storage-
Grenze geschlossen: bisher wurden nur mehrere Rc<Buffer> erkannt, nicht zwei
verschiedene Buffer-Views derselben Allocation. Der direkte gepinnte MTPLX-Test
(QSACache.write_raw, Runtime 0.32.2, modellfrei) bestätigt für ein Update 1→2:
Ein Alias desselben Array-Objekts sieht 2, eine vorher ausgewertete View bleibt 1.
Der entsprechende Rust-Test wurde negativ geprüft: Nur die alte Besitzprüfung
wiederhergestellt ergibt einen Fehlschlag (View fälschlich 2); die Korrektur
erhält 1. Die bestehende Sammlung und ihre numerischen Fixtures bleiben erhalten.
Der Completion-Test prüft zusätzlich verschachtelte Views, Root-Lebensdauer und
sichtbaren GPU-Data-Besitz vor/nach Abschluss. Belege:
local-eval-results/20260906-mtplx-port/qsa-data-ownership-check.log.
Normaler und verschärfter Lauf bestehen mit jeweils 34/34 Tests; Kernelquellen-
Prüfung, produktiver Release-Buildcheck, Formatierung und Release-Test-Clippy
bestehen ebenfalls. Die Abhängigkeit block 0.1.6 meldet weiterhin nur ihren
bekannten Future-Incompatibility-Hinweis.
Die QSA-Graphauswertung registriert inzwischen nach jedem Primitiv dessen
Eingaben (einschließlich gebundener Projektionsparameter) und Geschwisterausgaben
als deduplizierte Data-Menge, abzüglich der tatsächlich ausgewerteten Hauptausgabe,
wie im gepinnten backend/metal/eval.cpp. Die Halterung beginnt vor dem nächsten
Primitiv, nicht erst beim letzten Graph-Verbraucher. Graph-Detach löst nun nur
die Descriptoren; ein zweites Halten dieser Blätter würde die Hauptausnahme
wieder aufheben. Backend-Scratch und Fehlerpfad behalten ihre eigene Halterung.
Der Scheduler führt dafür neben dem Produzenten diejenige Geschwisterausgabe mit,
deren geteilte Abhängigkeitszahl null wurde; sie ist nicht immer Ausgabe null.
Ein CPU-Test deckt unterschiedliche Root-Reihenfolgen und doppelte Kanten ab.
Ein Metal-Test prüft leere Batch-Fallbacks, deduplizierte Views, Hauptausgabe eins,
die Ausnahme bei geteiltem Eingabe-/Ausgabespeicher und Referenzzahlen vor/nach
GPU-Abschluss. Es gibt keinen neuen Flush, Wait, Kernel oder GPU-Readback.
Belege: local-eval-results/20260906-mtplx-port/qsa-evaluator-holds-check.log.
Die erweiterte Sammlung besteht normal und mit unretained Command Buffers jeweils
mit 36/36 Tests. Kernelquellen-Prüfung, Release-Test-Clippy, produktiver
Release-Buildcheck und Formatprüfung bestehen ebenfalls.
Tatsächliche Donation bei QSA-Cache-Updates
Die beiden BF16-DynamicSliceUpdate-Knoten verwenden jetzt wie das gepinnte
backend/gpu/primitives.cpp → backend/common/copy.h vorhandenen Speicher,
wenn der Vector-Copy-Donation-Vertrag erfüllt ist. Die neue Ausgabe erhält eine
eigene View-/Array-Identität auf demselben Data; der Vector-Copy-Dispatch entfällt,
die originale dynamische Zeilenkopie bleibt. Prüfkriterien am Ausführungszeitpunkt:
exklusiver Array-Descriptor, exklusives Rc<Buffer>/Data einschließlich GPU-Holds,
identischer Eingabedescriptor, ausreichender View-Bereich und höchstens 16 KiB
Überhang der Root-Allocation, nicht nur der kleineren View. Beide Elementtypen
sind in diesem installierten Cachepfad BF16; dies ist keine generische Dtype-Regel.
Der unveränderte Graph nimmt entweder festgehaltene Buffer-Eingaben oder exklusiv
veränderlichen QsaCacheInput::State entgegen. Die verbundene Hostmethode heißt
nun qsa_indexer_rows und gibt den echten Cache über die State-Variante hinein.
Snapshots/Views bleiben durch die gemeinsame Besitzprüfung geschützt. Es gibt
keinen zweiten Algorithmus und keine Donation-Einstellung für Anwender.
Alle 198 bestehenden Q/K-/Hidden-Referenzfälle laufen zusätzlich durch die
State-Variante mit lebenden Snapshots und anschließend exklusivem Besitz. Gleiche
Ausgabe-/Zustandshashes, unveränderte Snapshot-Hashes und tatsächliche unterschiedliche
bzw. identische Data-Adressen prüfen Kopieren und Donation getrennt. Die zwei
zusätzlichen Durchläufe sind keine neuen unabhängigen Referenz-Fixtures. Ein
zusätzlicher Test prüft Descriptor-Aliase, geteilte Storage-Snapshots, native Views,
GPU-Data-Holds sowie Überhänge 0/16384/16386 Byte. Reproduktionsbelege:
local-eval-results/20260906-mtplx-port/qsa-cache-donation-check.log.
Normaler und verschärfter Lauf bestehen mit 37/37 Tests. Kernelprüfung,
Release-Test-Clippy, produktiver Release-Buildcheck und Formatprüfung bestehen.
Allocator: Referenzfolge, Cache-Auswahl und Größenrundung
tools/mtplx-allocator-reference.py zeichnet 101 echte modellfreie Allokations-,
Freigabe-, Limit- und Clear-Ereignisse der installierten MTPLX-Runtime 0.32.2 auf.
tests/fixtures/mtplx-allocator.jsonl hält aktive/gecachete Bytes, tatsächliche
Buffergrößen und lauflokal anonymisierte physische Buffer-Identitäten fest.
Es ist kein nachgebauter Python-Allocator und kein Performance-Benchmark.
Die Rust-Implementierung von backend/common/buffer_cache.h verwendet zwei
geordnete Standard-Maps anstelle der C++-Multimap plus intrusiver Zeigerliste.
Sie erhält Best-Fit, älteste Einfügung bei gleicher Größe, die strikte Grenze
min(2*Anforderung, Anforderung+2*Seitengröße), altersbasierte Teilfreigabe und
vollständiges Leeren ab 90% angeforderter Freigabe. Bei vollständigem Leeren
bleibt die größenbasierte Reihenfolge erhalten. Der Replay-Test prüft alle
101 Zustandsübergänge und wiederverwendeten Buffer-Identitäten; außerdem die
Grenzen beim Ändern des Cache-Limits und dessen erlaubtes kurzfristiges
Überschreiten bei Freigabe. Der Cache ist noch nicht an native Ressourcen gebunden.
Die Größenrundung aus MetalAllocator::malloc ist bereits an Buffer::bytes
und Buffer::untracked der testgebundenen Schicht angeschlossen: Anforderung
zuerst gegen das wirkliche Metal-maxBufferLength prüfen, nur oberhalb einer
VM-Seite aufrunden. Auf diesem M5 Max beträgt die Seite 16384 Byte. Eine logische
View erhält die angeforderte Tensorgröße; Data besitzt weiterhin die vollständige
Allocation. Dadurch sehen Donation und Speicherzählung die tatsächliche Größe,
während Read-/Write-Grenzen unverändert bleiben. Die native Ergänzung liest nur
die Metal-Gerätegrenze; Auswahl-/Rundungslogik bleibt Rust.
Der Metal-Test prüft beide vorhandenen Resource-Optionen und 1/255/256 Byte sowie
die Seitengrenzen. Die Donation-Grenztests verwenden jetzt die real gerundeten
Root-Größen. Kernel und Synchronisationsgrenzen bleiben unverändert.
Belege: local-eval-results/20260906-mtplx-port/allocator-policy-check.log.
Normaler und unretained Metal-Lauf bestehen mit jeweils 39/39 Tests;
Kernelprüfung, Release-Test-Clippy, produktiver Release-Buildcheck und
Formatprüfung bestehen ebenfalls.
Noch offen für den vollständigen Allocator: Bindung des Pools an die echte Data-Freigabe, 1-MiB-Heap für Anforderungen unter 256 Byte, Residency/Wired-Limit, Ressourcen-/GC-/Speicherlimits und deren Zähler sowie die leere Array-/Null-Buffer- Repräsentation. Die vorhandenen Resource-/Hazard-Optionen wurden nicht pauschal umgestellt; dazu gehört die noch fehlende vollständige Encoder-Abhängigkeitslogik.
Dies ist noch keine vollständige Donation-/Evaluator-Parität: Außerhalb des QSA-Graphen fehlt die modellweite Integration dieser Regeln; ebenso andere Primitive und generische Typ-/Layoutzweige. Vollständiger Modellgraph und produktive Integration bleiben offen. Der produktive FP32-Pfad erhält durch diese testgebundene Besitzschicht keine neue Referenzzählung; keine Durchsatz- oder UI-Parität wird behauptet.
Allocator: GPU-Ressourcenbesitz unabhängig von Data-Donation
Die gemeinsame kanonische Dispatch-Schicht hält jetzt Rust-Allocation-Besitz
bis zum Abschluss des zugehörigen Metal-Command-Buffers. BufferData besitzt
eine gemeinsame Root-Allocation; GPU-Bindings halten diese Allocation, nicht
Data. Damit bleibt die vorhandene referenzkonforme Donation-Prüfung unabhängig
von der physischen GPU-Ressourcenhaltung. Nur der letzte Allocation-Besitzer
gibt den nativen Root frei. Diese Trennung ist für die noch ausstehende Pool-
Anbindung erforderlich: Ein bloßer nativer MTLBuffer-Retain verhindert zwar
Deallokation, aber nicht die verfrühte Wiederverwendung durch einen Rust-Pool.
Rust dedupliziert Root-Allocations pro Dispatch. Die bestehende native Completion-Registrierung übernimmt den Rust-Besitz atomar und setzt den Übergabezeiger auf null; bei früher Validierungs-/Pipeline-/Encoder-Ablehnung behält und bereinigt Rust ihn. Der Callback ersetzt in diesem Pfad das native Resource-Set, ohne zusätzliche Callbacks, Flushes, Commits oder Wartepausen. Der rohe ABI-Pfad ohne Rust-Owner behält seine bisherige native Haltung. Die typisierten Bindings binden zudem die Lebensdauer von Tensor-Views und Scalar-Zeigern an ihre Rust-Referenzen bis zur Übergabe.
Ein modellfreier Metal-Test prüft Deskriptor-/Data-Detach bei noch uncommitteter
GPU-Arbeit, Allocation-Lebensdauer, unveränderte Data-Donation, Deduplikation
bei In-place-Bindings, Freigabe nach Completion, synchrone Einzel-Dispatches
sowie zurückbehaltenen Besitz bei Validierungsfehlern. Beide vollständigen
kanonischen Sammlungen bestehen mit 40/40 Tests, normal und mit
DS4_METAL_UNRETAINED_COMMAND_BUFFERS=1; alle bisherigen Referenzhashes bleiben
gleich. Beleg: local-eval-results/20260906-mtplx-port/allocation-lifetime-check.log.
Kernelprüfung, Release-Test-Clippy und produktiver Release-Buildcheck bestehen.
Zu dieser Zwischenstufe war der Pool noch nicht aktiviert. Der folgende Abschnitt dokumentiert die anschließende native Anbindung; modellweiter Evaluator und produktive Integration bleiben offen.
Allocator: Nativer Pool, Heap und Limits
Allocator bindet die bestehende Cache-Politik jetzt an echte native Roots und
deren finale Allocation-Freigabe an. Das gilt einschließlich der GPU-Besitzer
des gemeinsamen Dispatch-Pfads: Solange ein Command Buffer noch auf Speicher
zugreift, bleibt dieser aktiv und kann nicht als Cache-Treffer vergeben werden.
Die Besitzerstruktur enthält keinen Zyklus: Der Cache besitzt native Roots,
nicht die Allocation-Deskriptoren, die ihrerseits den Allocator halten.
Die Rust-Seite übernimmt die vollständige bisher portierte malloc/free-Policy: Cache-Suche vor GC, ursprüngliche Best-Fit-Grenzen, aktive/gecachete/Peak-Bytes, Ressourcenzähler, Cache-Limitwechsel ohne sofortiges Leeren, Trimmen erst nach Allokation, Memory-Limit/GC-Schwelle und Ressourcenlimit. Auch die unsigned Subtraktion bei ausschließlich ressourcenbedingtem Druck bleibt erhalten. Ein Memory-Limit ist hier wie in der Referenz keine harte Ablehnung einer größeren Allokation. Anfangswerte stammen aus den tatsächlichen Metal-/sysctl- Werten und den Referenzformeln; Resource-Limit-Fallback ist 499000.
Die native Ergänzung stellt nur Metal-Plattformoperationen bereit: einen
1-MiB-Heap, Buffer daraus oder als Fallback direkt vom Gerät sowie Freigaben.
Rust wählt den Heap ausschließlich für Anforderungen unter 256 Byte.
Die Ressourcenoptionen sind Shared | HazardTrackingUntracked. Die Paravirtual-
Ausnahme bleibt erhalten. Null/0 Byte liefert None, keine künstliche
Ein-Byte-Allokation; vorhandene Array-APIs müssen diese Darstellung noch
modellweit übernehmen. Logische Views bewahren die ursprünglichen Tensorgrenzen
auch bei gerundeten oder größeren wiederverwendeten Roots.
Der native Replay-Test führt alle 101 Referenzereignisse mit echten Allokationen aus und prüft nach jedem Schritt aktive/gecachete/Peak-Bytes, Ressourcenzahl und logische/physische Größen. Cache-Treffer müssen tatsächlich dieselben Speicheradressen zurückgeben; neue Geräteallokationen dürfen andere Adressen als beim Referenzprozess haben. Ein weiterer Test prüft 1/255/256/257- Byte-Heap-Routing, Erschöpfung der 1-MiB-Heap-Slots mit Geräte-Fallback, Memory-/Ressourcen-GC, unveränderte Zähler bei Ressourcenablehnung und echte Cache-Wiederverwendung erst nach GPU-Completion.
Beide kanonischen Sammlungen bestehen mit 42/42 Tests, normal und unretained.
Beleg: local-eval-results/20260906-mtplx-port/native-allocator-check.log.
Clippy für Release-Tests, produktiver Release-Buildcheck, Original-Kernel- und
Formatprüfung bestehen. Es wurden keine Modellgewichte geladen.
Verbleibende Integration: Residency/Wired-Limit, externe/wrapped Buffer, prozessweiter Allocator-Lebenszyklus, Routing aller kanonischen Allokationen und vollständige Encoder-Abhängigkeiten. Der Allocator wird bislang explizit von den modellfreien Tests verwendet, nicht vom vollständigen Modellpfad. Die vorhandenen Helfer werden nicht vor der Abhängigkeits-Portierung pauschal auf untracked Ressourcen umgestellt. Vollständiger Modellgraph, UI/Harness- Produktionspfad und ±2%-Performance-Abnahme bleiben weiterhin unerledigt.
Allocator: Residency und Wired-Limits
qwen_mtplx/residency.rs portiert die Regeln aus dem gepinnten
backend/metal/resident.cpp: Metal-3/macOS-15-Freigabe, initiales Set mit
stehender Residency-Anforderung, 5%-Standardcap mit 64-MiB-Untergrenze,
Single-Set-Modus, First-Fit, Wiederverwendung leerer Sets für übergroße
Allokationen und Emptiest-Fallback bei 32 Sets oder späterem Treiberfehler.
Die ursprünglichen Umgebungsvariablen und deren einmalige atoi-Auswertung
bleiben erhalten. Rust führt Budgets, Sets und gespeicherte Allokationsgrößen;
die native Bridge enthält nur die Metal-Operationen.
Der Allocator registriert den Heap einmal und jeden Nicht-Heap-Root bei Neuanlage. Cache-Einträge bleiben registriert/verdrahtet; tatsächliche Freigabe entfernt sie vor dem nativen Release. Wired-Limitwechsel registrieren passende bereits vorhandene Allokationen bzw. entfernen sie unter das neue Budget. Pro berührtem Set erfolgt ein Commit. Weder Freigabe noch erneutes Setzen desselben Limits befördert wartende Allokationen automatisch. Eine atomare Set-Zahl erlaubt den schnellen Queue-Attach-No-op; neue Sets werden im Test unmittelbar vor dem GPU-Commit angefügt, nicht bereits beim Allokieren.
Ein nativer Test überträgt die zehn Lifecycle-Szenarien aus der ursprünglichen
tests/residency_tests.cpp und prüft zusätzlich Cache-Verbleib, Limit-Ablehnung
und tatsächliche Metal-allocationCount-/containsAllocation-Ergebnisse.
Maximal rund 129 MiB werden dabei gleichzeitig verdrahtet. Die Tests prüfen
Budgets, Set-Auswahlregeln und native Mitgliedschaft; gleiche Adress-/Hash-
Bucket-Reihenfolgen zwischen zwei Prozessen werden damit nicht behauptet.
Der Resize-Durchlauf verwendet wie die Referenz eine ungeordnete Map.
Beide kanonischen Sammlungen bestehen mit 43/43 Tests, normal und unretained;
Release-Test-Clippy, produktiver Release-Buildcheck, Original-Kernel- und
Formatprüfung bestehen. Beleg:
local-eval-results/20260906-mtplx-port/residency-check.log.
Weiter offen: automatische Anbindung an sämtliche tatsächlichen Encoder- Commit-Pfade, externe/wrapped Buffer, prozessweiter Besitzer, vollständiges Routing der Modellallokationen und Encoder-Abhängigkeiten. Der explizite Allocator ist weiterhin testgebunden; es gibt keinen neuen Gesamtmodell- Benchmark und weiterhin keinen Nachweis der verlangten ±2%-Parität.
Submission: Residency an tatsächlichen Commit-Grenzen
qwen_mtplx/submission.rs hält Queue, Allocator und den bereits angefügten
Set-Index über mehrere Command-Batches hinweg. Ein Scope registriert einen
threadlokalen, synchronen Rust-Callback vor dem tatsächlichen nativen Commit.
Beim Erstellen werden vorhandene Sets angefügt; vor jedem späteren Commit
werden nur neu entstandene Sets ergänzt. Nested Scopes können den Besitzer
nicht überschreiben. Finish/Drop lassen den Besitzer bis nach dem Drain leben
und entfernen dann den Callback; danach erbt der Legacy-Pfad keinen Hook.
Alle zwölf bisherigen direkten Command-Buffer-Commit-Stellen der Bridge laufen jetzt durch einen gemeinsamen Einstieg, einschließlich Flush, Readback, Cleanup und GLM-Streaming-Split. Der Hook ist nur im kanonischen Scope aktiv und auf dessen Encoding-Thread sowie die Haupt-Queue begrenzt; andere Queues bleiben ausgenommen. Metal-Residency-Set-Commits bleiben eigene Operationen. Es entstehen keine zusätzlichen Command Buffers, Flushes oder Wartepausen. Ein Quelltest schützt gegen erneute direkte Commit-Umgehungen.
Der native Test prüft nachträglich erzeugte Sets, Flush, Eval, Finish, Drop,
native interne Batch-Beendigung mit anschließendem synchronen Einzel-Dispatch
und das Entfernen des Hooks. Die kanonische Sammlung besteht normal und
unretained mit 45/45 Tests. Release-Test-Clippy, produktiver Release-
Buildcheck, Original-Kernel- und Formatprüfung bestehen ebenfalls. Beleg:
local-eval-results/20260906-mtplx-port/submission-check.log.
Dies schließt den bisher manuellen Residency-Attach für diesen testgebundenen Scope, nicht den gesamten MTPLX-Encoder. Weiter offen sind die genaue Input-/Output-Klassifikation aller Bindings, Barrier-Epochen, ConcurrentContext, Encoder-Fences/Completion-Bereinigung, Ops-/Byte-Commit-Schwellen und vollständige Modell-/Produktintegration. Der produktive Qwen-Graph nutzt den Scope noch nicht; Gesamtmodell-Performance und ±2%-Abnahme bleiben unbewiesen.
Encoder: abhängige Ausführung, Fences und Shared Events
qwen_mtplx/encoder.rs portiert die zusammengehörige Steuerung aus MTPLXs
gepinntem Runtime-backend/metal/device.cpp, einschließlich event.cpp und
der verbrauchenden Fehlersemantik aus error.h. Rust besitzt eine eigene Queue
und unretained Command Buffers. Jeder Compute-Encoder ist Concurrent; Rust
entscheidet anhand tatsächlicher Metal-Buffer-Identitäten über Read/Write-
Barrieren, aktuelle Barrier-Epochen, deferred ConcurrentContext-Ausgänge und
deduplizierte Fence-Waits zwischen Encodern. Completion entfernt einen Producer
nur, wenn dessen Fence noch aktuell ist. Temporäre Ressourcen werden aus den
encoderübergreifenden Mengen entfernt und bis Completion gehalten.
Shared-Event-Wait und -Signal beenden den aktuellen Encoder. Completion führt zuerst den Benutzer-Callback aus, übernimmt den ersten gültigen fremden Wait-Event-Fehler und danach gegebenenfalls einen GPU-Fehler. Signal-Events teilen den konsumierbaren Fehlerzustand des Encoders; bei GPU-Fehlern werden sie zusätzlich auf der CPU signalisiert, damit wartende Queues nicht hängen. Synchronize wirft/entnimmt den Fehler; der Destruktor wartet, ohne ihn zu entnehmen. Fence-, Event- und Buffer-Holds bleiben bis Completion gültig.
Die ursprünglichen Commit-Schwellen und ihre einmaligen Umgebungsvariablen
werden übernommen. Korrektur der bisherigen Byte-Bezeichnung: Der gepinnte
Code addiert array.data_size() ohne Multiplikation mit item_size. Laut
array.h sind das Elemente, keine Bytes. Auf Max/Ultra gilt daher strikt
ops > 50 || (data_size >> 20) > 50. Ein Buffer zählt beim ersten Input-Eintrag
je Encoder; die Summen werden erst beim Command-Commit zurückgesetzt. Raw-
Buffer-Bindings zählen als encoderübergreifende Ein- und Ausgänge, ändern aber
weder die Barrier-Epochen noch den Größenzähler. Es gibt keine zusätzlichen
automatischen Sleeps oder pro-Layer-Waits.
Die native Bridge benutzt denselben validierenden Pipeline-/Binding-/Dispatch- Code für den bisherigen und den explizit übergebenen Encoder. Sie entscheidet nicht über Abhängigkeiten, Batching oder Fehlerweitergabe. Der neue Rust- Encoder lehnt Tensor-Bindings ohne explizite Input/Output/Raw-Rolle ab, statt aus Buffergrößen oder Kernel-Namen Zugriffsrollen zu erraten.
Drei neue Checks prüfen Barrier-/Commit-Epochen, disjunkte Concurrent-Outputs,
abhängige untracked Kopien über mehrere Encoder und asynchrone Command Buffers,
Fence-Deduplizierung/Completion-Rennen, temporäre Buffer, beide Dispatch-
Geometrien sowie reale Shared-Event-Transfers zwischen zwei Queues. Fehler-
Completion wird gezielt mit einem synthetischen GPU-Status geprüft, ohne einen
GPU-Hänger auszulösen. Die gesamte Sammlung besteht normal mit 48/48 und
unretained mit 48/48 Tests; Clippy, produktiver Release-Buildcheck und
Original-Kernel-Abgleich bestehen. Beleg:
local-eval-results/20260906-mtplx-port/encoder-check.log.
Nicht abgeschlossen: Dieser Encoder ist weiterhin testgebunden. Vollständige
Zugriffsrollen und exakte Array-data_size-Metadaten aller Operator-Bindings,
Routing der Allokationen, Stream-/Scheduler-/Graph-Integration einschließlich
aller Eval- und Completion-Grenzen sowie der komplette Modellpfad fehlen noch.
Die große bestehende Kernelsammlung läuft weiterhin über den bisherigen
Dispatch-Pfad; nur die neuen Encoder-Tests benutzen die eigene Queue. Der alte
Submission-Scope ist damit noch keine Produktintegration. P05 und der gesamte
Paritätsaudit bleiben offen; keine neue UI-/Gesamtmodell- oder ±2%-Abnahme.
Operator-Routing: Normen und zusammenhängende MoE-Kette
Ein threadgebundener Scope verbindet die vorhandenen Operatorfunktionen jetzt
mit dem eigenen Concurrent-Encoder und demselben gepoolten, untracked Allocator.
Er fügt keine Dispatch-/Eval-Grenzen ein. Nested Scopes werden abgelehnt; nach
dem Scope erbt der bisherige Pfad weder Encoder noch Allocator. Der Besitzer
bleibt über mehrere Operationsketten hinweg bestehen und wartet beim Abbau.
Die Dispatch-Implementierung und die vorhandenen Fixture-Auswertungen werden
wiederverwendet, nicht als zweiter Operatorpfad nachgebaut.
Explizite Ein-/Ausgangsrollen und Elementspannen sind für die gesamte
Norm-/MoE-Kette übernommen: Softmax/Top-10-Router, Argsort mit Multi-Block-Merge,
Gather/Unsort, Gate/Up und SwiGLU, Grouped-/Gated-RMS, BF16/FP32-Casts,
Affine-QMV/QMM einschließlich Split-K, Gather-QMM einschließlich sortiertem
RHS und Broadcast-Indizes, Stock-/Fused-MoE sowie Shared Expert und Gate.
Geslicte Inputs zählen wie backend/common/slicing.cpp ihre adressierte
Elementspanne, nicht die volle Allokation oder nur die Zahl logischer Werte.
Broadcast-Indizes behalten ihre tatsächliche Speicherspanne.
Zwei bisherige setBytes-Ersatzbindungen sind durch die ursprünglichen skalaren
Array-Inputs ersetzt: das Einheitsgewicht für ungewichtete RMSNorm und der
Divisor in GatherSort. Sortier- und Split-K-/Reduktions-Scratch werden an den
ursprünglichen Stellen als Backend-Temporaries registriert. Ihre Lebensdauer
und ihr Ausschluss aus den encoderübergreifenden Ressourcenmengen laufen damit
über den portierten Encoder, nicht nur über zurückgegebene Rust-Bufferlisten.
Original-Kernel, Rundungsfolgen und Geometrien bleiben unverändert.
Neun vorhandene Fixture-Gruppen werden ohne Abschwächung ihrer Ausgabehash- Prüfungen jeweils im bisherigen und im neuen Encoder ausgeführt: 78 Affine, 40 Gather-QMM, 123 Argsort, 7 GatherSort, 16 Router, 10 Gate/Up, 25 Normen, 21 SwitchGLU und 220 MoE — insgesamt 540 Referenzfälle in beiden Encodern. Das sind zusätzliche Ausführungen vorhandener Fälle, keine neuen unabhängigen Referenz-Fixtures. Die Tests unterscheiden native Legacy-Busy- Zähler ausdrücklich vom Commit-Zähler der eigenen Queue. Der neue Scope-Test prüft zudem tatsächliche Pool-Allokation, Cache-Rückgabe, den Gate/Up- Speicherspannenzähler und genau eine erforderliche Barrier ohne Zwischencommit.
Die gesamte kanonische Sammlung besteht mit 49/49 Tests sowohl normal als
auch mit unretained Legacy-Command-Buffers. Release-Test-Clippy, produktiver
Release-Buildcheck, Format-/Diff-Prüfung und Original-Kernel-Abgleich bestehen.
Beleg: local-eval-results/20260906-mtplx-port/operator-encoder-check.log.
Weiter offen: GDN-/QSA-Operator-Routing, allgemeine Array-Metadaten/Donation, vollständige Stream-/Evaluator-/Graph-Anbindung und deren tatsächliche Eval-, Commit- und Completion-Grenzen sowie der produktive Gesamtmodellpfad. Ein manuell abgegrenzter Operator-Testbatch beweist nicht die Scheduling-Parität eines gesamten MTPLX-Chats. Der eigene Encoder ist noch nicht mit der normalen UI-/Harness-Instrumentation verbunden. Die ±2%-Abnahme bleibt ausstehend.
Operator-Routing: zusammenhängende GDN-Kette
GDN verwendet nun ebenfalls den gemeinsamen Dispatch mit expliziten Input-/
Output-Rollen und Array-Elementspannen: Conv/Mask/Cache, Q/K-L2-Norm, compute_g,
Sigmoid, rekurrentes Delta-Update, Fused-Step und Fused-Output. Der bisherige
direkte native Fused-Step-Aufruf entfällt. Projektionen und Gated-Norm verwenden
die bereits angebundenen Operatoren; Original-Kernel und Geometrien bleiben
unverändert. Binäre skalare Operanden und das CustomKernel-T-Argument sind echte
skalare Array-Inputs, keine setBytes-Ersatzbindungen.
backend/metal/slicing.cpp::concatenate_gpu bestimmt den Conv-Fenster-Aufbau:
disjunkte Output-Slices mit ihrer jeweiligen data_size, eine Concurrent-Region
für beide Kopien und anschließender Dependency-Join. Ein RAII-Guard stellt den
Join auch bei vorzeitigem Fehler sicher. CustomKernel-Eingangskopien werden in
Input-Reihenfolge nach der Output-Allokation ausgeführt und nach dem Dispatch
als Backend-Temporaries registriert. Die fehlende Conv-State-Kopie im Fused-Step
liegt jetzt hinter der Eingangsprojektion statt davor.
Die vier bestehenden Gruppen mit 80 Delta-Update-, 2 laufenden Fused-Step-, 130 Staged- und 264 Forward-Fällen laufen jetzt jeweils in beiden Encodern. Zusammen mit Norm/MoE sind das 1.016 vorhandene Referenzfälle in beiden Encodern, ohne neue oder abgeschwächte Referenz-Hashes. Die Forward-Fälle prüfen auch fortgesetzte Zustände, Nullzustände, Masken, gültige Längen, Projektionslayouts und die gewählten Fusionszweige.
Die gesamte Sammlung besteht normal mit 49/49 Tests (35,79 s) und mit
unretained Command Buffers mit 49/49 Tests (35,28 s). Release-Test-Clippy,
produktiver Release-Buildcheck, Format-/Diff-Prüfung und Original-Kernel-Abgleich
bestehen. Beleg: local-eval-results/20260906-mtplx-port/gdn-encoder-check.log.
Weiter offen: QSA-Operator-Routing, allgemeine Array-/Donation-Verträge, der vollständige Evaluator mit tatsächlichen Eval-/Commit-/Completion-Grenzen, Stream-Anbindung, UI-/Harness-Instrumentation und produktiver Gesamtmodellpfad. Diese GDN-Integration ist noch kein vollständiger Modellgraph und keine Performance-Paritätsabnahme. P05 und der Gesamtauftrag bleiben offen.
QSA-Cache-Kopien und kompilierte Cache-Fenster am Encoder
Die gemeinsamen QSA-Kopierfunktionen tragen jetzt explizite Array-Metadaten:
statische Source-Slices zählen ihre adressierte Elementspanne; Slice-Updates
binden das vollständige Zielarray, Concatenate dagegen die logische Größe
seines Output-Slices. Dynamische Kopien erhalten beide vollständigen Array-
data_size-Werte vom Aufrufer, unabhängig von der kopierten Zeilenzahl. Der
Encoder-Test prüft genau diese Unterscheidung sowie die Ablehnung zu kleiner
Metadaten. Konstanten, die im Original Arrays sind, bleiben skalare Arrays;
die dynamischen Offset-Arrays sind Inputs und Backend-Temporaries.
Zero-Fill, COW-/General-Kopien, die kompilierten Frontier-Operationen und die fused Query-/Pool-Vorbereitung benutzen explizite Ein-/Ausgangsrollen. Die KV-Vergrößerung verwendet für ihre disjunkten Concatenate-Kopien den originalen Concurrent-Kontext. Kernelquellen und Dispatch-Geometrien wurden nicht verändert. Die vorhandenen 12 Backing-/Dynamic-Copy- und 26 Cache-Window- Fälle laufen mit identischen Hash-Prüfungen in beiden Encodern; insgesamt sind damit 1.054 bestehende Referenzfälle in beiden Encoder-Pfaden abgedeckt.
Gesamtsammlung: 49/49 normal (35,53 s) und 49/49 unretained (35,11 s).
Release-Test-Clippy, produktiver Release-Buildcheck, Format-/Diff-Prüfung und
Original-Kernel-Abgleich bestehen. Beleg:
local-eval-results/20260906-mtplx-port/qsa-copy-encoder-check.log.
Weiter offen: Das ist noch nicht die komplette QSA-Kette. Insbesondere eager RoPE/Pooling, Score-Produzenten und Selektoren, sämtliche verbleibenden Concurrent-/Eval-Grenzen und der vollständige Graph-/Produktionspfad müssen weiter angebunden werden. Die neuen Cache-Fälle ersetzen weder die vollständige Modellprüfung noch die geforderte Performance-Abnahme.
QSA-Vorbereitung, Cache-Fortsetzung und fused Selektor am Encoder
Die eager Query-/Pool-Vorbereitung verwendet jetzt ebenfalls explizite Ein-/Ausgangsrollen und die adressierten Elementspannen. Alle drei RoPE- Concatenates haben die ursprünglichen Concurrent-Regionen samt anschließenden Dependency-Joins. Positions-, Amplituden- und Mittelwertskalierung verwenden skalare Array-Operanden; die BF16-/FP32-Grenzen bleiben unverändert. Die vorhandenen Norm-, Cast- und General-Copy-Operatoren werden weiterverwendet.
Der fused Selektor und seine Chunk-Zusammenführung sind ebenfalls angebunden. Die drei Frontier-Arrays werden wie im Original separat angelegt statt als drei Views derselben Allokation. Seine private Score-Ausgabe bleibt ein CustomKernel-Output, keine als Backend-Temporary deklarierte Arbeitskopie. Numerische Kernelquellen und Dispatch-Geometrien sind unverändert.
Die vorhandenen 210 Vorbereitungs-/Projektions-, 88 laufenden Cache- und 75 Selektor-/Chunk-Fälle werden nun in beiden Encodern geprüft, einschließlich Trim/Reserve/Restore und Descriptor-/Data-Alias-Verhalten. Insgesamt laufen damit 1.427 bestehende Referenzfälle in beiden Encoder-Pfaden. Die Cache- Tests enthalten auch reine Metadatenoperationen; ihre manuellen Testgrenzen sind ausdrücklich keine Behauptung identischer Modell-Eval-Grenzen.
Gesamtsammlung: 49/49 normal (36,34 s) und 49/49 unretained (36,33 s).
Release-Test-Clippy, produktiver Release-Buildcheck, Format-/Diff-Prüfung und
Original-Kernel-Abgleich bestehen. Beleg:
local-eval-results/20260906-mtplx-port/qsa-prepare-encoder-check.log.
Weiter offen: getrennte Score-Produzenten, eager Selektions-/Ausgabepfade, komplette Graph-/Stream-/Evaluator- und Produktionsanbindung samt Instrumentation. Die bisherige minimale Platzhalter-Allokation für leere Selektor-Arrays ist unverändert; ein allgemeiner Null-Storage-Array-Vertrag fehlt weiterhin. Keine dieser Operator-Prüfungen ist eine vollständige Modell- oder Performance- Abnahme. Der gesamte Paritätsauftrag bleibt offen.
QSA-Score-Produzenten und verbundener Prefill am Encoder
Beide Score-Produzenten, Prefill-Top-k und die bestehende Chunk-Verkettung laufen jetzt über den unabhängigen Encoder. Der FP32-Pfad bindet GEMV, Steel/NAX, Split-K samt Akkumulation, Maximum und Reduktion mit expliziten Array-Rollen und Elementspannen. Maximum/Divide verwenden echte skalare Arrays. Matmul allokiert seinen Output vor den Transpose-Kopien; diese Kopien und Split-K- Scratch werden nach ihren Konsumenten als Backend-Temporaries registriert. AsType- und Score-Zwischenergebnisse bleiben normale Graph-Arrays.
Der MPP-Pfad behält seine stridefähigen Eingaben ohne zusätzliche Kopien. Prefill-Top-k allokiert alle Outputs vor der erforderlichen General-Copy, registriert diese Arbeitskopie nach dem Dispatch und verwendet drei separate Frontier-Arrays. Kernelquellen, Spezialisierungen und Dispatch-Geometrien bleiben unverändert. Vorhandene Operatoren und Referenzfälle werden wiederverwendet.
Die 384 FP32-Score-, 146 MPP/Top-k/Prefill- und 96 gemischten Producer-Fälle bestehen nun in beiden Encodern mit unveränderten Originalhashes. Insgesamt: 2.053 bestehende Referenzfälle in beiden Encoder-Pfaden. Die bestehenden manuellen Testgrenzen ergeben jeweils genau ein Submission; sie behaupten ausdrücklich keine identischen vollständigen Modell-Eval-Grenzen.
Gesamtsammlung: 49/49 normal (36,76 s) und 49/49 unretained (37,19 s).
Release-Test-Clippy, produktiver Release-Buildcheck, Format-/Diff-Prüfung und
Original-Kernel-Abgleich bestehen. Beleg:
local-eval-results/20260906-mtplx-port/qsa-score-encoder-check.log.
Weiter offen: eager Selektions-/Ausgabepfade, vollständiger Graph, Streams, Evaluator, allgemeiner Null-Storage-Vertrag und Produktionsanbindung samt Instrumentation. Die produktive Qwen-Ausführung ist nicht umgeschaltet. Diese Operator-Prüfungen ersetzen weder Modell- noch Performance-Abnahme; der vollständige Paritätsauftrag bleibt offen.
Eager QSA und verbundener Indexer am Encoder
Maskierung, Ranking und sämtliche eager Ausgabevarianten verwenden nun
explizite Array-Rollen/-Spannen und skalare Array-Operanden. Die negative
Unendlichkeit wird zwischen Kacheln geteilt. Jedes ursprüngliche mx.eval(top_t)
wartet auf der tatsächlich aktiven Queue; der unabhängige Pfad eröffnet dafür
keinen Legacy-Command-Buffer. Tiled-Index-, Decode-Tail-, Rows-Gather- und Dense-
Concatenates besitzen ihre ursprünglichen Concurrent-Regionen samt Join.
Zwei frühere Verkürzungen sind entfernt: Dense-Padding wird vor Concatenate materialisiert, und Rows-Gather erzeugt seine beiden separaten Arange-Ausdrücke. Vorhandene Originaloperatoren werden wiederverwendet, keine Kernelkörper oder Spezialisierungen verändert. Der feste Indexer-Graph hält Input-/Sibling-Data nun über Completion-Callbacks der aktiven Queue; primäre beziehungsweise gespendete Output-Data bleiben ausgeschlossen. Graph-Concatenates sind ebenfalls angebunden, und kompilierte Frontiers sind vier separate int32-Arrays.
Die bestehenden 540 eager Fälle und 200 laufenden Indexer-Aufrufe laufen jetzt in beiden Encodern, einschließlich kompilierter Varianten, Cache- Fortsetzungen, Selektions-/State-Hashes, Graph-Engagement und expliziter Tile- Eval-Anzahlen. Insgesamt 2.793 bestehende Dual-Encoder-Referenzfälle. Der vorhandene Data-Ownership-Test prüft zusätzlich beide Queues, Donation- Ausschluss und das Ausbleiben einer Submission beim bloßen Registrieren von Holds.
Gesamtsammlung: 49/49 normal (40,19 s) und 49/49 unretained (40,20 s).
Release-Test-Clippy, produktiver Release-Buildcheck, Original-Kernel-Abgleich,
Format-/Diff-Prüfung bestehen. Beide Referenz-Checkouts sind sauber und auf den
festgehaltenen Commits. Beleg:
local-eval-results/20260906-mtplx-port/qsa-eager-encoder-check.log.
Weiter offen: vollständiger Modellgraph und allgemeiner Stream-/Evaluator- Scheduler, insbesondere die automatische Commit-Entscheidung nach Original- Primitiven; allgemeiner Null-Storage-Vertrag und Produktionsanbindung samt Instrumentation. Die manuellen Fixture-Grenzen ersetzen diese nicht. Der produktive Qwen-Pfad ist weiterhin nicht umgeschaltet, und die vollständige Modell-/Performance-Abnahme aller drei Modelle bleibt offen.
Primitive-Commits und Scheduler am festen Indexer-Tape (2026-09-07)
Der Rust-Scheduler übernimmt die FIFO-Worker je CPU-Stream, früheste Fehler, nicht konsumierende Event-Fehlerweitergabe, Synchronisation und abarbeitendes Shutdown aus der von MTPLX verwendeten Runtime 0.32.2. Verwendet werden stdlib und die vorhandene Shared-Event-Bridge, keine weitere Abhängigkeit. GPU-Encoding bleibt auf dem aufrufenden Thread wie in der Referenz.
Der feste Indexer-Tape prüft die originale Commit-Bedingung jetzt nach dem
vollständigen Primitiv, nicht pro Kernel. Input-/Sibling-Data und Backend-Holds
sind davor an den betreffenden Command Buffer gebunden. Automatische Commits
zählen laufende Aufgaben, deren Completion beziehungsweise fehlgeschlagene
Übergabe den Zähler wieder ausgleicht. Die originale Druckbedingung
tasks > 10 || (active_memory > memory_limit && tasks > 0) finalisiert den
hier einzigen offenen GPU-Stream und wartet auf Fortschritt; keine neuen Sleeps.
Dabei fiel eine veraltete Testannahme auf: Der verbundene Indexer erwartete
pauschal die manuellen Tile-/Final-Submissions. Zwei volle Prefill-Fälle
(compiled_s12_qk0_step0 und compiled_s12_qk1_step0) benötigen zusätzlich je
einen automatischen Commit: nach 17 Dispatches mit 57.469.227 beziehungsweise
55.246.572 gezählten Elementen gilt (data_size >> 20) > 50. Diese beiden
Fall-Erwartungen werden unabhängig vom Zähler der expliziten Synchronisationen
geprüft; alle übrigen verbundenen Fälle erwarten null automatische Commits.
Die alte Prüfung wurde nicht durch eine pauschale größere Toleranz ersetzt.
Output-, Cache- und Graph-Hashes bleiben unverändert.
Prüfung: vier zusätzliche Scheduler-/Primitive-Tests; Gesamtsammlung
53/53 normal (42,53 s) und 53/53 unretained (41,97 s). Release-Test-Clippy,
produktiver Release-Buildcheck, Format-/Diff-Prüfung und Original-Kernel-Abgleich
bestehen. Beide Referenz-Checkouts sauber auf den festgehaltenen Commits.
Beleg: local-eval-results/20260907-mtplx-port/scheduler-check.log.
Weiter offen: allgemeine Device-/TLS-Stream-Verwaltung, vollständiger
Evaluator mit streamübergreifendem Tape, CPU-Primitive-Encoding, vollständiger
Qwen-Modellgraph, allgemeiner Null-Storage-Vertrag und Produktionsanbindung samt
Instrumentation. Die CPU-Worker sind bisher modellfrei geprüft, nicht im
Produktionsmodell angebunden. Der kanonische Port bleibt cfg(test);
Produkt-Qwen, UI/Harness-Verhalten und Gesamt-Performance sind nicht abgenommen.
Der vollständige Auftrag und die anschließende Drei-Modell-Matrix bleiben offen.
CPU-Dispatch und gemeinsame Primitive-Ownership (2026-09-07)
Der CPU-CommandEncoder-Teil aus backend/cpu/encoder.h ist im bestehenden
Rust-Scheduler ergänzt: jeder zehnte Dispatch zählt eine laufende Aufgabe;
eine separate nachfolgende FIFO-Aufgabe meldet den Abschluss auch bei einem
Fehler im eigentlichen Dispatch. Ein abgewiesenes Enqueue lässt keinen neuen
Task-Zähler zurück. Die Cleanup-Aufgabe aus backend/cpu/eval.cpp zählt dabei
ebenfalls als Dispatch und hält Input-/Sibling-Data sowie Backend-Temporaries
bis hinter die zuvor eingereichte Arbeit.
CPU- und GPU-Evaluator verwenden dafür jetzt dieselbe Data-Auswahlfunktion:
Deduplication nach Data-Identität, primärer Output einschließlich gespendeter
Input-Data ausgeschlossen. CPU-Temporaries behalten ihre vollständigen nativen
Deskriptoren; der private Send-Wrapper erlaubt ausschließlich deren Freigabe
auf dem Worker, keinen Buffer-Zugriff. Buffer selbst bleibt nicht Send/Sync.
Es gibt keine neue Abhängigkeit, keinen Metal-Kernel- oder Produktionswechsel.
Gezielte Prüfungen: 5/5 Scheduler-Tests, GPU-Evaluator-Ownership 1/1,
verbundener Indexer mit allen 200 Fällen in beiden Encodern 1/1 normal
(2,54 s) und 1/1 unretained (2,50 s), jeweils unveränderte Ausgabe-/State-
Hashes. Release-Test-Clippy, Produkt-Buildcheck, Originalquellen-Abgleich und
Format-/Diff-Prüfung bestehen. Die vollständige 53er-Sammlung des vorherigen
Schrittes wurde hierfür nicht als neue Gesamtabnahme ausgegeben.
Beleg: local-eval-results/20260907-mtplx-port/cpu-scheduler-check.log.
Weiter offen: Device-/TLS-Stream-Registry und allgemeiner Evaluator samt Modellgraph; CPU-Dispatch-/Hold-Regeln sind vorhanden, CPU-Modelloperationen und deren Routing aber noch nicht verbunden. Produktionsanbindung und gesamte Modell-/Performance-Abnahme bleiben unverändert offen. Der Stream-Abgleich ist keine Behauptung, dass bereits eine vollständige Registry implementiert sei.
CPU-/GPU-Stream-Verwaltung und Indexer-Anbindung (2026-09-07)
Ein Runtime-eigener Stream-Besitzer verbindet jetzt die vorhandenen CPU- und
GPU-Encoder für den installierten Ein-CPU-/Ein-Metal-Backend-Vertrag. Die Regeln
aus stream.h/cpp sind abgebildet: getrennte Defaults pro Thread/Device,
threadlokale Stream-Templates mit verzögerter Auflösung, normale threadgebundene
Streams und sequentiell threadübergreifend verwendbare globale Streams.
CPU-IDs bleiben wegen des gemeinsamen Schedulers über Context-Wechsel eindeutig.
Die Registry hält ihren Lock weder beim Encoding noch bei Dispatch oder Wait. Ein ausgewählter GPU-Encoder benutzt weiterhin den vorhandenen Rc/RefCell-/TLS- Operatorpfad und denselben Allocator; pro Stream-Auswahl wird kein neuer Encoder oder neuer GPU-Queue-Besitzer erzeugt. Für die sichere Rückgabe aus einer Auswahl werden genau ein starker und null schwache Rc-Besitzer verlangt. Gleichzeitige mutable Nutzung wird abgewiesen, Fehler und Unwinding geben den Encoder zurück. Ein TLS-Cleanup gibt lokale Encoder auch beim Thread-Ende ohne explizites Clear frei. Explizites Clear erhält wie die Referenz die dann gegebenenfalls veralteten Default-/Template-Handles und Stream-Metadaten; globale GPU-Encoder werden dabei nur vom Scheduler-Main-Thread entfernt, globale CPU-Encoder nicht.
Wait/Signal, Finalize und Synchronize verwenden die existierenden CPU-FIFOs und Metal-Events. Die streamübergreifende Lastbegrenzung finalisiert alle offenen GPU-Streams in der ursprünglichen Device-/Index-Reihenfolge, bevor sie auf Fortschritt wartet. Der gezielte Test verbindet zwei GPU-Queues per Event und hält elf gezählte CPU-Aufgaben dahinter zurück. Erst das Einreichen beider GPU-Queues löst die Kette. Eine fünfsekündige Sicherung würde einen kaputten Finalize-All-Pfad fehlschlagen lassen statt den Test endlos hängen zu lassen.
Die vorhandene laufende 200-Fall-Indexer-Folge nutzt nun im unabhängigen Pfad einen registrierten Default-GPU-Stream statt eines alleinstehenden Scope; Legacy-Gegenpfad und sämtliche Ausgabe-/State-/Commit-Erwartungen bleiben erhalten. Zwei neue Stream-Tests prüfen außerdem Defaults, Thread-Zuordnung, Template- Auflösung, Cleanup, Fehler-Rückgabe, Thread-Wechsel und echte Kernel-Kopien.
Prüfung: vollständige modellfreie Sammlung 57/57 normal (41,39 s) und
57/57 unretained (41,56 s). Release-Test-Clippy, Produkt-Buildcheck,
Format-/Diff-Prüfung und Original-Kernel-Abgleich bestehen; beide Referenzen
sauber auf den festgehaltenen Commits. Beleg:
local-eval-results/20260907-mtplx-port/stream-check.log.
Weiter offen: vollständiger allgemeiner Array-/Evaluator-Graph mit streamübergreifenden Abhängigkeiten, CPU-Modelloperationen, Compile-Cache-Clear- Anbindung, Null-Storage-Vertrag und kompletter Modell-/Produktionspfad samt Instrumentation. Die Registry ist bisher im kanonischen Test-Port angebunden, nicht in der UI-Inferenz. Dieser Schritt belegt weder den kalten UI-Ping noch Modell-/Performance-Parität; die anschließende Drei-Modell-Matrix bleibt offen.
Evaluator-Events und beide Inter-Stream-Fence-Pfade (2026-09-07)
Der Port enthält jetzt die Event-/Fence-Verträge aus event.h,
backend/metal/event.cpp und backend/metal/fence.cpp. Graph-Event-Kopien teilen
native Event-/Fehlerzustände, behalten aber ihren eigenen Wert-Snapshot und
Ursprungsstream. Host-Waits prüfen den gemeinsamen Fehler vor und nach dem Wait.
Diese Events sind von den internen MTLFences des Command Encoders getrennt.
Inter-Stream-Fences unterstützen beide Referenzzweige. Standardmäßig bleibt
SharedEvent-Synchronisation aktiv. Der optionale Fast-Pfad verlangt unverändert
MLX_METAL_FAST_SYNCH und Metal3/macOS15-Unterstützung. Er verwendet die bereits
in der gepinnten Metallib vorhandenen Originalfunktionen input_coherent,
fence_update und fence_wait, keine nachgebauten Kernel. GPU-Waits registrieren
die konsumierten Arrays als Outputs; GPU-Updates erhalten die ursprüngliche
Cross-Device-Coherence-Stufe und explizite Barrier. CPU-Operationen verwenden
den separaten atomaren Timestamp mit SeqCst-Zugriffen, ohne neue Sleeps/Yields.
Fence-Kopien teilen den Update-Zähler, während eingereihte Operationen ihren
jeweiligen Zählerwert erfassen. CPU-Aufgaben und Command-Completion-Holds halten
den privaten Timestamp-Speicher bis zum tatsächlichen Abschluss.
Die Metal-Bridge akzeptiert nun wie die Referenz leere Dispatch-Grids. Ein
gezielter Test prüft den leeren Coherence-Dispatch sowie eine BF16-Spanne, die
auf zwei uint32-Wörter aufgerundet wird. Das prüft einen realen Speicher mit
data_size=0, nicht den weiterhin offenen allgemeinen Null-Storage-Vertrag.
Die betroffene Rust-FFI wird derzeit ausschließlich vom cfg(test)-Port benutzt.
Drei neue Prüfungen decken Event-Snapshots/Fehler, kleine leere/teilwortige
Coherence-Grids und eine CPU → GPU → GPU → CPU-Kette in beiden Fence-Modi
mit exakten Daten und Freigabe nach Completion ab. Eine ausschließlich im Test
vorhandene fünfsekündige Sicherung löst Wartebedingungen bei einem Fehler auf;
sie griff nicht ein. Neue modellfreie Gesamtsammlung:
60/60 normal (41,38 s) und 60/60 unretained (41,47 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung, Originalquellen- und Metallib-Hash-
Prüfung bestehen. Beide Referenzen sind sauber auf den gepinnten Commits.
Beleg: local-eval-results/20260907-mtplx-port/graph-sync-check.log.
Weiter offen: vollständiger Array-/Evaluator-Graph, der diese Abhängigkeiten aus den Modelloperationen erzeugt; CPU-Modelloperationen, Compile-Cache-Clear, Null-Storage und vollständige Qwen-Produktionsanbindung samt Instrumentation. Der Fast-Modus wird nicht als Optimierung eingeschaltet. UI-Verhalten und Gesamt-Performance wurden nicht neu gemessen; die vollständige Drei-Modell- Abnahme bleibt offen.
Gemeinsame Graph-Planung und Stream-Abhängigkeiten (2026-09-07)
qwen_mtplx/eval.rs übernimmt die Traversierung aus dem gepinnten
transforms.cpp::eval_impl: Auswahl des Synchronizer-Streams, DFS-Gradzählung
für alle Geschwister-Ausgaben, BFS mit Breitenlimit und DFS-Fortsetzung sowie
umgekehrte Ausführungsreihenfolge. Tape-Einträge identifizieren die tatsächlich
gewählte Ausgabe, nicht bloß deren Producer; diese Wahl ist für Data-Holds und
Donation relevant. MLX_BFS_MAX_WIDTH wird wie in utils.h einmalig mit
get_var/atoi-Semantik gelesen (Default 20), nicht mehr lokal fest verdrahtet.
Die Traversierung berücksichtigt Unscheduled/Evaluated/Available und das vom Aufrufer gelieferte effektive Tracer-Flag. Bereits ausgewertete, nicht mehr getracete Primitive werden einschließlich ihrer Geschwister abgelöst. Async- Tracer und fehlende Primitive behalten die Referenzfehler. Stream-Abhängigkeiten werden pro Ausgabe ermittelt; der Cross-Device-Bedarf wird über alle Konsumenten vereinigt. Das ist noch keine allgemeine Array-Speicher- oder Transform-Runtime.
Der bisherige separate QSA-Scheduler ist entfernt. Der bestehende kompilierte Indexer erzeugt sein wiederverwendetes Tape jetzt über diesen gemeinsamen Planer. Sein einzelner logischer Stream wird beim Replay weiterhin auf dem Encoder des Aufrufers ausgeführt; die Planung erzeugt keine zusätzliche Queue. Alle bestehenden Ergebnis-, State-, Lifetime- und Commit-Prüfungen bleiben unverändert. Keine Metal-Kernel, Flush- oder Prefill-Sonderregeln geändert.
Drei neue modellfreie Strukturprüfungen decken Breiten-/Sibling-Reihenfolge,
Stream-/Device-Abhängigkeiten sowie Status-/Detach-/Tracer-Fehler ab. Ihre
Erwartungen wurden aus der gepinnten Traversierung abgeleitet, nicht als neue
Live-Runtime-Trace ausgegeben. Gesamtsammlung 63/63 normal (40,70 s) und
63/63 unretained (40,90 s); Release-Test-Clippy, Produkt-Buildcheck,
Format-/Diff-Prüfung und Originalquellen-/Metallib-Hash-Prüfung bestanden.
Beide Referenz-Checkouts sind unverändert auf den festgehaltenen Commits.
Beleg: local-eval-results/20260907-mtplx-port/graph-tape-check.log.
Weiter offen: allgemeine Array-Daten-/Primitive-Ausführung mit dem gesamten
Eval-Epilog und Fehler-Cleanup, Verknüpfung der hier ermittelten Abhängigkeiten
mit Graph-Events/Fences, CPU-Modelloperationen, Compile-Cache-Clear, Null-Storage
und vollständiger Qwen-Produktionspfad samt Instrumentation. Der kanonische Port
bleibt cfg(test); der UI-Modellpfad ist damit nicht umgestellt. Keine neuen
Modell-/Performance-Läufe, kein Paritäts-Pass und keine Rücknahme eines
Referenzbestandteils. Die vollständige Drei-Modell-Abnahme bleibt offen.
Gemeinsamer Eval-/Async-Eval-Ablauf mit Abschluss und Fehler-Cleanup (2026-09-07)
Der gemeinsame Planer ist jetzt mit dem Ausführungs-Kontrollfluss aus
transforms.cpp::eval_impl, eval und async_eval verbunden. Der Evaluator
verwendet die vorhandene Stream-Registry, CPU-FIFOs, Encoder, Graph-Events und
beide Graph-Fence-Backends. GPU-Primitive laufen auf dem aufrufenden Thread im
Scope ihres Streams, nicht in einem neu eingeführten Worker-Pool.
Innerhalb einer Auswertung werden die geplanten Stream-Abhängigkeiten per Fence abgewickelt; zwischen Async-Auswertungen über das gespeicherte Event. Bereits signalisierten Events wird beim Ablösen noch ihr Fehler entnommen. Ein fehlgeschlagenes Ablösen lässt Event und Status bestehen. Status, primäre Ausgabe und Geschwister werden in Referenzreihenfolge aktualisiert. Der Abschluss signalisiert die Eval-Events und finalisiert alle offenen GPU-Streams; der synchrone Aufruf wartet auf den Synchronizer, der asynchrone nicht. Leere oder bereits geplante Async-Ausgaben erzeugen keine neue Auswertung/Submission.
Bei einem Primitivfehler werden die beteiligten Events signalisiert und alle betroffenen Streams synchronisiert. Cleanup-Fehler ersetzen nicht die Ursache. Dasselbe Cleanup läuft beim Rust-Unwinding; danach wird der ursprüngliche Panic weitergereicht. Der lokale Synchronizer wird in allen Rückgabewegen entfernt. Frühere erfolgreiche Knoten bleiben ausgewertet, so dass ein Retry nur die fehlgeschlagenen Knoten erneut ausführt. Gemeinsame Data-Hold-Helfer werden für den bestehenden QSA-Pfad und den neuen Kontrollfluss wiederverwendet; CPU-Cleanup behält seine Zehner-Taskzählung. Der Synchronizer benötigt keinen Datenpuffer.
Drei neue modellfreie Prüfungen verbinden echte kleine CPU-/GPU-Operationen: CPU → GPU mit Geschwister-Ausgaben → zweite GPU-Queue → CPU; eine absichtlich noch laufende Async-Ausgabe als Eingabe der nächsten Auswertung; Fehler und Panic mit vollständigem Drain/Retry; Tracer-Donation-Schutz und behaltene Topologie. Die zehnsekündige Deadlock-Sicherung gilt ausschließlich für diese winzigen Unit-Tests und beendet bei einem Hänger deren Prozess; sie griff nicht ein und ersetzt nicht den Startup-/Progress-Watchdog der Modell-Harness. Zusätzlich prüft der bestehende Event-Test einen Fehler trotz signalisiertem Event.
Gezielte neue Tests: 3/3 SharedEvent (0,14 s) und separat
3/3 Fast-Fence (0,12 s). Gesamtsammlung 66/66 normal (41,35 s) und
66/66 unretained (41,58 s). Release-Test-Clippy, Produkt-Buildcheck,
Format-/Diff-Prüfung und Originalquellen-/Metallib-Hash-Prüfung bestanden.
Keine Shader-/Bridge-Änderung; beide Referenzen sauber auf ihren Pins.
Beleg: local-eval-results/20260907-mtplx-port/eval-execution-check.log.
Abgrenzung: Das ist der gemeinsame Ausführungs-Kontrollfluss, noch nicht der
vollständige Array-/Modellport. Primitive werden als konkrete Rust-Operationen
eingespeist; materialisierte Buffer mit Elementzahl/Elementgröße bleiben beim
Aufrufer. Allgemeine Descriptor-/Graph-Ownership, Shapes/Strides, Freigabe bei
letzter Graph-Referenz und Null-Storage müssen noch mit diesem Ablauf verbunden
werden. Der derzeitige Tracer-Schutz hält Input-Data vorübergehend und verhindert
Donation; die vollständige Descriptor-Referenzsemantik ist damit nicht belegt.
CPU-Modelloperationen, Compile-Cache-Clear und vollständiger Qwen-Produktionspfad
samt Instrumentation bleiben offen. QSA nutzt weiter seinen kompilierten
Replay innerhalb des Caller-Batches, nicht einen zusätzlichen Eval-Abschluss
pro Indexer-Aufruf. Der gesamte kanonische Port bleibt cfg(test).
Keine UI-/Modell-/Performance-Abnahme und keine Schließung des Drei-Modell-Ziels.
Leere materialisierte Daten und Null-Bindings (2026-09-07)
Der kanonische Buffer-Pfad kann nun leere Data-Objekte ohne Metal-Allokation
darstellen. MetalAllocator::malloc(0) der gepinnten Runtime liefert null;
array::set_data erzeugt trotzdem eine eigene Data-Identität. Entsprechend
erzeugt Buffer::bytes(0) im Test-Port einen leeren nativen Descriptor mit
buffer=nil, nicht einen Dummy-Puffer. Allokator-, Cache-, Peak- und Ressourcen-
Zähler bleiben unverändert. Allocator::allocate(0) liefert weiterhin None.
Der vorhandene Descriptor-/Data-/Allocation-Lebenszyklus wird wiederverwendet: unabhängige leere Buffer haben verschiedene Data-Identitäten, Views teilen Data und bekommen ihre eigene Descriptor-ID. Die native View-/Free-Verwaltung bleibt zuständig; es gibt keine zweite Speicherverwaltung. Leere Reads/Writes sind gültig, nichtleere oder außerhalb liegende Zugriffe bleiben Fehler. Eine leere View kann außerdem einen vorhandenen nichtleeren Speicher behalten und am Ende dieser Allokation liegen; sie wird nicht stillschweigend durch Null-Data ersetzt.
Die kanonische Metal-Bindung akzeptiert jetzt die von device.cpp verwendeten
Null-Bindings und leere Views. Null-Ressourcen bleiben wie in der Referenz Teil
der RAW-/WAR-Abhängigkeitsmengen; ihr data_size ist null. Die Objective-C-
Fallback-Hold-Menge übernimmt nur tatsächliche Metal-Buffer, da NSSet kein nil
aufnehmen darf. tensor_contents gibt für Null-Storage direkt null zurück,
ohne Pointer-Arithmetik darauf auszuführen. Die unveränderten Originalkernel
input_coherent, fence_update und fence_wait laufen in den entsprechenden
leeren Grids/Fence-Pfaden; kein Ersatzkernel und kein zusätzlicher Flush.
Zwei neue Prüfungen decken Identitäten, Freigabe, Grenzen, unveränderte
Allokatorzähler, Null-Abhängigkeiten, leere Tail-Views sowie beide nativen
Ownership-Pfade ab. Bestehende Fence-/Evaluator-Prüfungen enthalten nun echten
Null-Storage, einschließlich GPU → CPU. Gezielte Prüfungen je 1/1 (0,06 s);
erweiterter Fast-Fence-Evaluator 3/3 (0,11 s). Gesamtsammlung
68/68 normal (41,23 s) und 68/68 unretained (41,44 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung und Originalquellen-/Metallib-Hash-
Prüfung bestanden; Referenz-Checkouts unverändert auf den Pins.
Beleg: local-eval-results/20260907-mtplx-port/empty-storage-check.log.
Abgrenzung: Damit ist der leere Buffer-/Binding-Vertrag verbunden, nicht
automatisch jeder Zero-Shape-Zweig sämtlicher Array-Operationen. Allgemeine
Array-Descriptor-/Graph-Ownership, Shapes/Strides, Freigabe bei letzter
Graph-Referenz, CPU-Modelloperationen und der vollständige Modell-/Produktions-
pfad bleiben offen. Die neue Buffer-Erzeugung ist an den kanonischen cfg(test)-
Pfad gebunden; die produktive Inferenz ist noch nicht umgestellt. Keine neuen
Modelldownloads oder Modell-/Performance-Läufe; das Drei-Modell-/2%-Ziel bleibt offen.
Gemeinsame Array-Ownership im Lazy-Evaluator (2026-09-07)
Die externe Vec<Option<Value>> des allgemeinen Evaluators ist entfernt.
eval/async_eval arbeiten jetzt unmittelbar auf geteilten Array-Deskriptoren;
Primitive materialisieren ihre vorhandenen Ausgabedeskriptoren. Status, Events,
Eingaben, Geschwister, Ausgabeposition und Data gehören diesem Owner. Der
kompilierte QSA-Planner bleibt derselbe; seine vorhandenen materialisierten
Cache-Arrays verwenden ebenfalls den gemeinsamen Storage-/Descriptor-Owner.
Die Ownership-Regeln stammen aus array.cpp/array.h der gepinnten Runtime:
Descriptor-Kopien teilen Identität, separate Data-Views nicht; Donation verlangt
exklusive Descriptor- und Data-Ownership. Geschwister halten sich gegenseitig
und ihre jeweiligen Eingaben. Beim letzten äußeren Verweis werden die Zyklen
aufgelöst und lange Eingabeketten iterativ freigegeben. detach entfernt bei
allen Geschwistern Primitive, Eingaben, Geschwister und Ausgabeposition, ohne
Status oder Events zu löschen. Data-/Allocation-/GPU-Completion-Holds bleiben
in der bestehenden Speicher-/Encoder-Verwaltung; keine zweite Allokatorlogik.
Für die Planung entsteht nur ein schwacher Topologie-Index, keine zusätzliche starke Referenz auf jedes Zwischenergebnis. Der Ausführungstape hält die von MTPLX ausgewählten Ausgaben; nach Detach und letztem Verbraucher verschwinden die Eingabedeskriptoren. Planungs-Detach wirkt unmittelbar, auch vor einem späteren Planungsfehler. Bei Ausführungsfehlern bleibt der Rest-Tape bis nach dem Event-/Stream-Cleanup erhalten. Tracer halten während des Primitivaufrufs jetzt zusätzliche Descriptor-Verweise, nicht ersatzweise zusätzliche Data.
Zwei neue reine Ownership-Tests prüfen die letzte äußere Geschwisterreferenz, 30.000 Knoten mit behaltenem Zwischenknoten, 10.000 doppelte Geschwisterstufen und vollständigen Detach. Die bestehenden drei verbundenen Evaluatorprüfungen sind auf Array-Ownership umgestellt; eine vierte prüft Donation ohne künstliche Arena-Referenzen, Freigabe nach letztem Verbraucher und unabhängig behaltene Geschwister-Ausgaben. Der QSA-Donation-Test prüft zusätzlich einen direkten Descriptor-Alias. Ergebnis-, Cache-, Lifetime- und Commit-Assertions des vorhandenen Kernel-/Indexer-Bestands bleiben erhalten.
Prüfstand: 71/71 normal (42,16 s) und 71/71 unretained (42,15 s);
abschließender Fast-Fence-Evaluator 4/4 (0,14 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung und Originalquellen-/Metallib-Hash-Prüfung
bestanden. Beide Referenz-Checkouts sauber auf ihren Pins; keine Shader- oder
native Bridge-Änderung in diesem Schritt. Diese Zeiten sind Testlaufzeiten,
keine Modell-Performance. Beleg:
local-eval-results/20260907-mtplx-port/array-ownership-eval-check.log.
Abgrenzung: Das verbindet die Descriptor-/Graph-Lebensdauer mit dem
Ausführungskontrollfluss, schließt aber nicht den gesamten Array-/Modellport.
Allgemeine Shapes/Strides/Dtypes/Flags, konkrete Modellprimitive und ihre
vollständige Verbindung, CPU-Modelloperationen, Compile-Cache-Clear sowie die
Produktionsanbindung samt Instrumentation bleiben offen. Elementzahl und
Elementgröße werden ausdrücklich mit Materialisierungen übergeben; das ist
noch kein allgemeiner Shape-Inferenzpfad. Der kanonische Port bleibt cfg(test).
Keine neuen Modellgewichte, keine Gesamtmodell-Messung, keine Paritätsabnahme.
Typisierte Array-Geometrie vor der Auswertung (2026-09-07)
Der allgemeine Evaluator übernimmt keine freie Kombination von data_size
und itemsize mehr. Der bisherige Value-Transporttyp ist entfernt; Shapes
und echte Dtypes stehen bereits am unscheduled Ausgabedeskriptor. Primitive
materialisieren dessen Daten über set_data. Die gemeinsame Array-Geometrie
enthält Shape, kanonische Strides, Elementzahl, Dtype, Data-Elementzahl und
Contiguity-Flags. BF16 und FP16 bleiben verschiedene Typen trotz gleicher
Bytebreite; alle 14 Dtype-Werte der gepinnten Runtime sind abgebildet.
Die Regeln folgen ArrayDesc::init, array::set_data, array::make_arrays
und dtype.h: skalare Shapes haben ein Element, Shapes mit Null-Dimensionen
null; kanonische Strides werden von hinten aufgebaut. Negative Achsen werden
relativ zum Rank ausgewertet. Vor Materialisierung sind die drei Flags true;
danach wird Column-Contiguity aus der Form bestimmt. Ein neuer Primitivoutput
übernimmt nicht versehentlich die materialisierten Flags seines Inputs.
GPU-Primitive weisen Float64 an Eingaben oder Ausgaben zurück; die reine
CPU-Deskriptorkonstruktion erlaubt es. Leere Ausgabelisten erzeugen keine
Deskriptoren und führen diese GPU-Prüfung entsprechend nicht aus.
Materialisierungen mit zu kleinem Buffer sind Fehler und lassen vorhandene Daten/Geometrie unverändert; Größenberechnungen sind geprüft. Die bestehende Data-/Descriptor-/Completion-Verwaltung bleibt unverändert. QSA-Backing-Arrays sind als BF16 typisiert; ihre vorhandene logische Cache-Geometrie und Head- Strides bleiben beim Cache. Das ist noch keine Umstellung jedes Cache-Views auf allgemeine Array-Shape-/Offset-Operationen. Im Evaluator leiten sich die Fence-Elementzahl und Bytebreite jetzt aus dem typisierten Descriptor ab.
Eine neue reine Geometrieprüfung deckt die 14 Dtypes mit skalaren, leeren, einheitsdimensionalen und mehrdimensionalen Formen sowie Grenzen/Flags ab. Eine neue modellfreie Metal-Prüfung deckt echte Materialisierung, Fehler ohne Datenverlust, Aliase und leeren Speicher ab. Der bestehende Evaluator- und QSA-Testbestand ist auf den typisierten Vertrag umgestellt; keine bisherigen Ergebnis-/Lebensdauer-/Commit-Prüfungen entfernt.
Prüfstand: 73/73 normal (42,01 s) und 73/73 unretained (41,66 s);
Fast-Fence-Evaluator 4/4 (0,14 s). Gezielte Array-Prüfungen einschließlich
kleiner Metal-Allokationen 4/4 (0,07 s). Release-Test-Clippy, Produkt-Buildcheck,
Format-/Diff- und Originalquellen-/Metallib-Prüfung bestanden. Referenzen sauber
auf den bisherigen Pins; keine Shader-/Bridge-Änderung. Beleg:
local-eval-results/20260907-mtplx-port/typed-array-geometry-check.log.
Abgrenzung: Allgemeine strided Views mit Byte-Offsets, negative Strides,
Broadcast/Transpose/Reshape-Operationen, Dtype-Promotion/Conversions und alle
Modellprimitive sind damit nicht als vollständig portiert abgenommen. Auch
CPU-Modelloperationen, Compile-Cache-Clear, vollständiger Qwen-Modell-/Produktions-
pfad und Instrumentation bleiben offen. Der Port ist weiterhin cfg(test);
keine Modell- oder 2%-Performance-Abnahme und keine neuen Modellgewichte.
Geteilte Views und Byte-Offsets bis zur Metal-Bindung (2026-09-07)
Array-Deskriptoren tragen jetzt ihren eigenen Byte-Offset über demselben
geteilten Backing. set_strided_data übernimmt Strides/Flags/Data-Größe und
einen Byte-Offset; copy_shared_buffer addiert wie array.cpp einen Offset in
Elementen des Ziel-Dtypes zum vorhandenen Offset. Beide verwenden die
bestehenden Descriptor-/Data-/Allocation-Owner, keine zusätzlichen GPU-Views
oder Allokationen. Ungültige Spannen/Offsets werden vor einer Mutation abgewiesen.
set_data setzt den Offset zurück, behält aber wie die Referenz die Strides.
Die gemeinsamen materialisierten Backend-Operationen Slice, Broadcast und
Transpose sind aus backend/common/slicing.cpp, broadcasting.cpp und
common.cpp::Transpose::eval angeschlossen. Sie erhalten bereits inferierte
Ausgabe-Shapes und normalisierte Achsen/Indizes. Negative Strides und Broadcast-
Strides von null bleiben erhalten; Flags/Data-Größe werden nach den jeweiligen
Referenzregeln berechnet. Leeres Slice/Broadcast erzeugt leere eigene Data statt
das Eingabebacking zu halten. Generelles Reshape und Dtype-View/Conversion sind
noch nicht durch diese drei Backend-Operationen abgedeckt.
Der kanonische Metal-Binding-Vertrag hat nun einen zusätzlichen Byte-Offset.
Rust reicht ihn an setBuffer weiter; die native Brücke prüft Basisgrenzen und
Additionsüberlauf vor der Submission. Inline-Bytes haben weiterhin Offset null.
Die Ressourcenabhängigkeiten bleiben pro Backing, nicht pro View. Auch der
Fast-Fence-Coherence-Aufruf des allgemeinen Evaluators bindet den Array-Offset;
bestehende Buffer-Aufrufer verwenden unverändert Offset null. Kein zusätzlicher
Flush, Wait, Puffer oder veränderter Originalkernel.
Die neue überwachte Prüfung verbindet Reverse-Slice → Transpose → Slice → Broadcast → Original-Metal-Copy im gemeinsamen Evaluator. Das Ergebnis ist bytegenau geprüft; bis zur tatsächlichen Copy bleiben Allokatorzähler unverändert. Zusätzlich: positive Offset-View über GPU → CPU, leere/ungültige Views, Freigabe der ursprünglichen Graphreferenz. Bestehende Array-Tests prüfen explizite negative Strides, Ziel-Dtype-Offseteinheiten, Selbst-Sharing, Fehler ohne Mutation und Offset-Reset. Native Grenztests prüfen, dass ein ungültiger Binding-Offset den Ressourcen-Owner nicht übernimmt. Der vorhandene kleine Test-Watchdog ist wiederverwendet, keine neue Modell-Gesamtlaufzeitgrenze.
Prüfstand: 74/74 normal (41,18 s) und 74/74 unretained (41,35 s).
Die neue View-Kette besteht separat normal 1/1 (0,08 s) und mit Fast-Fences
1/1 (0,06 s); der bestehende Fast-Fence-Evaluator 4/4 (0,15 s).
Release-Test-Clippy, Produkt-Buildcheck, Format-/Diff-Prüfung und Originalquellen-
/Metallib-Hash-Prüfung bestanden; Referenz-Checkouts sauber auf den Pins. Beleg:
local-eval-results/20260907-mtplx-port/array-views-offsets-check.log.
Abgrenzung: Das ist eine verbundene Backend-/Ownership-/Binding-Erweiterung,
keine vollständige Array-Ops-API oder Qwen-Modellintegration. Allgemeines Reshape,
Dtype-View/Promotion/Conversions, weitere Modellprimitive, vollständige logische
QSA-Graphanbindung, CPU-Modelloperationen, Compile-Cache-Clear und produktive
Instrumentation bleiben offen. Der kanonische Port bleibt cfg(test); keine
Gesamtmodell-/UI-/2%-Performance-Abnahme und keine neuen Modellgewichte.
Reshape: gemeinsames Backing oder Original-General-Copy (2026-09-07)
views::reshape übernimmt common.cpp::prepare_reshape und
metal/copy.cpp::reshape_gpu: gleiche Elementzahl/Dtype, Single-Array-Collapse
mit INT32_MAX-Grenze, passende geteilte Strides einschließlich negativer und
Broadcast-Strides; unveränderte Data-Größe/Offsets und referenzgleiche Flags.
Leere und row-contiguous Inputs teilen das Backing ohne GPU-Allokation.
Der Copy-Fall kollabiert dagegen Input- und kanonische Output-Strides gemeinsam
in der Input-Shape, allokiert die Ausgabe und dispatcht die unveränderten
General-Copy-Kernel aus der übernommenen Metallib. Rust selektiert Rang,
Large-Index-Namen und Work-per-thread wie die Referenz; Inline-Slices werden
über den vorhandenen Binding-Helfer mit ihrer tatsächlichen Byte-Länge gebunden.
Kein zusätzlicher Flush oder Wait, keine neue Ownership-Schicht.
Der überwachte Test verbindet Transpose → Reshape im gemeinsamen Evaluator: 13 GPU-Dtypes × vier Shape-Fälle, mit positivem Backing-Offset, Singleton-Achsen, g2/g3/gn2-Kopien und unabhängig indizierter bytegenauer Ausgabeprüfung. Zusätzlich: Reverse-Strides beim geteilten Reshape, skalare und nichtuniforme Broadcasts (Share versus Copy), leere Arrays und Größenfehler ohne Mutation. Das sind kleine modellfreie Funktionstests; Large-Index-Kopien oberhalb INT32_MAX werden hier nicht mit großen Allokationen ausgeführt.
Prüfstand: 75/75 normal (41,85 s), 75/75 unretained (41,63 s);
View-/Reshape-Ketten mit Fast-Fences 2/2 (0,09 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung und Quellen-/Metallib-Hash-Prüfung
bestanden; beide Referenz-Checkouts sauber auf den Pins. Befehle/Ergebnisse:
local-eval-results/20260907-mtplx-port/reshape-check.log.
Der kanonische Port bleibt cfg(test). Dtype-View/Promotion/Conversions,
weitere Modellprimitive, vollständige logische QSA-Graphanbindung, CPU-
Modelloperationen, Compile-Cache-Clear, produktive Instrumentation und der
vollständige Qwen-Modellpfad sind weiterhin offen. Der Reshape-Backend-Port
ist ausdrücklich keine Produktions-, UI- oder Gesamtmodell-Performance-Abnahme.
AsType und Dtype-View am gemeinsamen Copy-/Evaluator-Pfad (2026-09-07)
Die tatsächlich verwendeten Qwen-Referenzaufrufe wechseln u.a. Router-Indizes,
QSA-Pooled-Scores und RoPE-Zwischenwerte (models/qwen4_exp.py: 345, 803–804,
1633–1658, 1945, 1965–1968). Der kanonische Rust-Backend-Port bildet jetzt
gpu/primitives.cpp::AsType::eval_gpu und View::eval_gpu ab, ohne dafür
Konvertierungsshader neu zu schreiben.
AsType selektiert Vector anhand des contiguous-Flags (nicht nur row- contiguous), erhält dabei Strides/Flags/physische Data-Größe und übernimmt donierbare gleich breite Speicher innerhalb der referenzierten 16-KiB-Grenze. Bei gleichem Dtype entfällt dann der Dispatch; bei verschiedenem Dtype werden Werte tatsächlich in place konvertiert. Andere Layouts gehen durch General Copy. Vector-Work-per-thread richtet sich nach Zieldtype und 65536-Schwelle; Large-Index-Namen und 2D-Grid-Faktorisierung folgen der gepinnten Referenz.
Dtype-View prüft skalare/letzte-Achsen-Bytegrößen. Gleiche Breite, geeignete kleinere Breite oder row-contiguous Input teilen das Backing mit angepassten Strides/Data-Größen. Andernfalls kopiert der originale General-Kernel zunächst in einen dichten temporären Input-Dtype-Puffer, den die Ausgabe anschließend teilt. Der General-Copy-Pfad wird auch von Reshape wiederverwendet. Seine 1024-Thread-Bedingung wird jetzt am tatsächlichen Pipeline-State geprüft; Vector nutzt dessen Maximum. Die native Lookup-Routine ist aus dem vorhandenen Dispatch extrahiert und zwischen Abfrage/Encoding geteilt. Kein zusätzlicher GPU-Command, Flush, Wait oder geänderter Metal-Kernel.
Neue überwachte Evaluator-Prüfung: alle 169 GPU-Dtype-Konvertierungspaare mit unabhängig kodierten 0/1-Werten; Vector-Schwellen 65535/65536/65537, Donation mit/ohne Konvertierung, negative Strides, spaltenkontiguierliche und Broadcast- Backings, Dtype-View-Sharing und -Copy, skalare/ungültige/leere Ausgaben. Large-Index-Grid und originale Large-Pipelines sind ohne große GPU-Allokation geprüft; keine Ausführung von Multi-GB-Copies daraus behauptet.
Prüfstand: 76/76 normal (41,86 s), 76/76 unretained (41,29 s) und
3/3 View-/Reshape-/Konvertierungsketten mit Fast-Fences (0,15 s).
Release-Test-Clippy, Produkt-Buildcheck, Format-/Diff-Prüfung und Quellen-/
Metallib-Hash-Prüfung bestanden; beide Referenz-Checkouts sauber auf den Pins.
Beleg: local-eval-results/20260907-mtplx-port/dtype-copy-view-check.log.
Offen bleiben die vollständige Array-Ops-API samt Promotion, weitere
Modellprimitive/logische QSA-Anbindung, CPU-Modelloperationen, Compile-Cache-
Clear und die Produktionsintegration mit Instrumentation. Weiterhin cfg(test);
keine Gesamtmodell-/UI-/2%-Performance-Abnahme.
Graph-eigene Array-Operationen statt externer Test-Zuordnung (2026-09-07)
Array-Deskriptoren können jetzt ihre konkrete Operation besitzen. Der neue
ops::evaluate verwendet unverändert den gemeinsamen Eval-/Async-Eval-Pfad,
liest den Payload aber aus dem Graphen, nicht aus einer externen ID-/Callback-
Tabelle. Detach gibt auch diesen Payload frei. Die bisherigen spezialisierten
Fixture-Callbacks bleiben verfügbar; der Produktionsmodellpfad ist noch nicht
umgeschaltet.
Lazy-Konstruktoren für Reshape, Transpose, Broadcast, AsType, Dtype-View,
ExpandDims und Squeeze übernehmen Shape-/Achsenprüfung, negative Achsen,
Reshape-Inferenz und die jeweiligen No-op-Regeln aus ops.cpp. ExpandDims
fügt Stride 1 ein, Squeeze entfernt nur die ausgewählten Strides; Flags,
Data-Größe und Offset bleiben geteilt wie in common.cpp. CPU-Ausführung
ist hier nur für diese gemeinsamen Views angeschlossen; CPU-Copy/Conversions
bleiben ausdrücklich offen und werden nicht still auf die GPU umgeleitet.
Der überwachte Test baut Qwens pooled.astype(float32).swapaxes(1,2)[:,None]
aus diesen Konstruktoren und verbindet weitere Reshape-/View-/Broadcast-
Verbraucher einschließlich GPU→CPU und Async→Sync. Vor Evaluation entstehen
keine GPU-Allokationen. Er prüft erwartete Shape/Strides, bytegenaue Werte,
No-op-Identitäten/Fehler und die Freigabe ursprünglicher Arrays und Operations-
Payloads. Das ist eine eigenständig ausführbare Layout-Graphfolge, noch keine
Anbindung des vollständigen QSA-Caches oder Qwen-Modells.
Prüfstand: 77/77 normal (41,19 s), 77/77 unretained (41,47 s);
neuer Graph mit Fast-Fences 1/1 (0,06 s). Release-Test-Clippy, Produkt-
Buildcheck, Format-/Diff- und Originalquellen-/Metallib-Prüfung bestanden.
Beleg: local-eval-results/20260907-mtplx-port/owned-operations-check.log.
Slice-Normalisierung und Contiguous für Cache-Fenster (2026-09-07)
Der graph-eigene Slice-Konstruktor übernimmt die Normalisierung von Start/Stop,
Vorwärts-/Rückwärts-Schritten und Singleton-Strides aus ops.cpp. Die No-op-
Entscheidung verwendet das ursprüngliche Vorzeichen vor der Singleton-
Vereinfachung. Rangfehler und Schritt null werden vor Graphanlage abgewiesen.
Ausführung nutzt den vorhandenen geteilten Slice-Backend, ohne neuen Kernel.
Contiguous ist wie in ops.cpp immer ein eigener Knoten. Sein GPU-Backend
teilt row-contiguous oder ausdrücklich erlaubte column-contiguous Inputs nur
innerhalb der ursprünglichen 16-KiB-Backing-Grenze; sonst verwendet es den
gemeinsamen Original-General-Copy. Diese Entscheidung ist für Qwens
cache[0] = contiguous(conv_input[:, -n_keep:, :]) relevant, damit ein kleines
Fenster nicht unbegrenzt ein großes Prefill-Backing hält.
Der überwachte Graph-Test prüft Slice-Werte/Identitäten/Strides, leere und
skalare Inputs, negative Grenzen/Schritte und Fehler. Dieselbe Zwei-Zeilen-
Cache-Ansicht wird einmal aus kleinem Backing geteilt und einmal aus großem
Backing kopiert; Column-Major erlauben/verbieten ist separat geprüft. Keine
Modellgewichte geladen; vollständige QSA-/Modellintegration und Performance-
Abnahme bleiben offen, der Port bleibt cfg(test).
Prüfstand: 78/78 normale modellfreie Tests (41,85 s). Die beiden graph-
eigenen Operationsprüfungen bestehen zusätzlich 2/2 unretained (0,09 s)
und 2/2 Fast-Fences (0,08 s); keine vollständige unretained-Wiederholung
in diesem Schritt. Release-Test-Clippy, Produkt-Buildcheck, Format-/Diff-
Prüfung und Quellen-/Metallib-Hashes bestanden. Beleg:
local-eval-results/20260907-mtplx-port/slice-contiguous-check.log.
RMSNorm als rechnende Graphoperation (2026-09-07)
Der Array-Payload-Pfad unterstützt jetzt mehrere Eingaben; RMSNorm trägt Input
und Gewicht als normale Graphkanten. Der GPU-Konstruktor folgt fast.cpp
einschließlich der für RMSNorm gültigen Floating-Promotion, vorgeschalteter
AsType-Knoten und skalarem Eins-Gewicht im ungewichteten Fall. CPU-Fallback-
Arithmetik bleibt offen und wird ausdrücklich abgewiesen, nicht auf GPU
umgeleitet.
Der Backend übernimmt metal/normalization.cpp statt pauschal contiguous
aufzurufen: passende zusammenhängende letzte Dimension und zulässiger
vorletzter Stride; anschließend Donation oder gleichartiges Backing. Andere
Layouts werden einmal dicht kopiert, und dieses Backing wird zum Output.
Die Zeilenzahl folgt der physischen Data-Größe, nicht der virtuellen Shape.
Input-/Gewicht-/Output-Offsets und Gewicht-Stride gehen in den Originalkernel.
Der frühere BF16-Helper und der neue Graphbackend teilen denselben Dispatch;
kein neuer Normalisierungsshader, keine neue Flush-/Wait-Grenze.
Neue überwachte Prüfung: FP16/BF16/FP32, Breiten 1/128/4096/4097, vorhandene
Input-Aliase versus letzter Verbraucher, Broadcast-Backings, notwendige
Input-Copy, strided/versetzte Gewichte und Inputs, ungewichtete Norm,
BF16+FP16→FP32 sowie ungültige Shapes. Die vorhandenen BF16-Modul-/QSA-/GDN-
Fixtures prüfen zusätzlich den gemeinsam umgestellten Dispatch. Das bleibt
ein kanonischer cfg(test)-Port; vollständige Modellintegration und der
Gesamtmodell-Performance-Nachweis sind nicht damit erreicht.
Prüfstand: 79/79 normal (41,87 s) und 79/79 unretained (41,49 s);
RMSNorm-Graph mit Fast-Fences 1/1 (0,08 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff- und Originalquellen-/Metallib-Prüfung bestanden.
Beleg: local-eval-results/20260907-mtplx-port/graph-rms-norm-check.log.
Quantisierte BF16-Projektionen als Graphoperation (2026-09-07)
Der normale transponierte Affine-Linear-Pfad der installierten Qwen-Gewichte
ist jetzt eine Operation mit vier Graphkanten (x, W, scales, biases). Output-
Allokation vor der Eingabevorbereitung und ensure_row_contiguous_matrix
folgen metal/quantized.cpp: nur die letzten beiden Strides entscheiden
über die notwendige General-Copy; kein Contiguous-Slack-Kriterium. Kopien
werden als Encoder-Temporaries bis zum GPU-Abschluss gehalten.
Graph und bestehende Modul-Fixtures benutzen denselben Affine-Dispatcher: QMV/Quad/Wide, QMM/NAX/Split-K und die Split-Reduktion bleiben unverändert. Die Eingaben erhalten ihre tatsächlichen Byte-Offsets und Array-Data-Größen für Bindings und Submission-Zähler. Keine neuen Shader, Flushes oder Waits. Der Graphzweig ist ausdrücklich BF16 mit zweidimensionalen 4/8-Bit-Gewichten, Gruppengröße 32/64. Andere Dtypes und echte batched/expert-Matmul-Graphzweige sind noch offen; sie werden nicht stillschweigend flachgerechnet.
Die neue überwachte Prüfung führt alle 78 bestehenden Referenz-Fixtures jeweils dicht, mit führendem Storage-Offset und mit strided Eingaben aus. Alle vier Eingaben werden variiert; x behält über ExpandDims eine zusätzliche Batch-Dimension, ohne vorab per Reshape dicht kopiert zu werden. 234/234 Outputs sind exakt gegenüber den gepinnten Referenz-Hashes. Kein Modell geladen, kein Download, kein Gesamtmodell-Performance-Vergleich.
Prüfstand: 80/80 normal (42,51 s) und 80/80 unretained (42,62 s);
der neue Graph-Test mit Fast-Fences 1/1 (0,99 s). Release-Test-Clippy,
Produkt-Buildcheck, Format-/Diff- und Originalquellen-/Metallib-Prüfung bestanden.
Produktintegration und vollständige Modelloperationen bleiben offen; dieser
Graph ist weiterhin cfg(test). Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-quantized-linear-check.log.
Elementweise Unary-Operationen im Graph (2026-09-07)
Negative, Square, Exp, Sigmoid, Tanh, Sqrt und Rsqrt sind jetzt eigene
Graph-Payloads. Konstruktoren folgen den jeweiligen ops.cpp-Typregeln:
Negative/Square erhalten den Typ, die übrigen verwenden at_least_float
mit vorgeschaltetem AsType; Negative/Bool und Sigmoid/Complex werden wie
in der Referenz abgewiesen. CPU-Arithmetik bleibt ausdrücklich unportiert.
Der gemeinsame Backend folgt metal/unary.cpp: physische Data-Größe bei
zusammenhängendem Backing, v/vn-Wechsel bei 65536 Elementen, v2 für
große zusammenhängende Daten, sonst zusammengefasste Dimensionen und
gn1/gn4large. Kernel-Maximalgruppen und Original-Grid-Regeln werden
verwendet. Inputs und Outputs tragen ihre Byte-Offsets und Data-Größen.
Die Original-Metallib wird nicht verändert.
set_unary_output_data ist mit AsType geteilt: Donation nur bei eindeutiger
Ownership, gleicher Elementbreite und höchstens 16 KiB zusätzlichem Backing;
sonst physisches gleichartiges Backing bei Contiguous oder dichter Output
für allgemeine Strides. Der bisherige Single-Array-Collapse von Reshape
wird ebenfalls wiederverwendet, nicht mit dem Joint-Copy-Collapse vermischt.
Der überwachte Test prüft exakte dyadische Werte für FP16/BF16/FP32 bei
0/1/65535/65536/65537 Elementen, mit und ohne Alias, sowie transponierte,
strided, negative, Broadcast- und Offset-Views, übergroße Backings,
Integer-Square und Integer→Float-Sqrt. Eine anfänglich falsche Testannahme
zur Donation von Reverse-Views wurde anhand check_contiguity korrigiert:
negative Strides zählen dort nicht zur positiven physischen Contiguity;
der Backend erzeugte bereits korrekt einen neuen dichten Output.
Große >UINT32-Allokationen werden mit diesem Test nicht behauptet.
Prüfstand: 81/81 normal (43,88 s) und 81/81 unretained (42,99 s);
Unary mit Fast-Fences 1/1 (0,41 s). Release-Test-Clippy, Produkt-Buildcheck,
Format-/Diff-Prüfung und unveränderte Originalquellen/Metallib bestätigt.
Produktgraph und vollständige Modellintegration bleiben offen. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-unary-check.log.
Binäre Graphoperationen und gemeinsame Typ-Promotion (2026-09-07)
Add/Subtract/Multiply/Divide/Maximum/Minimum/LogAddExp laufen jetzt als
binäre Graph-Payloads durch denselben Evaluator. Ihre Konstruktoren übernehmen
ops.cpp: Typ-Promotion, gegebenenfalls at_least_float, AsType beider
Eingaben und Broadcasting einschließlich der Null-Dimensionen.
Die vollständige Promotion der 14 Referenztypen ist gemeinsam in Dtype
implementiert und gegen alle 196 Einträge der gepinnten dtype.cpp-
Tabelle geprüft. RMSNorm und Unary benutzen die gemeinsamen Typregeln statt
eigener Teilabbildungen; ihre bestehenden Prüfungen bleiben erhalten.
Der Binary-Backend übernimmt common/binary.h und metal/binary.cpp:
Scalar/Scalar, Scalar/Vector, Vector/Scalar, gemeinsame Row-/Column-Vector-
Layouts und General. Scalar/Scalar allokiert ein neues physisches Element;
die übrigen Fälle erhalten referenzgleiche Donation-Priorität und Strides.
General kann einen passenden dichten Input übernehmen. Elementbreite,
Ownership und 16-KiB-Slack werden gemeinsam mit Unary/AsType geprüft.
General-Dispatch verwendet den Joint-Collapse von Input A, Input B und
Output; derselbe verallgemeinerte Helfer ersetzt den bisherigen Zwei-Layout-
Collapse für Kopien. g1/g2/g3/gn2/gn4large sowie ss/sv/vs/vv mit den
Vector-Arbeitsgrenzen werden aus den Originalregeln selektiert. Kernelquellen
und Metallib bleiben unverändert; keine neue Flush-/Wait-Grenze.
Überwachte GPU-Prüfung: BF16/FP32, alle sieben Operationen, leere Eingaben, Scalar/Vector-Grenzen bei 1/65535/65536/65537, alle Donation-Prioritäten, Column-/General-Layouts, zweiachsiges Broadcasting, rank-5 General-Dispatch, nichtkonstante Reverse-/Offset- und rank-5-Indizierung, gemischte Typen und Integer-Division mit Float-Promotion. Die erste Donation-Prüfung hielt ihre ursprünglichen Eingaben durch Rust-Shadowing ungewollt weiter am Leben; die Testeingaben werden nun vor der Auswertung ausdrücklich freigegeben. Der Backend war in diesem Fall korrekt nicht-donierend. Keine Änderung der Original-Ownership-Regeln zur Anpassung an eine falsche Testannahme.
Das bleibt cfg(test)-Grapharbeit; vollständige Modell-/Produktintegration
und der Gesamtperformance-Nachweis bleiben offen. Prüfstand: 83/83 normal
(44,06 s), 83/83 unretained (44,03 s), binärer Graph mit Fast-Fences
1/1 (0,13 s). Release-Test-Clippy, Produkt-Buildcheck, Format-/Diff-Prüfung,
Originalquellen-/Metallib-Prüfung bestanden. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-binary-check.log.
Shared-Expert-MLP als zusammenhängender Graph (2026-09-07)
_FusedGateUpMLP ist jetzt aus normalen Graphknoten aufgebaut: quantisierte
fusionierte Gate/Up-Projektion → Split → der tatsächlich erfasste kompilierte
BF16-SiLU-Kernel → separater Multiply → quantisierte Down-Projektion. Kein
eager Mehrkernel-Callback und keine neue Shaderimplementierung.
Split ist ein gemeinsamer Mehrfach-Output-Knoten mit Geschwistern. Jedes
Geschwister trägt denselben Operation-Payload; der bestehende Evaluator kann
jedes davon als primären Output wählen. Der schnelle Split übernimmt exakt
die Flags-/Data-Größen-Regeln aus common.cpp, allgemeine Indizes gehen über
die Slice-Fallbackknoten aus ops.cpp. Das ist materiell für Submission:
bei [2,6] entlang der letzten Achse liefert Split pro Hälfte data_size=6,
nicht die überstrichene Spanne von 9 Elementen. Der neue Graph zählt das
referenzgleich; die älteren isolierten Buffer-Helper sind damit nicht pauschal
als graph-/scheduling-identisch erklärt.
Die SiLU-Graphoperation nutzt die unveränderten 19 erfassten JIT-Varianten.
Contiguity, Joint-Collapse, negative/large Indizes, dynamische Ränge und
Donation folgen common/compiled.cpp und metal/compiled.cpp. Insbesondere
hat compiled Donation keine 16-KiB-Slack-Grenze; diese wird nicht aus Unary
übertragen. Die Kernelwahl liest die Output-Data-Größe wie im Referenzcode
vor der Allokation, nicht ersatzweise die logische Shape. Dieser Port betrifft
den erfassten nichtskalaren BF16-SiLU-Pfad, nicht einen allgemeinen Compiler.
24 neue modellfreie Receipts wurden direkt durch die tatsächliche MTPLX- Klasse erzeugt: 1/4/7/2048 Zeilen, installierte 2560→1280→640→2560-Projektionen und kleine 128/64-Grenzfälle, 4-/8-Bit und Gruppen 32/64. Alle 24 finalen Outputs sind exakt. Zusätzlich stimmen beide Outputs der zehn vorhandenen SiLU/Gate-Up-Fixtures durch den echten Split-/Multiply-Graphen exakt. Separate Layoutprüfungen decken Split-Geschwisterauswahl, wiederholte und allgemeine Indizes, Strides/Offsets und compiled Donation ab. Positive und negative nichtzusammenhängende Ränge 4/8 decken die festen und dynamischen erfassten SiLU-Kernel ab. Die Donation eines Inputs mit negativer Singleton-Stride übernimmt im strided compiled Zweig die Output-Strides; diese beim abschließenden Source-Abgleich korrigierte Stelle hat einen eigenen Regressionstest.
Der Referenzgenerator verwendet den bestehenden Pattern-/QuantizedLinear-
Aufbau gemeinsam mit den MoE-Fixtures; kein Download und kein Modellladen.
Referenzreceipts: tests/fixtures/mtplx-shared-mlp.jsonl. Produktanbindung,
übrige Modelloperationen und Gesamtmodell-Performance-Parität bleiben offen.
Prüfstand: gesamte Port-Suite 85/85 normal (43,50 s) und 85/85 unretained
(43,79 s). Nach der abschließenden Singleton-Stride-Korrektur die beiden
betroffenen Tests erneut 2/2 normal (0,28 s), 2/2 unretained (0,31 s)
und 2/2 Fast-Fences (0,27 s). Clippy, Produkt-Buildcheck, Python-Syntax,
Format-/Diff-Prüfung und Originalquellen-/Metallib-Prüfung bestanden.
Prüfbeleg: local-eval-results/20260907-mtplx-port/graph-shared-mlp-check.log.
Qwen-Normalisierungsmodule als zusammenhängender Graph (2026-09-07)
normalization.rs bildet jetzt GroupedRMSNorm und SigmoidRMSNormGated
aus qwen4_exp.py:350–386 als gewöhnliche Graphknoten ab. Gruppierte Norm:
Reshape → ungewichtete RMSNorm → Reshape → voller Gewichts-Multiply.
Die Gewichtung wird nicht in RMSNorm gezogen; die BF16-Rundungsstelle bleibt.
Gated Norm: gewichtete RMSNorm, Gate-Cast nach FP32 → Sigmoid,
Norm-Cast nach FP32 → Multiply mit Gate als erstem Operand → Rückkonvertierung
auf den Hidden-State-Typ. Auch ohne Gate erfolgt diese Rückkonvertierung.
Keine neuen Shader und kein eager Callback für das gesamte Modul.
Alle 25 bestehenden tatsächlichen MTPLX-Modulreceipts stimmen exakt: zehn Gruppierungs-/Kernelgrenzfälle und fünf Tokenzahlen (1/4/7/11/2048) mit keinem, zusammenhängendem oder gestridetem Projektions-Gate. Projektions- Gates entstehen durch echte Slice-/Reshape-Knoten, nicht vorab dichte Buffers. Zusätzliche Prüfungen sichern gemischte Gewichtstypen, Rückkonvertierung mit/ohne Gate und ungültige Gruppengrößen ab.
Prüfstand: gesamte Port-Suite 86/86 (44,38 s); beide Normalisierungs-
Graphprüfungen zusätzlich 2/2 unretained (0,26 s) und 2/2 Fast-Fences
(0,26 s). Clippy, Produkt-Buildcheck und Originalquellen-/Metallib-Prüfung
bestanden. Beleg: local-eval-results/20260907-mtplx-port/graph-norm-check.log.
Der Graph bleibt cfg(test); vollständige Modell-/Produktanbindung und
Gesamtmodell-Performance-Parität bleiben offen. Dies ersetzt keinen P16-Lauf.
GDN-Decode als Zustandsgraph und Dispatch-Geometrie (2026-09-07)
qwen_mtplx/gdn.rs verbindet die Eingangsprojektionen, den tatsächlichen
dreifachen Custom-Kernel-Output und die Ausgangsprojektion als normale
Array-Knoten. Fusionierte Projektionen verwenden Split-Geschwister; getrennte
und gemischt quantisierte Projektionen bewahren qkv → z/Head-Reshape → b → a.
Conv- und FP32-Delta-Zustand werden als Graphwerte an den Folgeschritt gegeben.
Ein fehlender Conv-Zustand mit vorhandenem Delta-Zustand entsteht wie in der
Referenz als Broadcast-Nullarray, das erst am Custom-Kernel materialisiert wird.
Die Custom-Primitive folgt metal/custom_kernel.cpp: alle drei Outputs zuerst
allokieren, danach nicht-row-contiguous Inputs in Argumentreihenfolge per
General-Copy vorbereiten, Offsets/physische Data-Größen binden und Kopien bis zur
Command-Completion halten. Kein eager Mehrkernel-Callback und kein neuer Shader.
Konkrete Geometrieabweichung korrigiert: Der bisherige eager gdn_decode
übermittelte das MTPLX-Thread-Grid [256,1,48] mit individual_threads=false.
Die native Bridge führte damit dispatchThreadgroups aus: 256 Gruppen in X
statt einer, bei identischen Ausgaben aus redundanten Schreibvorgängen.
gdn_step_fused.py:237/custom_kernel.cpp verlangen dispatchThreads.
Der neue Graph und der alte Helper nutzen jetzt dieselbe korrekte Bindung.
Das ist eine Korrektur im bislang cfg(test)-Port, keine Erklärung oder
Behebung des produktiven UI-Stalls. Es wurde kein Gesamtmodell-Speedup daraus
abgeleitet.
Ein opt-in Test-Recorder erfasst erfolgreiche native Dispatch-Aufrufe mit
Kernelname, Grid, Gruppengröße und Thread-/Gruppensemantik. Regressionstests
prüfen den tatsächlichen GDN-Aufruf im eager und Graph-Pfad, nicht nur Hashes.
Der Recorder ist cfg(test) und gelangt nicht in Produktmessungen.
Zwölf bestehende tatsächliche GatedDeltaNet.__call__-Receipts stimmen exakt:
fused/separate/mixed, mit/ohne anfänglichen Conv-Zustand, jeweils zwei Schritte.
Jeder Fall läuft sowohl mit Evaluation pro Schritt als auch als ein verbundener
Graph mit gemeinsamer späterer Evaluation. Zwei weitere GDN-Kernelreceipts
prüfen gestridete Inputs mit Offset, General-Copies und Evaluation vom letzten
Output-Geschwister aus. Wiederverwendung des MLP-Affine-Fixture-Helfers; keine
neuen Referenzdaten, Modelle oder Downloads erforderlich.
Prüfstand: Port-Suite 88/88 normal (43,96 s); nach dem abschließenden
z-Reshape-Reihenfolgeabgleich 88/88 unretained (44,01 s) und betroffene
Graphprüfungen 2/2 normal (0,18 s) / 2/2 Fast-Fences (0,18 s). Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung und Originalquellen-/Metallib-Prüfung
bestanden. Beleg: local-eval-results/20260907-mtplx-port/graph-gdn-check.log.
Staged Prefill/Verify, Branch-/Capture-/Cache-Orchestrierung und vollständige
Modell-/Produktanbindung bleiben offen; P06 und die P16-Paritätsabnahme bleiben
unerledigt. Die neue Funktion ersetzt ausdrücklich nicht deren übrige Zweige.
GDN-Verify, Delta-Update und gemeinsame Compiled-Ausführung (2026-09-07)
Der fusionierte Conv-Verify-Zweig für B=1/S=2..6 ist jetzt durchgehend als Array-Graph verbunden: Eingangsprojektionen/Split → Conv/Norm → Delta-Update → SigmoidRMSNormGated → Ausgangsprojektion. Conv-/Delta-Zustand und die sechs Capture-Commit-Eingänge werden referenzgleich weitergegeben. Capture hält qkv/q/k/v/a/b nur bei aktivierter Erfassung; ohne Capture werden diese zusätzlichen Referenzen nicht im Rückgabewert gehalten. Cache-Advance und Modell-Branchauswahl bleiben Aufgaben der noch ausstehenden Orchestrierung.
gated_delta_update enthält normale Sigmoid-, Compiled-compute_g- und
Custom-Kernel-Knoten einschließlich optionalem FP32-Nullzustand und Maske.
Die ursprünglichen Conv/Norm- und Rekurrenzkernel verwenden gemeinsam die
CustomKernel-Allokations-/Copy-/Lebensdauerfolge des vorigen Decode-Ports.
Der GDN-Conv-Dispatch zählt 10240 Threads/1024 pro Gruppe; Delta zählt
[32,128,B*48] Threads mit [32,4,1] pro Gruppe. Die Testbeobachtung an der
nativen Grenze sichert diese Geometrien ab.
SiLU und compute_g verwenden den gemeinsamen compiled.rs-Evaluator für die
bereits erfassten nichtskalaren Kernel: Contiguity über alle Eingänge,
Broadcast-/Joint-Collapse, negative/large Indizes, Output-Allokation und
Donation gemäß common/compiled.cpp/metal/compiled.cpp. Kein neuer Shader
und kein allgemeiner JIT-Ersatz. Ein direkter DOT-Export aus dem gepinnten
Referenzprozess bestätigt A_log [48], a [1,1,48] und dt_bias [48] als
direkte Compiled-Eingänge; die Softplus-Konstante ist im erfassten Shader.
Auch die einzelne GDN-Zeile wählt deshalb den kollabierten strided-1-Kernel,
nicht anhand der physischen Länge einen contiguous-Kernel. Die tatsächliche
compute_g-Kernelwahl wird für alle 80 Delta-Receipts mitgeprüft.
Nachweise: sechs Conv/Norm-Kernelreceipts und 80 tatsächliche Delta-Update- Receipts exakt (1/4/7/32/2048 Zeilen, beide Gate-Layouts, Maske an/aus, Initialzustand an/aus, zwei fortgesetzte Schritte). Zwölf vollständige echte Verify-Modulreceipts bei 2/4/6 Zeilen stimmen einschließlich Q/K/V exakt; alle drei Hauptoutputs ohne Capture sind dazu bytegleich. Der erste Verify-Testversuch verwendete für vier Zeilen einen nicht existierenden Forward-Fixturenamen; die Zuordnung wurde auf die vorhandenen vollständigen Staged-Receipts korrigiert, keine Referenzwerte oder Hashprüfung abgeschwächt.
Prüfstand: gesamte Port-Suite 90/90 normal (46,46 s) und 90/90 unretained
(45,17 s). Fast-Fences: GDN 4/4 (1,13 s), MLP 2/2 (0,28 s).
Nach zusätzlicher compute_g-Dispatch-Assertion derselbe betroffene Test erneut
normal/unretained/Fast-Fences bestanden (0,94/0,90/0,96 s). Clippy,
Produkt-Buildcheck, Format-/Diff-Prüfung und Originalquellen-/Metallib-Prüfung
bestanden. Beleg: local-eval-results/20260907-mtplx-port/graph-gdn-verify-check.log.
Offen bleiben der allgemeine Concatenate/Conv1d/Reduktions-Prefill-Graph, maskierte/ragged Conv-Fallbacks, Single-Row-Output-Fusion als Graph, vollständige Branch-/Capture-Commit-/Cache-Orchestrierung und Produktintegration. Die 2048-Zeilen-Rekurrenzprüfung ist kein vollständiger Prefill-Nachweis. P06/P16 und das Drei-Modell-Performanceziel bleiben ausdrücklich offen.
GDN-Conv1d-Prefill als zusammenhängender Array-Graph (2026-09-07)
Der unmaskierte, längenlose Conv1d-Fallback ist jetzt von den Eingangsprojektionen bis zur Ausgangsprojektion verbunden: Concatenate → Contiguous-Conv-Zustand → Depthwise-Conv1d → erfasste SiLU → Split/Head-Reshape → FP32-L2-Summe/Rsqrt → BF16-Rückkonvertierung/Q-Skalierung → Delta-Update → SigmoidRMSNormGated → Ausgangsprojektion. Auch S=1 bei abgeschalteter Fusion nimmt diesen Pfad. Die vorherige Beschränkung auf den fusionierten Verify-Zweig entfällt damit für unmaskierte Eingaben ohne Cache-Längen. Modellwahl und cache.advance(S) sind weiterhin nicht durch diese Graphfunktion ersetzt.
Concatenate verwendet die gemeinsame Copy-Implementierung jetzt auch als
GeneralGeneral: gemeinsame Kollabierung von Quell-/Ziel-Strides, echte
Byte-Offsets, Referenz-Datengrößen und concurrent disjoint writers. Die
Output-Slices sind wie in der Referenz primitive-/speicherlose temporäre
Array-Deskriptoren mit anschließend geteiltem Output-Backing. Conv1d allokiert
zuerst den Output und materialisiert danach bei Bedarf Input und Gewicht in
dieser Reihenfolge. Kein neuer Shader und keine eigene Faltung: Der originale
depthwise_conv_1d_*-Kernel zählt [C,Tout,B] Threads. Die GDN-Summe wählt
referenzgleich zwischen row_reduce_looped (16 Köpfe bei S=1) und
row_reduce_simple (ab 32 Köpfen); die übrigen allgemeinen Reduktionspläne
werden nicht als portiert ausgegeben.
Der bestehende vollständige Modulreceipt-Test umfasst jetzt 52 Fälle: 12 fusionierte Verify-Fälle und 40 Conv1d-Fallback-Fälle, S=1/2/4/6/7/32/2048, Initialzustand an/aus, zwei fortgesetzte Schritte und die jeweils anwendbaren Fusionsflags. Alle sechs Output-Hashes einschließlich q/k/v sowie beider Folgezustände sind exakt. Ohne Capture stimmen die drei Hauptoutputs bytegenau mit dem Capture-Lauf überein. Kernelwahl und Dispatch-Geometrie von Conv1d und beiden Summen werden an der nativen Grenze zusätzlich geprüft. Der strided V-Capture wird ausschließlich nach dem eigentlichen Forward für den Fixture-Reader gepackt; der Modellgraph behält seinen originalen View. Ein kleiner zusätzlicher Concatenate-Test prüft vierdimensionale transponierte und rückwärts gerichtete Views, alle vier Achsen, Typ-Promotion, leere Inputs und die Referenz-Single-Input-Identität vor Achsenvalidierung.
Prüfstand: komplette Port-Suite 91/91 normal (45,89 s) und 91/91 unretained
(45,40 s); Fast-Fences: GDN 4/4 (1,84 s), Concatenate 1/1 (0,05 s).
Clippy, Produkt-Buildcheck, Format-/Diff-Prüfung bestanden. Originalquellen weiterhin
15 Körper / 35 Custom-Einstiegspunkte / 20 Runtime-Einheiten / 84 Runtime-
Einstiegspunkte plus dynamische QSA-Quellen exakt, unveränderte Metallib-SHA256
dc59d1cceb1a5c7e578232e6e41e28e2c73c9463ac6dbc3886c3ee17ffc270ed.
Prüfbeleg: local-eval-results/20260907-mtplx-port/graph-gdn-prefill-check.log.
Weiter offen: maskierter Conv-Select, ragged Cache-Längen/Gather,
Single-Row-Output-Fusion als Graph, vollständige Modell-/Cache-/Capture-Commit-
Orchestrierung und Produktintegration. P06/P16 bleiben offen. Der gesamte Port
ist weiterhin cfg(test); weder UI-Responsivität noch Durchsatzparität sind
damit nachgewiesen. Die vollständigen Drei-Modell-Chats werden dadurch nicht
ersetzt; es gab keinen Modelllauf, Download oder Performance-Rollback.
Maskierter und längenabhängiger GDN-Prefill (2026-09-07)
Der Conv1d-Graph enthält nun auch MTPLXs Maskierungs- und ragged-State-Zweig.
QKV wird vor Concatenate mit where(mask[..., None], qkv, 0) maskiert; Capture
bewahrt genau diesen QKV-Strom. Die ursprüngliche Maske geht zusätzlich an die
Delta-Rekurrenz. Für Cache-Längen bleibt die Referenzfolge als einzelne Knoten
erhalten: Maximum/Minimum auf [0,S] → ExpandDims → Arange(INT32) → Add →
ExpandDims → GatherAxis über das Conv-Fenster. Keine CPU-Auswertung des
Längentensors und kein vorgezogener GPU-Sync. Ohne Längen bleibt der bestehende
Contiguous-Tail-Zweig unverändert.
indexing.rs enthält die dazu verwendeten Select-, GatherAxis- und Prefix-
Arange-Primitiven. Select übernimmt Typ-/Broadcast-Regeln sowie Scalar-/Vector-/
General-Kernelwahl, Donation, Strides und Dispatch aus der gepinnten Runtime.
Gather verwendet die bereits exportierten BF16/I32- bzw. BF16/U32-Kernel mit
tatsächlichen Src-/Index-Contiguity-Flags, Größen, Strides und Byte-Offsets.
Statisches Broadcast wird von Binary, Select und GatherAxis gemeinsam genutzt.
Andere Gather-Dtypes bzw. dynamisches Broadcast-Tracing werden damit nicht als
portiert erklärt.
Eine ABI-Abweichung wurde an der gemeinsamen Bridge behoben: Leere Inline-
Vektoren werden von ds4_gpu_mtplx_encode nicht mehr pauschal zurückgewiesen.
Die Referenz bindet bei Rank-1-Gather tatsächlich null Byte für Shape/Strides.
Die Bridge führt jetzt denselben Metal-Aufruf aus; kein Dummy-Payload, keine
Shaderänderung. Nichtleere Nullpointer, Übergröße, Offsets und doppelte Slots
werden weiterhin zurückgewiesen. Der Rank-1-Gather-Test schließt rückwärts
gerichtete Source-/Index-Views mit nichtnull Byte-Offsets ein.
Der erweiterte vollständige GDN-Modultest prüft 116 MTPLX-Receipts exakt, jeweils sechs Outputs einschließlich beider Zustände, plus bytegleiche Capture-off-Hauptoutputs. S=1/2/4/6/7/32/2048, maskiert/unmaskiert, zwei fortgesetzte Schritte, Initialzustand an/aus und Längen unter/innerhalb/über der Chunk-Grenze. Längenfälle hier S=4/7; S=1 bei aktivierter Output-Fusion bleibt bis zum Port dieser Fusion offen. Die tatsächliche Select-/Gather-Kernelwahl und Geometrie werden zusätzlich beobachtet. Ein kleiner Indexing-Test deckt alle fünf Select-Layoutarten, Column-Layout, Broadcast-Gather, negative Indizes, BF16/I32/U32, Rank-1-Leerargumente und leeres Arange ab.
Prüfstand: gesamte Port-Suite 92/92 normal (45,39 s) und 92/92 unretained
(45,23 s). Fast-Fences: GDN 4/4 (2,62 s), Indexing 1/1 (0,06 s).
Clippy (8,87 s), Produkt-Buildcheck (3,26 s), Format-/Diff- und Originalquellen-/
Metallib-Prüfung bestanden. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-gdn-masked-lengths-check.log.
Weiterhin offen sind Single-Row-Output-Fusion, vollständige Modell-/Cache-/
Capture-Commit-Orchestrierung und Produktintegration. Der Port bleibt
cfg(test); keine Modell-/UI-/Performance-Paritätsbehauptung. P06/P16 und das
vollständige Drei-Modell-Ziel bleiben offen; keine Downloads oder Rücknahmen.
Gemeinsamer GDN-Forward, Output-Fusion und Cache-Fortschreibung (2026-09-07)
Die getrennten kanonischen fused_decode-, prefill- und fused_verify-
Einstiege sind durch gdn::forward ersetzt. Dieser bildet für die installierte
Inferenzgeometrie die Reihenfolge von GatedDeltaNet.__call__ ab: Projektionen,
Conv-State/Maskierung, Fused-Step oder Conv-Zweig, Capture, Delta-Update,
Cache-Fortschreibung und Output-Fusion oder Norm/Projektion. Die unveränderten
Kernel werden nicht anhand lokaler Geschwindigkeitsvergleiche ausgewählt.
- Capture sperrt den Live-Step, aber nicht pauschal Conv-/Output-Fusion. Bereits gespeicherte Capture-Arrays bleiben erhalten, bis ein neuer Capture- Aufruf sie ersetzt. Der Step-Zweig kehrt vor der separaten Output-Fusion zurück.
- Cache-Längen und Masken sperren Conv-Fusion; B>1 und fehlender Cache verwenden den allgemeinen Conv-Zweig. Ohne Cache wird kein Cache-Tail-Graph erzeugt. Die tatsächlichen einmaligen Single-/Multi-Row-Geräteproben werden wie in MTPLX ausgeführt und ihr Erfolg pro Prozess gespeichert.
Cache::advancesubtrahiert S von Längen und linkem Padding als Tensor- Operationen, bevor der Output-Graph aufgebaut wird; kein CPU-Readback. Der aktuelle Vertrag für diese Metadaten ist INT32.- Die Single-Row-Output-Fusion verwendet die Originalkörper für Gruppen32/64 und BF16/FP32-Eingabe, einschließlich exakt 81920 Threads in 1024er Gruppen.
Referenzabdeckung: alle 264 Forward-Receipts mit fusionierten, getrennten und gemischt quantisierten Eingangsprojektionen; jeweils sofortige und verzögerte Auswertung zweier aufeinanderfolgender Aufrufe. Zusätzlich werden die tatsächlich ausgeführten Step-/Conv-Fusionszweige gegen die Referenzdaten geprüft. Alle 130 Staged-Receipts sind nun eingeschlossen, auch die zuvor fehlenden Single-Row-Fälle mit Output-Fusion. Vier direkte Output-Kernel- Receipts sichern Typen, Gruppen und Dispatch-Geometrie ab.
tools/mtplx-kernel-fixtures.py:gdn_graph_lifecycle_fixtures erzeugt außerdem
24 neue tatsächliche MTPLX-Modulreceipts, nicht Rust-generierte Sollwerte:
B=1/2, S=1/7, kein Cache/leerer Cache/Metadaten, jeweils zwei Aufrufe mit Capture
nur beim ersten. Sie prüfen Ausgaben, Conv-/Delta-Zustände, Längen/Padding und
den Erhalt der Capture-Array-Identitäten beim Folgeaufruf.
Verifikation: vollständige Port-Suite 92/92 (48,75 s), mit unretained
Command Buffers 92/92 (48,96 s); GDN mit Fast-Fences 4/4 (5,46 s).
Release-Clippy, Produkt-Check, Format-/Diff-Check und unveränderter
Referenz-Shaderexport bestehen. Der Prüfbeleg liegt unter
local-eval-results/20260907-mtplx-port/graph-gdn-forward-check.log.
Weiter offen: äußerer Modellablauf mit Maskenerzeugung, Cache-Batchoperationen,
Capture-Commit/Repair, weitere Graphkomponenten und Produktintegration.
Der kanonische Graph bleibt cfg(test). Diese Modulprüfungen sind weder eine
UI-Responsivitätsmessung noch ein Nachweis der Modell-/Performance-Parität;
P06/P16 und das Drei-Modell-Ziel bleiben offen.
GDN-Capture-Commit mit nachfolgendem Decode (2026-09-07)
gdn::Cache übernimmt jetzt die Validierungsregeln und den reinen GDN-Zweig
von Qwen4ExpTextModel.commit_verified_window: validierte Capture-Zeilen auf
die angenommene Länge beschränken, Delta-Rekurrenz vom Snapshot ausführen,
Conv-Tape aus Snapshot und behaltenem QKV bilden, Capture freigeben. Fehlender
Conv-Snapshot wird wie in MTPLX durch einen Nullzustand ersetzt; Delta-Snapshot
und passende Capture-Breite sind verpflichtend. Längen/Padding werden dabei
weder zurückgesetzt noch fortgeschrieben.
Die Trennung zwischen Validierung und Replay erlaubt dem noch zu verbindenden äußeren Modellablauf, zuerst alle Schichten zu validieren und erst danach irgendeinen Cache zu verändern. Sie ersetzt diese globale Transaktion nicht. QSA-Trim, PLE-Replay und die übergeordnete Fehler-/Rollback-Orchestrierung bleiben ausdrücklich offen. Kein vollständiger P12-Abschluss.
26 neue tatsächliche MTPLX-Commit-Receipts decken Fenster1/2/4/6, jede behaltene Präfixlänge und vorhandene/fehlende Conv-Snapshots ab. Die sieben Ausgabehashes einschließlich des nachfolgenden Decode stimmen exakt; im Rust- Graph sowohl bei sofortiger als auch verzögerter Commit-Auswertung. Native Dispatch-Aufzeichnung prüft: keine Submission während der Commit-Konstruktion, nur eine Delta-Rekurrenz und keine Projektionen/Conv-Kernel im isolierten Replay. Ungültige Präfixe, fehlende/kurze Snapshots und fehlende/falsch breite Captures werden ohne Veränderung der Cache-Array-Identitäten geprüft.
Ein zunächst abweichender Metadatenhash lag am Ablesezeitpunkt des Tests:
Pythons mx.array.__isub__ überschreibt den Deskriptor des gespeicherten
Metadatenobjekts beim folgenden Decode. Der Rust-Test liest deshalb die dann
aktuellen Cache-Metadaten statt einer vorher angelegten Wertkopie. Die echten
MTPLX-Receipts wurden nicht geändert; der Commit selbst erhält die Metadaten.
Verifikation: Port-Suite 92/92 (49,60 s), unretained 92/92 (49,50 s);
GDN mit Fast-Fences 4/4 (5,90 s). Release-Clippy, Format-/Diff-Check und
unveränderter Shaderexport bestehen. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-gdn-commit-check.log.
Der kanonische Port ist weiterhin ausschließlich cfg(test); keine Aussage
über Produktperformance, UI-Responsivität oder die 2%-Abnahme.
Hyper-Connection-Graph und Original-Quantisierung (2026-09-07)
Der kanonische Graph verbindet jetzt die Custom-Primitiven von
hyper_connection.py und hyper_connection_v3.py mit der originalen
prepare_v3_pack-Kette: Down/Inject konkatenieren, beide Matrizen mittels
fast::Quantize quantisieren, sechs Contiguous-Ausgänge auswerten. Die V3-
Geräteprobe führt beide echten Kernel mit den originalen Dummy-Geometrien aus
und speichert ihr Ergebnis pro Prozess. Die Probe bleibt vor der kostenpflichtigen
Pack-Vorbereitung dem noch zu verbindenden Modellselektor zugeordnet.
linear::quantize übernimmt Shape-/Parameterprüfung, drei Array-Siblings,
Allokationsfolge und Row-Contiguous-Kopie aus dem gepinnten Runtime-Backend.
Es bindet die unveränderten affine_quantize_*-Kernel aus derselben Metallib:
Gruppen32/64/128, Bits2/3/4/5/6/8, BF16/F16/F32. Die allgemeinen Elementkernel-
Typnamen sind hier nicht gültig; die originalen affinen Symboltypen lauten
bfloat16_t, float16_t und float. Diese Bindungsabweichung wurde bei der
ersten Ausführung erkannt und korrigiert, ohne Shaderänderung.
59 tatsächliche Quantisierungsreceipts decken alle 54 Typ-/Gruppen-/Bit- Kombinationen sowie Slice, Transpose und Null-/Positiv-/Negativkonstanten ab. U32-Packs werden roh gehasht, nicht verlustbehaftet nach Float konvertiert. Der echte V3-Pack stimmt in allen sechs Ausgängen exakt mit MTPLX überein; anschließende V3-Leseschritte stimmen sowohl mit neuen als auch bisherigen Sollwerten überein. Die ursprünglichen Read-Kernel mit/ohne Injection bei S=1/4/8 sind ebenfalls über den Graphen geprüft. R1/R2 verwenden genau ihre 11264/81920 Threads, jeweils 1024 pro Gruppe, und zusammen einen Command Buffer.
Der frühere direkte V3-Test mit kernel_qwen_quantize_hyper_q8 ist entfernt;
seine Ausgabereferenz und One-Command-Buffer-Prüfung liegen jetzt im verbundenen
Test mit Originalquantisierung. Der letztere prüft den Zähler des tatsächlichen
Graph-Streams, nicht den globalen Zähler der alten Produktqueue.
Zu diesem Zwischenstand noch offen für GatedResidual: eager Norm/Matmul/Mean-
Kette, Modellselektion und Lebensdauer des pro Modul gecachten Packs sowie
Verbindung mit dem restlichen Modell und Produktpfad. Keine Rücknahme wegen
Mikrobenchmark-Ergebnissen; cfg(test), P09/P16 und Gesamtparität bleiben offen.
Verifikation: vollständige Port-Suite 94/94 (51,84 s), unretained
94/94 (51,14 s). Fast-Fences: Hyper 1/1 (0,09 s), Quantize
1/1 (0,26 s). Release-Clippy, Format-/Diff-Check und unveränderter
Shaderexport bestehen. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-hyper-quantize-check.log.
Verbundener GatedResidual einschließlich eager Prefill (2026-09-07)
hyper::GatedResidual verbindet jetzt für die installierte BF16-Geometrie
den vollständigen Read: GroupedRMSNorm, Down/4, SiLU, Up/Sigmoid, gruppiertes
Produkt und Mean sowie die optionale Injection. Mean bleibt wie im Original
eine BF16-Summe mit anschließender BF16-Multiplikation mit1/4. Die dense
Projektion verwendet die unveränderte Runtime-Metallib mit originaler
M5-Max-Auswahl: GEMV, Wide-GEMV bis15 Zeilen, NAX-GEMM und NAX-Split-K samt
FP32-Zwischenergebnis und BF16-Akkumulationsausgang. Statisches Flatten/Unflatten,
Transpose-/Kopierprüfung, Function Constants, Bindings und Dispatch-Geometrie
folgen ops.cpp, matmul.cpp und reduce.cpp der gepinnten Runtime.
Der Modellselektor prüft zuerst V3 (eine Zeile, Combine, nichtquantisierter Down, Geräteprobe), anschließend den ursprünglichen fusionierten Read (bis8 Zeilen), ansonsten eager. Der V3-Pack gehört zur Modulinstanz, wird nur einmal erzeugt und über spätere Fused-/Eager-Aufrufe hinweg erhalten. Der Combine-Ausgang behält die ursprüngliche Hyper-Array-Identität. Quantisierte HC-Projektionen bleiben entsprechend MTPLX auf der eager-Kette.
hyper_forward_fixtures ruft die tatsächliche MTPLX-Klasse auf, ohne sie
nachzuimplementieren. Alle 128 Fälle stimmen exakt überein: dichte und
quantisierte Gewichte, mit/ohne Combine, S=1/2/4/8/15/16/32/2048 und alle vier
Kombinationen der beiden HC-Schalter. Geprüft sind beide Ausgänge, ausgewählter
Pfad (111 eager,15 fused,2 V3), Pack-Existenz/-Identität und die native
NAX-/Split-K-Auswahl. Keine Referenzwerte wurden an Rust-Ergebnisse angepasst.
Die Operatoren sind weiterhin nur Teil des kanonischen cfg(test)-Ports.
DecoderLayer/PLE, vollständige Modell- und Produktanbindung sowie P09/P16-
Gesamtabnahme bleiben offen. Die Beschränkung des dichten Wrappers auf die
installierten BF16-Projektionen ist kein Nachweis für beliebige Datentypen,
Dot-Produkte, leere Matrizen oder andere GPU-Architekturen. Es gab keine
Shaderänderung, kleinere Prefill-Chunks oder Rücknahme nach Mikrobenchmarks.
Verifikation: gesamte Port-Suite 95/95 (55,49 s), unretained
95/95 (52,73 s), Hyper mit Fast-Fences 2/2 (0,94 s). Release-Clippy,
Format-/Diff-Check und unveränderter Shaderexport bestehen. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-hyper-forward-check.log.
PLE-Projektion und dilatierte Cache-Fortsetzung (2026-09-07)
Der kanonische Graph verbindet PLELayer ab dem Ergebnis von
NGramEmbedding: Embedding-Cast, Key-/Value-Projektionen, drei GroupedRMSNorms,
BF16-Produktsumme, Divisor/Signed-Sqrt-Gate, Sigmoid, Broadcast/Reshape und
Short-Conv mit anschließendem SiLU und Residual-Add. Vorhandene dichte und
quantisierte Projektionen sowie Graph-/Copy-/Norm-/SiLU-Operatoren werden
wiederverwendet. Abs/Sign folgen dem originalen Typvertrag. Die gemeinsame
Row-Sum-Auswertung erhält GDNs FP32x128-Route und ergänzt PLEs BF16x2560-Route
mit640 Threads und originaler Simple-/Looped-Grenze.
Die PLE-Faltung mit Kernel4/Dilatation3 ist nicht der GDN-Depthwise1D-Pfad.
Die gepinnte Runtime bettet sie in2D ein und verwendet
implicit_gemm_conv_2d_bfloat16_bm32_bn8_bk16_wm4_wn1_channel_1_filter_l.
Rust bindet diesen unveränderten Metallib-Kernel mit den originalen Conv-/GEMM-
Parametern und der Grid-Geometrie. Ausgabeallokation sowie Input-/Weight-Kopien
verwenden denselben vorhandenen Helper wie GDN, in Originalreihenfolge.
Der Cache speichert die letzten9 Zeilen des Fensters als lazy Slice; die
Faltung liest noch das ganze Fenster, bevor der letzteS-Abschnitt aktiviert wird.
84 tatsächliche MTPLX-PLELayer-Receipts prüfen dense/quantized, S=1/4/7/8/ 32/2048 sowie Batch2/S7; kein, leerer oder12-zeiliger Vorzustand, jeweils mit anschließendem Ein-Zeilen-Decode. Der zweite Embedding-Eingang ist FP32 und wird wie im Modell auf BF16 gecastet. Ausgabe und Cache stimmen exakt überein, sowohl bei unmittelbarer als auch gemeinsamer verzögerter Auswertung (168 Vergleiche). Native Faltungsauswahl/-Geometrie ist zusätzlich geprüft. Der Fixture-Provider ersetzt ausschließlich den Lookup-Eingang; der restliche Aufruf ist die tatsächliche unveränderte MTPLX-Klasse. Dies beweist keinen N-Gram-Lookup, kein Staging und keine IO-/LRU-Parität.
Noch offen: NGramEmbedding samt Graph- und Staging-Pfaden, Sidecar/Resident-
Auswahl, Dequantisierung und Hot-Cache-Vertrag sowie Decoder-/Modell-/Produkt-
Anbindung. Der bisherige Produkt-PleReader arbeitet noch anders als MTPLX
(u.a. erste-Auftritts-Deduplizierung statt sortierter Unique-IDs und fehlender
identischer4096-Unique-Row-Bypass). Er wird nicht durch diese PLE-Projektions-
Tests freigestellt. cfg(test), P10/P16 und das Drei-Modell-Ziel bleiben offen.
Verifikation: gesamte Port-Suite 96/96 (51,40 s), unretained
96/96 (51,07 s), PLE mit Fast-Fences 1/1 (1,48 s). Release-Clippy,
Format-/Diff-Check und unveränderter Shaderexport bestehen. Prüfbeleg:
local-eval-results/20260907-mtplx-port/graph-ple-projection-check.log.
N-Gram-CPU-Staging-Hash und rohe History (2026-09-07)
ngram::HashContract::rows übernimmt den materialisierten CPU-Hash aus
NGramEmbedding._rows_np für den installierten Vertrag mit3-Grams/16 Heads.
Int64-Multiplikation, XOR, positiver Rest und Offsetaddition erhalten das
Overflow-Verhalten der NumPy-Referenz. EOS beeinflusst die verschobenen Tokens
erst nach dem Hash der EOS-Position; der zurückgegebene History-Cache behält
die tatsächlichen letzten2 Tokens. Eine EOS-normalisierte History ist nicht
die Cache-Repräsentation der Referenz. Der bisherige Produkt-Einzel-Token-Hash
bleibt davon getrennt; daraus allein wird kein Unterschied seiner fertigen
Row-IDs oder eine Ursache der UI-Verzögerungen behauptet.
64 Original-Receipts verwenden die installierte EOS-ID248044 und die Originalkonstanten. B=1/2, S=0/1/4/2048, vorherige History-Längen0/1/2/5 und jeweils ein Fortsetzungstoken stimmen in Roh-I64-Ausgabehashes und Shapes exakt überein. Fälle enthalten aufeinanderfolgende EOS, negative Werte und Int64- Grenzwerte. Auch die Python-Slice-Semantik bei S=0 (alle History-Rows) bleibt erhalten. Eingabe-/History-Formen und positive Head-Größen werden geprüft. Rust benötigt keine NumPy-Zwischenmatrizen; die gleiche Berechnung läuft in einem Durchgang, ohne eine GPU-Auswertung oder Synchronisierung einzuführen.
Dies ist ausschließlich der CPU-Hash-Baustein, noch kein verbundenes
NGramEmbedding.stage/__call__. Lazy GPU-Hash, Stage-Auswahl/-Verifikation,
Sidecar/Resident-Gather, Dequantisierung und LRU/Bypass bleiben offen; der
pipelined-AR-Pfad wird nicht durch diesen CPU-Baustein ersetzt. P10/P16,
Produktintegration und Drei-Modell-Performanceabnahme bleiben offen.
Verifikation: CPU-Port-Suite 22 bestanden,75 GPU-Tests explizit ignoriert;
Release-Clippy, Format-/Diff-Check bestehen. Keine neue GPU-Performanceprüfung
für diesen CPU-only-Baustein. Prüfbeleg:
local-eval-results/20260907-mtplx-port/ngram-cpu-hash-check.log.
Lazy N-Gram-GPU-Hash bis zu den Tabellen-IDs (2026-09-07)
ngram::GpuHash::rows bildet nun die originale _graph_path-Kette bis zum
Tabellenaufruf nach: I64-Cast, History-Concat/-Slice, beide voneinander
getrennten _shift_ignore_eos-Graphen mit Arange/Select/Cummax/Gather,
Int64-Multiply/XOR/Remainder und Head-Offsets. Checkpointkonstanten bleiben
Array-Leaves. Der Konstruktor liest keine Tokenwerte zurück und wertet keine
GPU-Knoten aus; auch eine noch nicht ausgewertete History kann weitergereicht
werden. Kein fusionierter Eigenbau-Hash und kein Ersatz durch den CPU-Hash.
Gemeinsame Graphoperatoren wurden um Equal/GreaterEqual mit Bool-Ausgang, BitwiseAnd/Xor und Remainder sowie I64-Arange/-Gather und inclusive Cummax erweitert. Für Gather sind8 zusätzliche I64/I64-Spezialisierungen des unveränderten Originaltemplates exportiert; der Original-Metallib-Hash ist unverändert. Scan übernimmt seine eigene Allokations-/Donation-Regel ohne die16KiB-Grenze des Unary-Helfers; diese Besonderheit wurde beim Quellabgleich korrigiert und mit einem oversized backing separat geprüft.
60 tatsächliche MTPLX-GPU-Receipts stimmen in IDs, roher History und Shapes exakt überein: B1/2, S1/4/2048, fehlende oder0/1/2/5-zeilige History und je ein Decode-Folgeschritt. Sofortige und verzögerte Auswertung ergeben120 Vergleiche; der Graphaufbau dispatcht nichts, beide Original-Scans und I64-Gather werden tatsächlich ausgeführt. Zusätzliche30 Scan-Prüfungen decken row-/column-major, Broadcast-Kopien, erhaltene Aliase und Threadgrößengrenzen bis4097 Elemente ab. Ein passender Folgeschritt prüft außerdem lazy I32→I64-Tokens.
Die Referenz ruft _graph_path selbst auf; ausschließlich der Tabellenaufruf
gibt im Fixture seine IDs zurück. Lookup/Dequantisierung, Sidecar/Resident-
Wahl, Stage-Auswahl/-Verifikation/-Konsum, Hot-Cache/Bypass und Decoder-/Modell-
Anbindung bleiben offen. Kein Nachweis für beliebige leere Cummax-Eingaben,
kein vollständiger NGramEmbedding-Aufruf, keine Produkt- oder2%-Abnahme.
Verifikation nach der Scan-Donation-Korrektur: reguläre Port-Suite 98/98
in51,93s, Unretained-Command-Buffer-Suite 98/98 in52,73s und der NGram-Test
mit MLX_METAL_FAST_SYNCH=1 1/1 in0,14s. Release-Clippy sowie Format-/Diff-
und Originalquellen-Prüfung bestehen. Diese Zeiten sind Testlaufzeiten, keine
Modell-Performancewerte. Prüfbeleg:
local-eval-results/20260907-mtplx-port/ngram-gpu-hash-check.log.
Verbundener residenter N-Gram-Graph (2026-09-07)
GpuHash::embedding verbindet nun den originalen Hash mit
ResidentTable::gather, affiner Dequantisierung und Head-Reshape. Der residente
Pfad liest keine IDs auf die CPU zurück und fügt keine Auswertung hinzu.
Der Loader muss die Tabelle vorab materialisieren; Laden/Residency-Entscheidung,
Sidecar-I/O, Hot-Cache, Stage-Auswahl und Produktanbindung sind noch nicht portiert.
indexing::take_rows verwendet wie die Referenz Gather plus Squeeze. Bei
zusammenhängenden Tabellen und Indizes läuft der originale GatherFront; andere
Views verwenden den originalen allgemeinen Gather, ohne vorgeschaltete Kopie.
I64-Indizes, negative Indizes, rank0..4, BF16/F16/F32/U32, Byte-Offsets und die
große Indexvariante sind im Dispatch berücksichtigt. Die neue GPU-Dequantisierung
übernimmt Output-Allokation vor den drei Contiguous-Vorbereitungen, Bindings und
Grid/Thread-Geometrie. Quantize verwendet denselben vorhandenen Copy-Mechanismus.
Die Tabelle verwendet gleiche Floating-Dtypes für Scales/Biases; gemischte
Parameter-Dtypes und nicht-affine Quantisierung werden hier nicht beansprucht.
Originalquellen unverändert: 12 weitere GatherFront-Spezialisierungen sowie40
originale Gather-JIT-Wrapper, ausschließlich mit angepassten Einstiegspunktnamen.
Zwei zusätzliche geprüfte Runtime-Units; Export insgesamt15 Custom-Bodies,
35 Custom-Einstiege und22 Runtime-Units/144 Runtime-Einstiege. Der unveränderte
Original-Metallib-Hash bleibt dc59d1cceb1a5c7e578232e6e41e28e2c73c9463ac6dbc3886c3ee17ffc270ed.
Ein erster Compile-Versuch fand die falsche Reihenfolge der Gather-Abhängigkeiten;
behoben durch Platzierung nach dem Original-Utils-Export, ohne Kerneländerung.
Neue Original-Receipts, jeweils unmittelbar und verzögert exakt verglichen:
- 324 affine Dequantisierungen: BF16/F16/F32, group32/64/128, bits2/3/4/5/6/8, plain/transpose/slice/offset/broadcast/batch.
- 162 tatsächliche
NGramTable._lazy_gather-Aufrufe: BF16/F16, raw8/9/160 und Q4x160, zusammenhängende/transpose/offset Tabellen, skalare bis4D IDs, Slice- und Broadcast-ID-Views. GatherFront/Gather-Auswahl wird geprüft. - 24 vollständige originale residente
_graph_path-Ausgaben einschließlich Decode-Folgeschritt: raw/Q4, B1/2, S1/4/2048. Tabelle bewusst klein (17 Zeilen), echte Headbreite160 und Ausgang2560; Hashkonstanten für kleine Vokabelgrößen angepasst. Kein Ersatz des Tabellenaufrufs. Embedding und rohe History stimmen exakt überein, auch wenn beide Schritte vor der Auswertung aufgebaut werden.
Das sind Korrektheits-/Graphbelege, keine Vollmodell-Performanceabnahme. Der
kanonische Port bleibt cfg(test); aus diesen Ergebnissen folgt kein behobener
UI-Stall und keine erreichte2%-Parität.
Verifikation: reguläre Port-Suite101/101 in53,44s und mit Unretained-Command-
Buffers101/101 in53,25s; Release-Clippy, Format-/Diff- und Originalquellen-Check
bestehen. Die drei NGram-GPU-Tests bestehen auch mit MLX_METAL_FAST_SYNCH=1
in0,49s. Testlaufzeiten sind keine Modell-Performancewerte. Prüfbeleg:
local-eval-results/20260907-mtplx-port/ngram-resident-check.log.
Verbundener Sidecar-Gather und Tabellenauswahl (2026-09-07)
ngram_sidecar::SidecarGather portiert nun _SidecarGather als zusammenhängenden
Dateipfad: getrennte read-only Tensor-Mappings mit Random-Advice, sortierte
eindeutige I64-IDs und inverse Expansion, optionaler persistenter Prefetch-Pool
mit höchstens16 Threads und originaler Chunkformel clamp(ceil(n/32),1,64).
Prefetch liest jede Map pro Zeile mit pread; erst anschließend sammelt die
Generation die Rohzeilen aus den Mappings. Prefetch verändert den Cache nicht.
Threads und Aufträge werden vor Freigabe sauber beendet; nur eigene temporäre
Testdateien werden entfernt.
Der Hot-Cache speichert Rohzeilen-Views auf gemeinsam gehaltene Fetch-Matrizen. Damit behalten verbleibende Zeilen wie NumPy ihren zugrundeliegenden Fetch-Block. Ein HashMap-basierter doppelt verketteter LRU bietet O(1)-Touch/Eviction ohne unbeschränkt wachsende historische Touch-Liste. Misses werden zuerst eingefügt, alle eindeutigen Zeilen danach in sortierter Reihenfolge berührt und erst dann überzählige Einträge entfernt. Die Ergebnisreferenzen überleben diese Eviction. Leere Gathers, deaktivierter Cache und mehr als4096 eindeutige IDs umgehen den LRU vollständig, ohne dessen Zähler/Reihenfolge zu verändern.
gather_np erzeugt Integer-Arrays/View und die vorhandene originale affine
Dequantisierung, ohne einen Graph auszuwerten. Der nicht gestagte gather liest
hingegen wie _SidecarGather.__call__ den einmal ausgewerteten ID-Graph auf der
CPU. Der Abgleich mit mlx_to_nd_array erhält Strides und Byte-Offsets; keine
zusätzliche Contiguous-GPU-Kopie oder zweite Auswertung. Die Rohzeilenausgabe
bleibt anschließend lazy. Table::gather übernimmt die Referenzpriorität:
bevorzugte residente Tabelle, sonst Sidecar, sonst Fehler im Sidecar-Modus oder
plain Gewicht. GpuHash::embedding verwendet jetzt diese gemeinsame Auswahl.
192 tatsächliche dateibasierte Original-Receipts: BF16/F16, raw/Q4x160,
Prefetch aus/an, Kapazität0/3/4096 Zeilen, wiederholte/negative IDs, leer,
4096/4097 eindeutige IDs und weitere Decode-Gathers. Exakte Ausgabehashes,
LRU-Reihenfolge, Hits/Misses, Eintragszahl und Prefetch-Batches stimmen überein.
Original gather_np und Original __call__ liefern dieselben192 Receipts.
Rust prüft jede Folge materialisiert-sofort, materialisiert-verzögert und über
den nicht gestagten Tabellenpfad mit lazy strided IDs (576 Vergleiche).
Ausgaben bleiben auch nach Freigabe von Mappings, Pool und Cache korrekt.
Zusätzlicher Routingtest prüft resident/plain Priorität und fehlenden Sidecar.
Keine Kernel-/Bridge-Änderung in diesem Abschnitt. Vorhandene Array/View-,
Readback- und Dequantisierungsbausteine werden wiederverwendet; Rust-Stdlib
und das vorhandene memmap2 genügen, kein neues Crate. Eintrittspunkte nehmen
bereits aufgelöste Tensor-Metadaten und Prefetch-/Cache-Einstellungen entgegen.
Safetensors-Attach, Umgebungs-/Modellpolicy, Stage-Lifecycle und vollständige
Modell-/Produktanbindung bleiben offen. Kein Vollmodell- oder IO-Performance-
Vergleich und keine2%-Abnahme; Port weiterhin cfg(test).
Verifikation: reguläre Gesamt-Port-Suite103/103 in55,27s; Unretained-Command-
Buffer-Suite103/103 in54,87s. Release-Clippy, Format-/Diff- und Quellen-Check
bestehen. Fast-Synchronisation besteht mit5/5 NGram-Tests in2,25s.
Prüfbeleg: local-eval-results/20260907-mtplx-port/ngram-sidecar-check.log.
Diese Testlaufzeiten sind keine Modell-Performancewerte.
Verbundener N-Gram-Stage-Lifecycle (2026-09-07)
ngram_stage::Embedding verbindet jetzt CPU-Hash, Sidecar, GPU-Graph und History
mit dem originalen stage/__call__-Ablauf. Die CPU-Hashkonstanten werden beim
ersten tatsächlichen Stage-Aufruf gelesen und behalten; EOS bleibt der aktuelle
Modellwert. Stage selbst schreibt die Cache-History nicht. Gespeichert werden
Shape, lazy Embedding, neue rohe History und vorherige History für QA.
Kein Sidecar, deaktivierte Stage-Option oder _stage_disabled kehren wie die
Referenz zurück, ohne eine vorhandene Vorbereitung zu löschen. Tatsächliche
Vorbereitungsfehler löschen sie und warnen nur einmal, deaktivieren spätere
Versuche jedoch nicht dauerhaft. forward verbraucht die Vorbereitung zuerst
und prüft nur B/S, nicht Tokenidentität. Passende Vorbereitung aktualisiert erst
nach erfolgreicher optionaler QA den Cache und den Consumed-Zähler. Bei stale
Shape folgen Bypassed-Zähler und normaler Graph-Fallback. Dieser zählt Graph-
Calls und schreibt die neue History vor dem Tabellenzugriff, auch wenn der
Zugriff danach fehlschlägt. Census-Ausgabe und Warnung folgen der Referenz.
Die optionale QA verwendet die originale F32-allclose-Kette mit Atol1e-8,
Rtol1e-5, NaN-false und expliziter ±Inf-Korrektur. Vorhandene Binary-/Unary-
Operatoren sind um LessEqual, LogicalAnd/Or/Not erweitert; die ursprünglichen
Kernels stammen unverändert aus der gepinnten Runtime-Metallib. Die boolesche
Gesamtreduktion übernimmt die Original-Single-/Two-Pass-Geometrie sowie die
strikte64MiB-Grenze und4-Byte-Mindestallokation. Dieser Reducer deckt den dichten
Bool-Ausgang der Stage-QA ab, nicht beliebige andere Reduktionspläne.
Der gemeinsame ops::read_i64 folgt der NumPy-Konvertierung für Integer-Arrays:
einmal auswerten, dann Strides/Byte-Offsets auf dem gemeinsam gehaltenen Speicher
lesen und auf der CPU nach I64 konvertieren. Der Sidecar nutzt denselben Helfer
nach seinem originalen Flatten; Stage fügt kein GPU-Flatten oder Cast hinzu.
136 tatsächliche Original-Lifecycle-Receipts mit realer kleiner Sidecar-Datei: raw/Q4, B1/2, 4-Token- und ausgewählte2048-Token-Prefills, jeweils Decode-Folge. Normal, QA, Graph-only, Stage-disabled, stale Shape, andere Tokens gleicher Shape, QA-Mismatch, übersprungene Vorbereitung bei deaktivierter Policy oder fehlendem Sidecar, wiederholter Vorbereitungsfehler, kein Cache, längere History, überschriebene Vorbereitung und Graphfehler sind enthalten. Ausgabe- und History-Hashes, unveränderte History nach Stage, Consumed/Bypassed/Graph-Zähler, Warnstatus, Pending-State und Fehler stimmen unmittelbar und bei verzögerter Ausgabeauswertung überein (272 Vergleiche). Zusätzliche38 Original-Receipts prüfen die QA-Sonderwerte und Reduktionsgrenzen einschließlich >64MiB.
Keine neue Metal-/Bridge-Änderung und keine neue Dependency. Policywerte werden
explizit übergeben; deren Auflösung, Safetensors-Attach, Loader und gesamte
Decoder-/Modell-/Produktanbindung bleiben offen. Der Port ist weiterhin
cfg(test). Diese Belege sind keine UI-/Vollmodell-Performanceabnahme.
Verifikation: reguläre Port-Suite105/105 in56,27s und Unretained-Command-Buffer-
Suite105/105 in56,17s; Release-Clippy, Format-/Diff- und Quellen-Check bestehen.
Die sieben NGram-Tests bestehen auch mit Fast-Synchronisation in2,60s.
Prüfbeleg: local-eval-results/20260907-mtplx-port/ngram-stage-check.log.
Testlaufzeiten sind keine Modell-Performancewerte.
Vollständiger PLE-Aufruf mit Safetensors-Ladeanbindung (2026-09-07)
ple::Ple::forward verbindet jetzt das tatsächliche NGramEmbedding mit der
Projektion, dem Gate und der dilatierten Faltung. Der äußere Stage-Prepass bleibt
außerhalb des Aufrufs. Cache-Slot3 wird durch den Lookup vor der Projektion
aktualisiert; Slot2 erst durch die Faltung. Die bisherigen numerischen
Projektionsoperatoren werden unverändert weiterverwendet.
144 tatsächliche Original-PLELayer-Receipts, ohne Ersatz-Embedding: BF16-Tabelle
und Q4-Tabelle, dichte und quantisierte Projektionen, Stage/QA/Graph/residenter
Pfad, B1/2, 7/2048 Prefill-Tokens und folgende Decode-Schritte einschließlich EOS,
kein/leerer/vorbelegter Cache. Die Referenz erzeugt kleine lokale Safetensors und
benutzt jetzt auch attach_sidecar/attach_resident; deren 144 Ergebnisse sind
unverändert zu den zuvor direkt angebundenen identischen Tabellen. Rust prüft
Ausgabe, Faltungszustand und rohe Token-History sofort und verzögert (288 Vergleiche).
Table::attach_sidecar übernimmt Metadaten-Defaults, Entfernen eines vorhandenen
Plain-Weights, Prefetch-/Hot-Cache-Konfiguration und die existierende mmap-LRU.
attach_resident materialisiert die ausgewählten Arrays vor Rückkehr, setzt bei
Erfolg prefer_lazy=false und löscht bei Fehler die residente Bindung. Stage-
Flags werden mit den originalen exakten Stringvergleichen gelesen.
Der erforderliche CPU-Load ist an den vorhandenen Graph/Scheduler/Allocator
angeschlossen: eigener Vier-Worker-Load-Pool, unabhängiger Vier-Worker-Pread-Pool,
32MiB-Batches, direkter Rest, CPU-Stream wartet auf das Load-Future. Header und
Payload werden über denselben gehaltenen Dateideskriptor gelesen. Worker halten
die Zielallokation bis zum Ende ihrer disjunkten Schreibaufträge. Die bestehende
Header-Validierung wird weiterverwendet, einschließlich ihrer Schutzgrenzen.
Zusätzlicher Loader-Test: leer/klein und unter/auf/über32MiB sowie >64MiB,
Payload erst nach Graphkonstruktion geschrieben, Datei vor Auswertung entfernt,
sofortige/asynchrone CPU→GPU-Folge, gemeinsame Allocator-Buchung und nachträglich
abgeschnittene Datei mit propagiertem Fehler. Keine großen Modellgewichte geladen.
Unveränderte Original-Metal-Quellen und Metallib; keine neue Dependency. Offen
bleiben die modellweite Residency-/Memory-Plan-Auswahl, Laden/Sanitize der übrigen
Gewichte, Decoder-/Gesamtmodell-/Produktanbindung und vollständige Messabnahme.
Der Port ist weiterhin cfg(test); diese Nachweise schließen P10 oder das
2%-Gesamtziel nicht ab. Belege: tests/fixtures/mtplx-ple-connected.jsonl und
local-eval-results/20260907-mtplx-port/ple-connected-load-check.log.
Verifikation: Port-Suite107/107 in58,72s, abschließende Unretained-Command- Buffer-Suite107/107 in59,00s; Release-Clippy, Format-/Diff- und Quellen-Check bestehen. Der bestehende Safetensors-Boundary-Test besteht ebenfalls. Die abschließenden Fast-Synchronisationschecks bestehen für PLE in2,76s und den CPU-Loader in0,14s. Die Testlaufzeiten sind keine Modell-Performancewerte.
Verbundene Attention-Matrixpfade und Softmax (2026-09-07)
P08/P09: Der gemeinsame BF16-Matmul übernimmt jetzt auch führende Batchachsen, gemeinsames Broadcasting mit zwei ausgesparten Matrixachsen, Stride-Collapse, Broadcast-Batch-in-M-Collapse und ursprüngliche Transpose-/Copy-Vorbereitung. Wide-GEMV, GEMV und NAX-GEMM erhalten die originalen Batchformen/-strides und Dispatchbedingungen; Split-K bleibt auf Batch1 begrenzt. Die vorhandenen dichten Projektionen benutzen denselben Operator. Nicht abgedeckt sind allgemeine Dot-/Vektor-/N1-/Empty-Matmul-Fälle und andere Datentypen oder Geräte.
Der Last-Axis-Softmax ist ein eigener lazy Operator mit ursprünglicher
Contiguous-Prüfung, Donation oder Stride-erhaltender Allokation, notwendiger
Kopie sowie Block-/Looped-Auswahl an der4096-Grenze. BF16/F16 verwenden bei
precise die originale präzise Spezialisierung; F32 die normale. Der Speicher-
Reuse-Test synchronisiert nur seine Eingabevorbereitung: ein GPU-Event-Wait
garantiert weder hier noch in der Referenz, dass Completion-Callbacks ihre
Data-Referenzen schon freigegeben haben. Keine zusätzliche Synchronisation im
Laufzeitoperator oder Evaluator.
attention::sdpa_fallback verbindet die originalen BF16-Q-Skalierung,
GQA-Views, QK-Matmul, Bool-/additive Maskierung, präzisen Softmax und PV-Matmul.
Bool-false setzt hier BF16-finfo.min, nicht minus unendlich. Die Routenzuordnung
stammt aus MTPLXs gepinntem fast.cpp und Metal-SDPA: Qwen hat GQA12/D256;
S3–8 überschreitet die Fused-Vector-Bedingung S*GQA<=32. Größere D256-Prefills
mit expliziter Array-Maske benutzen ebenfalls diesen Fallback. Das ist eine
Quellzuordnung, keine gemessene Ursache für die Gesamt-MTP-Geschwindigkeit.
attention::rows_gather portiert getrennt den tatsächlichen MTPLX-Aufruf
_qsa_rows_gather_attention: zwei per-row Gathers über Cache-Achse2, gruppierte
Views ohne zwölfmaliges Materialisieren von K/V, BF16-QK vor F32-Cast und
Skalierung, minus-unendlich-Maskierung, F32-Softmax, BF16-Probabilities und PV.
Hier wäre ein Aufruf des obigen SDPA-Fallbacks numerisch und funktional falsch.
Der bereits vorhandene Tabellen-Gather wurde zum gemeinsamen Original-take
mit Gather/Transpose/Squeeze erweitert; NGram benutzt weiterhin dessen Achse0.
14 zusätzliche I32/BF16-Instanziierungen aus unverändertem Gather-Körper und
originalem JIT-Wrapper sind exportiert. Keine neue algorithmische Kernelversion,
Bridge oder Dependency; die ursprüngliche Runtime-Metallib bleibt unverändert.
Tatsächliche Original-Receipts (keine Performance-Mikrobenchmarks):
- 34 Batch-Matmul-Fälle, jeweils sofort/lazy:68 exakte Vergleiche. GQA-QK/PV, B1/2, S1/3/8/16/64/2048, Cache-Strides, Transposes, Cross-Broadcast, Batch-Collapse, nicht ausgerichtete Offsets und erforderliche Kopien.
- 48 Softmax-Fälle, jeweils mit/ohne gehaltene Eingabe:96 exakte Vergleiche.
BF16/F16/F32,
preciseaus/an,17/4097 Spalten, plain/swapped/strided/offset; außerdem Stride- und kontrollierte Donation-Prüfung. - 21 tatsächliche
mx.fast.scaled_dot_product_attention-Aufrufe, sofort/lazy: 42 exakte Vergleiche. GQA12 oder gleiche Headzahl, bis2048 Prefillzeilen, Cache-Backing-Offsets, keine/Bool/additive Maske, vollständig maskierte Zeile. - 18 tatsächliche MTPLX-Rows-Gather-Aufrufe, sofort/lazy:36 exakte Vergleiche. S1/3/8/16/64,8/17/1025/4097 gewählte Tokens, GQA12 oder gleiche Headzahl, volle/versetzte/strided Cacheansichten; zwei originale Gathers und ein F32-Softmax werden im Dispatch nachgewiesen.
Weiter offen: Full-SDPA-Auswahl und Bindung, vollständiges Attention-Modul mit
Projektionen/RoPE/Cache/Selektor, Decoder/Gesamtmodell und Produktionsumstellung.
Diese Operatoren bleiben cfg(test); P08/P09/P16 und das2%-Ziel sind nicht
abgeschlossen. Belege: tests/fixtures/mtplx-{dense-batch,softmax-graph, sdpa-fallback,qsa-rows-attention}.jsonl und
local-eval-results/20260907-mtplx-port/attention-graphs-check.log.
Verifikation: reguläre Port-Suite111/111 in61,32s, Unretained-Command-Buffer- Suite111/111 in61,78s; die zwei verbundenen Attention-Tests bestehen zusätzlich mit Fast-Synchronisation in0,96s. Release-Clippy, Format-/Diff- und Quellen- Check bestehen. Diese Testlaufzeiten sind keine Modell-Performancewerte.
Gekachelter portabler Prefill-Gather (2026-09-07)
attention::prefill_gather verbindet nun auch MTPLXs tatsächlichen
_qsa_prefill_gather_attention-Ablauf: pro Kachel absolute I32-Positionen,
Integer-Divide, vollständige ausgewählte Blöcke, kausaler Tail, Bool-Repeat,
Concatenate und sichere Nullindizes für ungültige Slots; danach der oben
geprüfte Rows-Gather auf den vollen KV-Backings. Keine Vollkontext-Kopie.
Das unbenutzte Python-Argument total_tokens benötigt keinen Rust-Operand;
die Auswahl adressiert wie im Original ausschließlich die übergebenen Backings.
Jede Kachel wird vor der nächsten ausgewertet. Bei nur einer Kachel ist das Ergebnis schon ausgewertet; sonst bleibt ausschließlich die abschließende Concatenate-Operation lazy. Die Python-Lokalen werden auch in Rust über die Auswertung hinweg gehalten und erst in Referenzreihenfolge beim nächsten Schleifendurchlauf ersetzt. Zusätzliche Schattenbindungen kurzlebiger Ausdrücke und vorzeitig bewegte Concatenate-Eingaben wurden vermieden, weil sie Donation und Data-Lebensdauer trotz passender Ausgabehashes verändern würden.
Die vorhandenen Arange- und Binary-Operatoren übernehmen Startwerte und
Integer-Floor-Divide: Letzteres verwendet wie ops.cpp den vorhandenen Divide-
Kernel ohne True-Divide-Promotion nach F32. Keine neue Metal-/Bridge- oder
Dependency-Änderung. Die restliche SDPA-/Attention-/Produktanbindung bleibt offen.
34 tatsächliche MTPLX-Receipts, jeweils mit lazy bzw. vorher ausgewerteten
Eingaben (68 Vergleiche): GQA12/gleiche Headzahl, S1/7/17/2048,
Kompressionsratio1/4/128, Position0/3/127/511, Kachelgrößen1/4/64/2048,
dichte I32- und versetzte/strided I64-Blockauswahl, ungültige negative IDs.
Der Referenzgenerator protokolliert die tatsächlichen mx.eval-Aufrufe samt
Tile-Shapes. Rust prüft deren Reihenfolge/Form im ausgewerteten Ausgabegraph,
zwei Gathers und einen F32-Softmax je Kachel sowie das exakte Ausgabehash.
Belege: tests/fixtures/mtplx-qsa-prefill-gather.jsonl und
local-eval-results/20260907-mtplx-port/prefill-gather-check.log.
Das ist weiterhin ein cfg(test)-Portnachweis, keine P08-/P16-Gesamtabnahme.
Verifikation: reguläre Port-Suite112/112 in62,24s, Unretained-Command-Buffer- Suite112/112 in62,50s; alle drei Attention-Tests mit Fast-Synchronisation in1,37s. Release-Clippy, Format-/Diff- und Quellen-Check bestehen; ursprüngliche Metallib unverändert. Die Testlaufzeiten sind keine Modell-Performancewerte.
Fused-Vector-SDPA und typisierte Metal-Konstanten (2026-09-07)
Der BF16/D256-Vector-SDPA ist jetzt als eigene Primitive verbunden. Die
gemeinsame attention::scaled_dot_product-Auswahl verwendet bei Qwens normalen
Aufrufen ohne bzw. mit expliziter Array-Maske den originalen Vector-Pfad für
S<=8, S<=T und S*GQA<=32; sonst den bereits geprüften D256-Fallback.
Der direkte Vector-Aufruf unterstützt zusätzlich die kausale Maske; bei S1
bleibt ihr Kernel-Flag wie im Original ausgeschaltet.
Die Bindung übernimmt Q-/KV-/Masken-Kopierbedingungen, Query-Donation, Allokationsreihenfolge, Offset-/Stride-Bindings, Bool-/additive Maske und Ein-/Zwei-Pass-Auswahl. Zwischenpuffer werden wie in der Referenz als Encoder-Temporaries gehalten. Die drei unveränderten Originalkerne kommen direkt aus derselben gepinnten Runtime-Metallib.
Live korrigierte Hardwarezuordnung: mx.device_info meldet für diesen
Apple M5 Max applegpu_g17s (Max), nicht ...d (Ultra). Beim ersten Zwei-Pass-
Vergleich führte die falsche Zuordnung zu einem abweichenden Ausgabehash.
Für GQA12 ergibt die tatsächliche Max-Policy64 Blöcke bei T1024,128 bis8192,
256 bis32768,512 bis65536, danach1024; nicht die Ultra-Grenzen. Die Auswahl
verwendet jetzt den bereits vorhandenen Architektur-Bridge-Helfer gemeinsam
mit dem Scheduler und dem MLX_METAL_GPU_ARCH-Override. Alle originalen
Architekturzweige und MLX_SDPA_BLOCKS mit atoi-Semantik/32er-Aufrundung
sind abgebildet. Die zuvor falsche Annahme ist kein Modell-Performancebefund.
Der gemeinsame Bridge-Konstantentyp unterstützt jetzt Bool und echtes I32 statt ausschließlich Bool. Der Pipeline-Cache-Schlüssel enthält auch den Typ; ungültige Typen, Bool-Werte und doppelte Indizes werden weiterhin verworfen. Alle alten Bool-Aufrufe sind auf denselben neuen ABI-Typ umgestellt. Keine neue parallele Dispatch-Bridge und keine Änderung der Kernelkörper.
48 tatsächliche Referenzfälle, jeweils lazy/vorbereitet (96 exakte Vergleiche):
B1/2, GQA12, S1/2, T17/33/1023/1024/16384/65536, transponierte Query bzw.
Copy-erforderliche Strides, versetzte KV-Backings, keine/Bool/additive/kausale
Maske. Der Dispatch prüft die tatsächlich erwartete Ein-/Zwei-Pass-Folge;
wechselnde Blockzahlen prüfen auch die Integer-Konstante und Cachetrennung.
Belege: tests/fixtures/mtplx-sdpa-vector.jsonl und
local-eval-results/20260907-mtplx-port/vector-sdpa-check.log.
Offen bleiben Full-SDPA einschließlich NAX-D256-Causal-Split, Sinks/andere
Datentypen und Head-Dimensionen außerhalb des installierten Qwen-Aufrufs,
vollständiges Attention-/Modulrouting, Modell-/Produktanbindung und P16.
Der kanonische Port bleibt cfg(test); keine Vollmodell-Performanceabnahme.
Verifikation: reguläre Port-Suite113/113 in64,07s, Unretained-Command-Buffer- Suite113/113 in63,75s; Fused-SDPA-Fast-Synchronisationscheck in1,25s. Release-Clippy, Format-/Diff- und Quellen-Check bestehen; ursprüngliche Metallib unverändert. Die Testlaufzeiten sind keine Modell-Performancewerte.
Originale RoPE-Graphen und KV-Cache-Objektsemantik (2026-09-07)
rope.rs bildet _rope_inv_freq_and_scaling, _rope_cos_sin,
_build_mrope_axes, _mrope_cos_sin und _apply_partial_rope als gewöhnliche
Graphknoten ab. F32-Arange, Power, Sin/Cos und Typgrenzen verwenden dieselben
Runtime-Kerne, keine CPU-Frequenztabelle und keinen Ersatz-RoPE-Kernel.
Host-F64 bleibt auf die originalen Python-math-Schritte von statischem YaRN
beschränkt. Der Modell-Konfigurationsparser wird dadurch noch nicht ersetzt.
48 tatsächliche MTPLX-Referenzfälle, jeweils lazy/vorbereitet:96 exakte Vergleiche
für Frequenzen, Cosinus, Sinus und rotierte BF16-Ausgabe. Enthalten sind Rotary64
und256, partielle/vollständige Rotation, S1/7/64/2048, Positionen bis1048576,
Default/static YaRN einschließlich Amplituden-/mscale-Verhältnis und ungekürzter
Rampe sowie gleiche, interleaved und abschnittsweise M-RoPE-Achsen. Geslicte
Eingaben bleiben geslict. Die Referenz-Funktionen, nicht eine nachgebaute
Python-Formel, erzeugen tests/fixtures/mtplx-rope-graph.jsonl.
cache.rs portiert den von QSACache benutzten gewöhnlichen KVCache:
256er-Wachstum, Teilkapazitäts-Slice vor Wachstum, Full/Concatenate/SliceUpdate,
Trim und State-Roundtrip. ops::slice und slice_update teilen die ursprüngliche
Indexnormalisierung; Full und SliceUpdate verwenden die gemeinsamen Copy-Kerne
mit den originalen Scalar/Vector/General-/Donation-Regeln. GeneralGeneral-Copy
verwendet bei Ausschnitten weiterhin die Datengröße des vollständigen
Ziel-Arrays für Large-Dispatch und Encoder-Abhängigkeiten.
Tatsächlich gefundene Besitzabweichung: Eine reine Array::clone-Übernahme
bildete Python-Aliase auf cache.keys/values nicht ab. mlx_set_item überschreibt
den Descriptor des bestehenden Python-Arrayobjekts; gehaltene Python-Objektaliase
folgen dieser Änderung, bereits gebaute Graphknoten behalten dagegen ihren
ursprünglichen Descriptor. Der Rust-Cache trennt deshalb Rc<RefCell<Array>>
auf der Modellobjekt-Ebene von den unveränderten Array-Deskriptoren im Graphen.
Wachstum ersetzt das Objekt, SliceUpdate ersetzt nur seinen Descriptor. Das
ist weder eine zusätzliche GPU-Kopie noch ein geänderter Shader.
Die12 unveränderten tatsächlichen KVCache-Referenzfälle bestehen danach exakt: Startlängen0/1/255/256/257/2048, mehrere Updates, Trim/Overwrite, Wiederherstellung eines gehaltenen Zustands, vollständiger Trim und Wiederaufnahme; jeweils sofortige bzw. verzögerte Auswertung. Geprüft werden sowohl logische Zustände als auch vollständige Backings und Kapazitäten. Beim vollflächigen Ersatz kann ein transponiertes Eingabelayout erhalten bleiben; der reine Test-Readback wurde deshalb wie NumPy in logischer C-Reihenfolge exportiert. Die Referenzhashes wurden nicht angepasst. Zusätzliche SliceUpdate-Prüfungen decken negative Strides, leere Updates, Broadcast/Typkonversion und tatsächliche Donation ab.
Nur12 weitere originale F32/I32-Gather-Instanziierungen für M-RoPE;15 Custom- Kernelkörper,35 Custom-Einstiege und22 Runtime-Quellblöcke sind weiterhin unverändert zur Referenz. Der Export enthält jetzt170 Runtime-Einstiege; die originale Runtime-Metallib bleibt bytegleich.
P08 bleibt offen: vollständiger Attention-Aufruf mit QKV-/Indexer-Fusion,
QSA-Arraygraph und dessen veränderlichen Cacheobjekten, sämtliche Auswahlzweige
und das nachfolgende Modellrouting sind noch nicht verbunden. Insbesondere
darf der bisherige Buffer-/Rc-Pfad die hier aufgedeckte
Objekt-/Descriptor-Unterscheidung bei der Integration nicht verlieren.
Modell-/Produktanbindung und P16 sind weiterhin offen; der Port bleibt
cfg(test). Keine Modell-Performance- oder Responsiveness-Abnahme aus diesen
Fixtures. Belege: tests/fixtures/mtplx-kv-cache-graph.jsonl und
local-eval-results/20260907-mtplx-port/rope-cache-check.log.
Verifikation: Port-Suite115/115 in64,78s, Unretained-Suite115/115 in64,77s; zusätzliche Fast-Synchronisationschecks: RoPE1/1 in0,49s und KVCache1/1 in0,29s. Release-Clippy, Format-/Diff- und Quellenprüfung bestehen. Die Laufzeiten bezeichnen Modell-freie Prüfungen, keine Inferenz-Performance.
Direkte Sparse-Attention-Consumer im Arraygraph (2026-09-07)
sparse_attention.rs bindet jetzt die unveränderten MTPLX-Körper
qsa_flash_skip.py::_SRC und qsa_prefill_flash.py::_SOURCE als jeweils eine
CustomKernel-Primitive ein. Decode übernimmt die originalen Flatten-Aufrufe,
Host-Parameter, GQA-Spezialisierung und256 Threads; Prefill verwendet32 Threads
pro (Query-Zeile, KV-Head) und die originalen Metal-4-MPP-Matmulfragmente.
Es gibt weder ein Gather-/Dense-Ersatzverfahren innerhalb dieser Primitive
noch einen stillen Retry nach einem Dispatchfehler.
Der Prefill-Aufruf übernimmt die statischen Unterstützungsbedingungen:
macOS>=26.2 und GPU-Generation17 (Telefonklasse18), aktiver GPU-Stream,
B1/H24/KV2/D256, BF16/F16, I32-/Bool-Selektionen[S,512], S>1, exakter Suffix,
Kapazitätsgrenze, maximal1048576 Tokens, mehr als512 vollständige Blöcke und
Host-Scale exakt0.0625. Die Plattformantwort ist wie _mlx_nax_available
gecached; die Bridge liefert nur Betriebssystem-/Gerätedaten, Rust entscheidet.
Die Scale-Prüfung erfolgt auf Host-F64, vor der originalen F32-Kernelkonversion.
Ausgabeallokation, Input-Bindings und Lebensdauer folgen CustomKernel:
Decode verwendet den vorhandenen gdn::custom_evaluate einschließlich
General-Copies nicht zeilenkontiguierlicher Argumente und Encoder-Temporaries.
Prefill übernimmt ensure_row_contiguous=False und bindet alle fünf
Input-Stridetabellen sowie Byte-Offsets direkt. Die kanonischen Tests prüfen
bei vorab ausgewerteten Eingaben ausdrücklich genau einen Prefill-Dispatch,
auch bei geslicten Features und Selektionstabellen; keine versteckte KV-Kopie.
50 tatsächliche MTPLX-Fälle, jeweils lazy/vorbereitet:100 exakte Vergleiche.
Decode: GQA12/1, nur Tail bzw.512/17 ausgewählte Blöcke, T3/4099/2052.
Prefill: S2/8/137/2048, Start2050/8191/32767/2048; BF16/F16, transponierte
Query, ungerader Elementoffset, nichtkontiguierliche Features, Selektion mit
Strides, ungültige IDs und Gültigkeitslücken bis Slot511. Die Referenz ruft
die beiden tatsächlichen Sparse-Kerne direkt auf, keine nachgebaute Formel.
Belege: tests/fixtures/mtplx-sparse-attention.jsonl und
local-eval-results/20260907-mtplx-port/sparse-attention-check.log.
Der Quellenexport umfasst nun17 unveränderte Kernelkörper und41 Custom- Einstiege;22 Runtime-Quellblöcke/170 Runtime-Einstiege und die originale Runtime-Metallib bleiben unverändert. Die zusätzlichen instanziierten Decode-Varianten sind BF16/F16 mit GQA1/12; andere GQA-/Dtype-Spezialisierungen sind damit nicht als abgedeckt behauptet.
P08 ist weiterhin offen: Der vollständige Attention-Aufruf muss QKV-/Indexer-
Fusion, Norm/RoPE, KV-Update, Vision-Bypass und alle originalen Auswahlzweige
zusammenführen. Besonders die requestbezogene Prefill-Phase und die
32K-Crossover-Policy dürfen nicht durch bloßes prefill_supported ersetzt
werden. Der kanonische QSA-Indexer-/Cachegraph, Modell- und Produktanbindung
sowie P16 fehlen weiterhin. Keine Vollmodell-Performance-Abnahme aus diesen
Tests und kein produktiver Verhaltenswechsel.
Verifikation: gemeinsamer Release-Lauf116/116 in64,16s vor der abschließenden Plattform-Cache-/Host-F64-Präzisierung. Auf dem finalen Code besteht der gesamte Unretained-Lauf116/116 in65,21s; der fokussierte Normal- und FastSync-Lauf jeweils1/1 in1,75s. Release-Test-Clippy, Format-/Diff- und Quellenprüfung bestehen. Diese Zeiten sind Prüfzeiten ohne Modell, keine Performance-Abnahme.
Vollständige QSA-Blockmaskenrekonstruktion (2026-09-07)
attention::blocks_to_dense_mask übernimmt den tatsächlichen
_qsa_blocks_to_dense_mask-Graph: zeilenweise vollständige Blöcke, originale
I32-Vergleiche/Bool-Bitoperationen, ungültige IDs auf eine zusätzliche
Sentinel-Spalte, put_along_axis, Sentinel-Slice, Repeat, optionale Null-Padding-
Spalten, Tail und abschließende Kausalmaske. Dies ist der originale Consumer-
Fallback, kein Ersatz für den zuvor portierten direkten Flash-Prefill-Zweig.
Die gemeinsame ScatterAxis-Primitive übernimmt Cast/Squeeze/Broadcast-Reihenfolge, Scalar-/Vector-/General-Quellkopie, Vector-Donation, leere Updates, Achsen- und Stride-Bindings sowie die originale Dispatch-Geometrie. Bool/I64-QSA verwendet jetzt alle vier Update-/Index-Layoutkombinationen und Int-/Int64-Adressierung des unveränderten Runtime-Kernels:22 unveränderte Runtime-Quellblöcke und176 Runtime-Einstiege;17 Custom-Körper und41 Custom-Einstiege bleiben unverändert. Keine selbstgeschriebene Scatter-/Masken-Metal-Implementierung.
44 direkte MTPLX-Maskenfälle und64 direkte put_along_axis-Fälle werden lazy
und vorab ausgewertet verglichen:216 exakte F32-Readback-Hashes. Masken decken
S0/1/2/5/8/9/137/2048, Kontext bis32904, Ratio1/4/7, leere Selektionen,
gültige/ungültige/duplizierte IDs, vollständig gesperrte Blöcke und geslicte
Selektionstabellen ab. Scatter prüft Rank1/2/3, Achsen0/1, skalare/vollständige
Updates, negative Indizes und skalare/Offset-/Strided-Quellen. Zusätzlich:
führende Singleton-Updates, Achsenfehler, leere Updates und nachgewiesene
Vector-Donation ohne zusätzlichen Kopierdispatch.
Belege: tests/fixtures/mtplx-qsa-dense-mask.jsonl,
tests/fixtures/mtplx-scatter-axis.jsonl und
local-eval-results/20260907-mtplx-port/qsa-mask-scatter-check.log.
Gemeinsame Release-Verifikation:118/118 normal in68,82s und118/118 mit
unretained Command Buffers in68,04s. Release-Test-Clippy, Format-/Diff- und
Quellenprüfung bestehen. Das sind modellfreie Prüfzeiten, keine Inferenzdaten.
P08 bleibt bis zum vollständigen
QSA-Indexer-/QSACache-/Attention-Aufruf und der Produktintegration offen.
Keine Modellmessung, kein Abweichen vom vollständigen Port wegen Laufzeiten.
Positionaler QSACache im kanonischen Arraygraph (2026-09-07)
cache::QsaCache verwendet den bereits portierten KVCache und dessen
ArrayObject-Semantik. Raw-/Pooled-Schreibbereiche liegen an absoluten
Positionen; Vergrößerung erfolgt geometrisch mit256er-Ausrichtung, nicht
durch Anhängen oder Vollkopien je Dekodeschritt. Originale Full/SliceUpdate/
AsType-/Transpose-/View-Primitiven bilden die Mutationen ab; keine neue
Puffer-COW-Implementierung neben dem Arraygraph.
Der FP32-Spiegel wird beim ersten Zugriff aus dem vollständigen vorhandenen
Pooled-Inhalt aufgebaut, bei Schreibzugriffen inkrementell aktualisiert und
nach Session-Restore verworfen. Eine Reservierung vergrößert in MTPLX den
Spiegel ausdrücklich nicht sofort; diese Reihenfolge bleibt erhalten.
Die originale nbytes-Eigenschaft zählt KV/Raw/Pooled, aber nicht den
abgeleiteten Spiegel. Dies wird unverändert übernommen, nicht als Messung
des gesamten realen GPU-Speicherverbrauchs ausgegeben.
QSAIndexer::_ensure_compiled_backings ist mit dem Cache verbunden: Originale
Zweierpotenz-Buckets, ausstehende Reservierungen und der physisch notwendige
ceil(S/ratio)-Pooling-Bereich werden vor der Graphausführung berücksichtigt.
Session-Restore behält die vier Arrayobjekte, setzt Reservierungen auf die
restaurierten Ausdehnungen zurück und rekonstruiert den Spiegel erst bei Bedarf.
16 direkt ausgeführte MTPLX-Lifecycle-Sequenzen prüfen1896 exakte Tensor-Hashes
sowie Offsets, Kapazitäten, Reservierungen und nbytes nach jedem Schritt:
BF16/F16/F32, Ratio1/4/7, Indexbreite17/32/128, Initiallängen0/1/255/256/257/1025,
sofortige/verzögerte Auswertung, gehaltene Arrayobjekte und geslicte Zustände,
Rollback, Überschreiben, Restore, Mirror-Views und1025-Token-Replay-Reservierung.
Belege: tests/fixtures/mtplx-qsa-cache-graph.jsonl und
local-eval-results/20260907-mtplx-port/qsa-cache-graph-check.log.
Die erste gebündelte Referenzausgabe war abgeschnitten und enthielt dadurch eine syntaktisch gültige, aber vermischte Zeile. Alle aus abgeschnittenen Ausgaben übernommenen Zeilen wurden verworfen und einzeln aus unveränderten Originalaufrufen neu erfasst. Keine Anpassung von Implementierung oder Referenzhashes an einen fehlgeschlagenen Vergleich.
Verifikation:119/119 gemeinsame Release-Tests normal in67,06s und119/119 unretained in67,38s; fokussierter FastSync-Lauf1/1 in1,00s. Release-Test-Clippy, Format-/Diff- und unveränderte Quellenprüfung bestehen. Das sind modellfreie Prüfzeiten, keine Inferenz-Performance-Werte.
P08 bleibt offen: Die vollständige kanonische Indexer-Ausführung inklusive
kompiliertem Graphbank-Pfad und das Attention-Modul müssen diese Cache-Objekte
noch nutzen. Der Port bleibt cfg(test); keine Produkt-/Performance-Parität.
Parametrisierte QSA-Query-/Pooling-Primitiven (2026-09-07)
qsa_prepare.rs übernimmt die öffentlichen Query-/Pooling-Aufrufe aus
qsa_indexer_prepare.py einschließlich statischer Eignungsprüfung,
BF16/F16/F32, Kopfbreiten bis128, geradem partiellem/vollem RoPE, beliebigem
positivem Pooling-Verhältnis, RMS-Epsilon und positiver endlicher
Attention-Skalierung. Host-I32-Positionen werden zu einer Array-Konstante;
Tensor-Positionen werden nur auf ein I32-Element validiert und umgeformt,
ohne .item() oder Synchronisation.
Die Spezialisierung verwendet die bereits hashgeprüften Originalkörper
_prepare_queries_kernel und _pool_keys_kernel aus dem vorhandenen Export.
Nur Header-Konstanten, Datentyp-Instanziierung und Exportname ändern sich;
die Arithmetik bleibt bytegleich. Der vorhandene native CustomKernel-Compiler
verwendet Safe-Math und die originale Sprachversion. Der Pipeline-Schlüssel
enthält auch EPS-/Skalierungsbits, damit unterschiedliche Konfigurationen
nicht versehentlich dieselbe Kompilierung verwenden.
Originale Ausgabeallokation vor Kompilierung, vier Array-Inputs, drei
Stride-Tabellen, Byte-Offsets und Datenlebensdauer bleiben erhalten.
ensure_row_contiguous=False: keine impliziten General-Copies. Query verwendet
32 Threads je Zeile/Kopf, Pooling32 je Block; kein Fehler-Retry auf Eager.
72 direkte MTPLX-Fälle mit je zwei Ausgaben werden lazy/vorbereitet geprüft:
288 exakte Tensorvergleiche. S1/3/7/137/2048, H1/2/3/4/7, D2/17/64/128,
RoPE2/16/32/64/128, Ratio1/3/4/7/8, negative und große Positionen,
Plain-/Offset-/Strided-/Broadcast-Inputs, dynamische GPU-Positionen sowie
unterschiedliche EPS bei sonst gleichen Parametern. Vorbereitete Inputs
erzeugen genau zwei Dispatches; die dynamischen Kernelkörper werden zusätzlich
byteweise mit den geprüften Exportkörpern verglichen.
Belege: tests/fixtures/mtplx-qsa-prepare-graph.jsonl und
local-eval-results/20260907-mtplx-port/qsa-prepare-graph-check.log.
Verifikation:120/120 gemeinsame Release-Tests normal in67,95s und120/120
unretained in68,37s; fokussierter FastSync-Lauf1/1 in0,82s. Release-Test-Clippy,
Format-/Diff- und Quellenprüfung bestehen. Das sind modellfreie Prüfzeiten,
keine Inferenz-Performance-Werte.
P08 bleibt offen: Diese Primitiven müssen mit dem vollständigen kanonischen
QSAIndexer einschließlich Eager-Orakel und kompiliertem Graphbank-Pfad sowie
mit Attention/Modell/Produktausführung verbunden werden. Weiterhin cfg(test);
keine Vollmodellmessung oder Rücknahme aufgrund isolierter Laufzeiten.
Gemeinsame Float-Summen und QSA-Mittelwert (2026-09-07)
reduce.rs übernimmt für BF16/F16/F32 die gemeinsame Sum-Factory und den
Reduktionsplan aus ops.cpp, backend/common/reduce.cpp und
backend/metal/reduce.cpp der gepinnten MTPLX-Laufzeit. Keine neuen Metal-
Körper: sämtliche Reduktionskernel stammen aus der unveränderten originalen
Metallib. Die drei bisherigen speziellen GDN-/PLE-/HC-Summen wurden entfernt;
ihre kanonischen Modellgraphen verwenden jetzt dieselbe Sum-Operation.
Enthalten sind sortierte/validierte Achsen, keepdims/Squeeze, No-op-Achsen,
leere Reduktionen mit dem originalen Init-Kernel, zusammengefasste reduzierte
Achsen, Stride-Sortierung, General-Copy nur beim originalen GeneralReduce-Plan,
Row-Small/Simple/Looped sowie Col-Small/Looped/LongColumn/TwoPass und AllReduce
mit originalen Schwellen, Zwischenpuffern, Argumentlayouts und Threadgeometrien.
Shape-Collapse und zweidimensionale Grid-Faktorisierung werden mit den bereits
portierten Views geteilt. Der Runtime-Identitätszweig bewahrt beim Vector-Copy
auch kompakte Broadcast-Speicherung; er darf daraus keinen Full-Fill machen.
mean_f32 bildet genau den im QSA-Eager-Pooling benötigten Ausdruck ab:
expliziter F32-Input, Sum und anschließendes Multiply mit einem aus Host-F64
auf F32 gerundeten Kehrwert. Kein Divide, eigener Mittelwertkernel oder
Zusammenziehen mehrerer Primitiven. Dies ist kein vollständiger allgemeiner
Mean-/Integer-Reduce-/Shapeless-Compiler-Port.
232 tatsächliche MTPLX-Referenzfälle werden lazy und mit vorbereiteten Eingaben geprüft:928 bitgleiche Tensorvergleiche für Sum und F32-Mean. Enthalten sind alle neun Kernelfamilien, ein-/mehrdimensionale Reduktionen, zwei und fünf Kernel-Reduktionsdimensionen, Plain-/Offset-/Transpose-/Strided-/Reverse-/ Broadcast-Layouts, No-ops und leere Achsen. Grenzfälle decken insbesondere 31/32 Outputzeilen, Breiten512/513/1024/1025, Spaltenlängen31/32/256/257/ 1023/1024/32768 sowie AllReduce4096/4097 und die64-MiB-Schwelle ab. Zusätzlich werden konkrete Kernelnamen, Dispatch-/Threadgroup-Geometrien und Threads-vs-Threadgroups an14 ausgewählten Grenzen geprüft. Ein separater Runtime-Identitätscheck prüft physische Broadcast-Datengröße und Strides.
Belege: tests/fixtures/mtplx-sum-graph.jsonl (SHA256
d0963276ff75305d7903b91cb34f8d0db2472330fba444199f70dfd7fbebcdd1)
und local-eval-results/20260907-mtplx-port/sum-graph-check.log.
Gemeinsame Release-Suite:121/121 normal in69,63s und121/121 unretained in71,85s.
Nach der abschließenden Korrektur des Runtime-Identitätszweigs bestehen auch
die fokussierten Checks normal in2,39s, unretained in2,27s und FastSync in2,32s,
jeweils1/1 einschließlich aller928 Tensorvergleiche und Dispatch-Verträge.
Die vollständigen Suites liefen vor dieser letzten Identitätskorrektur.
Release-Test-Clippy, Format-/Diff- und unveränderte Quellenprüfung bestehen.
Prüfzeiten sind keine Modell-Performance-Werte.
P08 bleibt offen: insbesondere Sort/Argpartition für den Eager-Indexer,
dessen vollständige Auswahl-/Cache-/Graphbank-Kette,
Attention und produktive Modellintegration. Der Port bleibt cfg(test).
Keine Aussage zur UI-Responsivität oder erreichten Performance-Parität;
keine Rücknahme aufgrund isolierter Laufzeiten.
Kanonischer Float-Matmul und verbundener QSA-Score-Pfad (2026-09-07)
dense.rs verwendet jetzt eine gemeinsame Matmul-Factory für BF16/F16/F32,
Typ-Promotion, Vektoren, Matrix-/Vektorprodukte, Broadcast-Batches, statisches
Flatten/Unflatten und leere Matrizen. nn.Linear delegiert direkt an diese
Factory; seine duplizierten Expand-/Reshape-/Squeeze-Pfade wurden entfernt.
Alle bisherigen Attention- und HC-Aufrufer verwenden dieselbe Operation.
Der Metal-Backendport für den M5 Max übernimmt aus dem gepinnten
backend/metal/matmul.cpp beide GEMV-Richtungen, DotProduct mit F32-Partials,
originalem AllReduce und Scalar-Copy, F16/BF16-GEMV-Wide (ausdrücklich nicht für
F32), NAX/SIMD-Split-K und reguläre NAX-/SIMD-GEMM-Auswahl. Kernel, Partitions-
größen, Schwellen, Strides, Byte-Offsets, Zwischenpuffer, Function Constants
und Dispatch-Geometrien stammen aus dieser Referenz. Keine neuen Metal-Körper.
MLX_ENABLE_TF32 wird wie env::enable_tf32 einmal mit atoi gelesen, Default1;
TF32-off wählt die originalen SIMD-F32-Kernel, Vektoren bleiben bei GEMV.
Dies erweitert den M5-Max-Port, nicht Complex-Matmul oder den Shapeless-Compiler.
attention::qsa_scores verbindet den ursprünglichen Ausdruck aus
qsa_indexer_prefill_scores/QSAIndexer._select_eager: F32-Query-Cast bei
bereits F32-Poolingoperand gemäß Originalvertrag, Matmul, ReLU je Kopf, Sum über Achse2,
Division durch Host-F64-sqrt(D), auf F32 gerundet, und Auswahl von Batch0.
Der zuvor portierte gemeinsame Reduktionspfad wird direkt verwendet.
228 zusätzliche Original-Matmul-Fälle sind mit TF32 on/off erfasst: BF16/F16/F32, gemischte Eingabetypen, alle vier Transponierungsrichtungen, Dot-/linke/rechte Vektoren, Kreuz-Broadcasts, Copy-/Offset-/Collapse-/Flatten- Layouts, ungerade K, Split-K-Grenzen und leere Matrizen. Lazy/vorbereitete Ausführung ergibt456 bitgenaue Tensorvergleiche über beide TF32-Prozesse. Zusätzlich bestehen384 vorhandene direkte MTPLX-QSA-Score-Receipts jetzt auch durch den kanonischen Arraygraph, einschließlich S2048, N1/7/16/32/40/63/64/ 128/129/513 und acht Speicherlayouts. Zusammen840 neue Matrix-/Score- Vergleiche; die bisherigen68 BF16-Attention-Vergleiche bleiben erhalten. Konkrete F32-Kernelnamen und Threadgeometrien für GEMV, beide Split-K-Varianten und gebatchte reguläre GEMM werden zusätzlich geprüft.
Beim Erfassen der Referenz stürzte numpy.asarray auf einem leeren F32-
Matmul-Ergebnis ab. Ein unabhängiger Minimalaufruf bestätigt: mx.eval
schließt ab; erst das Auslesen der Null-Datenadresse stürzt ab. Der gemeinsame
Fixture-Emitter hasht daher bei size==0 die leere Bytefolge nach erfolgreichem
Eval, ohne NumPy-Lesen. Keine Änderung an Referenzmodell/-runtime, Berechnung
oder nichtleeren Hashes. Die abgebrochene F32-Capture-Gruppe wurde vollständig
neu erfasst. Form und Abschluss leerer Ergebnisse bleiben geprüft.
Belege: tests/fixtures/mtplx-dense-float.jsonl (SHA256
24ac569b5fe6f4dc6757cb21870bc3d9ae0fd2c7eff690240284b61d0ce76037),
vorhandene qsa_f32_score_*-Receipts und
local-eval-results/20260907-mtplx-port/dense-float-graph-check.log.
Verifikation des finalen Standes:123/123 gemeinsame Release-Tests mit
Default-TF32 in72,44s;123/123 mit MLX_ENABLE_TF32=0 und unretained Command
Buffers in72,34s; fokussierte Matrix-/QSA-Gruppe3/3 mit TF32 und FastSync
in2,00s. Release-Test-Clippy, Format-/Diff- und unveränderte Quellenprüfung
bestehen. Diese Prüfzeiten sind keine Inferenz-Geschwindigkeitswerte.
P08 blieb an diesem Messstand offen: kanonisches Sort/Argpartition, fehlende Indexier-Dtypes,
vollständige Indexer-Auswahl/Cache-/Compiled-Graphbank und Attention-Aufruf.
Auch Modell-/Produktausführung und abschließende Performance-Abnahme bleiben
offen. Der Port ist weiterhin cfg(test); kein Vollmodell-Speed oder UI-
Responsiveness-Nachweis wird aus diesen modellfreien Prüfungen abgeleitet.
Gemeinsames kanonisches Sort/Argpartition (2026-09-07)
sort.rs portiert die vier ursprünglichen Factories Sort, ArgSort, Partition
und ArgPartition und deren gemeinsamen Metal-Merge-Sort. Partition bleibt wie
in der Referenz ein vollständiger Sort; kth wird normalisiert, geprüft und
im Graph-Primitiv erhalten. Negative Achsen, Flatten bei fehlender Achse,
BF16/F16/F32/I32/U32/I64/U64, Layout-/Offset-Auswertung, der originale
Contiguous-/Noncontiguous-Dispatch, Blockgrößengrenzen einschließlich der
64-Bit-Ausnahme, Ping-Pong-Partition/Merge und abschließende Vector-/General-
Kopie verwenden den ursprünglichen Ablauf und unveränderte Metallib-Kernel.
Die Kopie benutzt die vorhandenen gemeinsamen Copy-Funktionen.
Der bisherige Buffer-Argsort für Router, MoE und QSA ist auf einen Adapter mit denselben Form-/Pufferprüfungen reduziert; seine duplizierte Sortier- und Kopierschleife wurde entfernt. Adapter und kanonischer Arraygraph gehen durch dieselbe Backendfunktion. Zurückgegebene Zwischenpuffer bleiben für vorhandene Buffer-Aufrufer bis zum GPU-Abschluss erhalten; im Arraygraph werden sie vom Encoder gehalten.
161 zusätzliche Original-Referenzfälle (23 Profile × sieben Dtypes) prüfen
jeweils alle vier Operationen, verzögert und mit vorbereiteten Eingaben:
1.288 bitgenaue Tensorvergleiche. Enthalten sind gleiche Sortierschlüssel,
negative Werte, beliebige Achsen, Transponierung, Schritt-/negative Strides,
Broadcast, Offset, Flatten sowie Ein-/Mehrblockgrenzen bis8.193 Elemente.
Für die Grenzprofile werden zusätzlich konkrete Kernel-Namen, Blockgrößen,
Grids und Anzahl der Merge-/Partition-Runden geprüft. Ungültiges kth wird
vor dem Dispatch abgewiesen. Leere Sortierachsen sind kein abgenommener Fall:
Der Originalbackend teilt durch die Achsengröße; der Rust-Port liefert bei0
einen Fehler statt einen erfolgreichen Sort vorzutäuschen.
Beleg: tests/fixtures/mtplx-sort-graph.jsonl, SHA256
a655665801dae88d9186faa60c4678bbf5af08b8b4797e95d836d5ab51cbd2b8.
Erfassung direkt mit sort_graph_fixtures im gepinnten MTPLX-0.32.2-Prozess,
ohne Modellgewichte oder Downloads. Der erste gemeinsame Release-Durchlauf
besteht124/124 Tests in73,96s, einschließlich bestehender Router-, MoE- und
QSA-Aufrufer. Dieser Lauf enthält die Ergebnisprüfungen; die anschließend
ergänzten Dispatch-Verträge werden im abschließenden Lauf geprüft.
Der finale gemeinsame Durchlauf mit unretained Command Buffers besteht
124/124 Tests in73,13s, einschließlich der Dispatch-Verträge. Die fokussierte
FastSync-Prüfung besteht ebenfalls. Release-Test-Clippy, Format-/Diff-Prüfung
und unveränderte Quellenprüfung bestehen. Vollständiges Prüfprotokoll:
local-eval-results/20260907-mtplx-port/sort-graph-check.log.
Diese Prüfzeiten sind keine Modell-Performancewerte.
P08 bleibt offen: fehlende Indexier-Dtypes, vollständige kanonische
Indexer-Auswahl/Cache-/Compiled-Graphbank und Attention-Aufruf. Der gesamte
kanonische Port ist weiterhin cfg(test); Produktmigration, vollständige
Funktionsparität, UI-Responsivität und die2%-Performance-Abnahme sind damit
ausdrücklich nicht abgeschlossen.
Verbundene kanonische Eager-QSA-Auswahl (2026-09-07)
attention::select_eager verbindet nun den zuvor portierten F32-Scoregraph
und Sort/Argpartition mit dem tatsächlichen QSAIndexer._select_eager-
Ablauf, dem kanonischen QSACache und allen fünf Ausgabeformen. Der gepoolte
F32-Spiegel kommt direkt aus QsaCache::pooled_f32_view, einschließlich
seiner gepaddeten, nicht-kontiguierlichen Ansicht. Causal-Blockgrenzen,
Minus-Unendlich-Maskierung und F32-Tie-Break werden vor Argpartition wie
im Original berechnet; die gewählten Indices bleiben eine Array-Ansicht.
Die Rückgabereihenfolge ist unverändert: chronologische Prefill-Blöcke mit Gather-Validität und Nullersatz; Flash-Decode mit Host-Tailgrenze; Decode-Gather mit vollständigen Blocktokens plus Rest; Rows-Gather mit gepaddeten Tailtokens und Gültigkeit; sonst vollständige kausale Maske. Flash gewinnt bei gleichzeitiger Aktivierung vor Decode-Gather. Gekachelte Scores schließen Rows-Gather wie im Original aus. Jede Kachel führt vor dem Anhängen der Indices ein echtes synchrones Eval aus; kein Ersatz durch Flush oder Async-Eval. Ungekachelte Auswahl und ungenutzte dichte Zwischen- ausdrücke bleiben verzögert. Die bestehenden Optionsfelder enthalten die vom Aufrufer aufgelöste Phase-/Positions-/Umgebungspolitik, nicht eine neue Heuristik allein anhand der Zeilenzahl.
Bool/I64-GatherAxis verwendet jetzt alle vorhandenen Stride-/Adressierungs-
varianten des Originaltemplates. Sieben zusätzliche Instanziierungen, keine
geänderten Kernelkörper. Der Quellenabgleich bestätigt weiterhin17 Original-
Metal-Körper und22 Runtime-Einheiten; die Runtime-Einstiegspunkte steigen
von176 auf183. Alle vier Bool/I64-Row-Contiguity-Kombinationen einschließlich
negativer Indices und negativer Source-/Index-Strides haben einen ausführbaren
Check. Der gemeinsame ops::repeat übernimmt Expand/Broadcast/Reshape aus
ops.cpp einschließlich Null-/Eins-/Fehlerfällen; auch die bestehende
Blockmaskenrekonstruktion verwendet ihn statt eines duplizierten Ausdrucks.
Die ursprünglichen Host-Lane-Zähler sind ebenfalls angeschlossen:
eager_selector, decode_flash_skip, decode_gather und
decode_dense_mask; Rows-Gather zählt wie das Original keinen dieser
Zähler. Snapshot und optionaler Bericht bei Prozessende über
MTPLX_QSA_PREFILL_DEBUG bleiben von GPU-Abschlussmessungen getrennt.
144 neue Receipts rufen direkt den gepinnten MTPLX-QSAIndexer._select_eager
mit dem originalen QSACache auf:24 Profile × BF16/F16/F32 × TF32 on/off.
Lazy und vorbereitete Rust-Ausführung ergeben420 bitgenaue Tensorvergleiche.
Abgedeckt sind alle Ausgabeformen, echte Kachelgrenzen und deren
Nichtaktivierung bei tile>=S, beide Gather-Schwellen, Flash-Priorität,
Prefill-vs-Verify-Phase, partielle Tails, ungültige frühe Top-k-Slots,
S2048, Kontext32768 sowie parametrisierte Ratio1/4/8. Der Test prüft Formen,
Host-Tailwerte, Lane-Zähler und Kernelarbeit vor der Rückgabe: ausschließlich
bei aktiven Score-Kacheln. Cache und Query werden vor dem abschließenden
Eval freigegeben, sodass auch die Graph-Lebensdauer geprüft wird.
Fixture: tests/fixtures/mtplx-qsa-eager-graph.jsonl, SHA256
25ea1819857c0eb91ff6700298f597ba47ccebe418cc5259a1dde76aae7bca2b.
Der erste fokussierte TF32-on-Test besteht in1,78s; der gemeinsame TF32-off-
Durchlauf mit unretained Command Buffers besteht125/125 Tests in74,83s.
Dieser erste Gesamtlauf liegt vor den zusätzlichen Bool-Layout- und
Lane-Zähler-Checks; deren finale Prüfung wird separat protokolliert.
Finaler Stand: gemeinsamer Standard-TF32-Durchlauf125/125 in75,49s;
TF32-off/FastSync-Auswahlprüfung1/1 in1,00s. Der Prozessabschluss meldet
die erwarteten Lane-Zähler (42 eager_selector,18 decode_flash_skip,
12 decode_gather,6 decode_dense_mask). Release-Test-Clippy, Format-/Diff-
und Quellenprüfung bestehen. Vollständige Protokolle:
local-eval-results/20260907-mtplx-port/eager-selection-graph-check.log.
Diese Testlaufzeiten sind keine Modell-Durchsatzwerte.
Die finale TF32-off/unretained-Gruppe für Eager-Auswahl, Bool-Gather-Layouts
und Repeat/Arraygraph besteht zusätzlich3/3 Tests in1,04s.
P08 bleibt offen: vollständiger Indexer-Aufruf mit Projektion, Query-/Pooling-
Vorbereitung und Cache-Update, Fused-/Compiled-Selektoren im kanonischen
Graph und Attention-Aufruf. Die Eager-Auswahl ist verbunden und geprüft,
nicht der gesamte Indexer und nicht das Produkt. Weiterhin cfg(test);
keine Vollmodell-Performance-, UI-Responsiveness- oder2%-Abnahme.
Gemeinsamer QSA-Indexer-Vorlauf und fortlaufender Cache (2026-09-07)
qsa_indexer::Indexer::prepare_rows verbindet jetzt den nicht-kompilierten
gemeinsamen Vorlauf von QSAIndexer._call_rows: vorhandenes Dense-/Quantized-
Linear oder direkt übergebene QK-Zeilen; Split/Reshape; Query-RMSNorm/RoPE;
positionsbezogenes Schreiben der Rohschlüssel; Vervollständigen ganzer Pool-
Blöcke, Norm/RoPE und Schreiben in gepoolten Cache samt F32-Spiegel.
Die vorher geprüften Array-, Linear-, RoPE-, Reduktions-, Cache- und Custom-
Kernel-Funktionen werden direkt wiederverwendet, keine zweite Mathematik.
Query und Pool verwenden bei tatsächlich erfüllter Original-Eligibility die
MTPLX-Prepare-Kernel; sonst den ursprünglichen Eager-Ausdruck. Pooling mittelt
zuerst inF32, castet zurück zum Eingabetyp, normiert und rotiert danach.
Blockpositionen stammen von min(cache.pooled_len,total/ratio), nicht von
der gerade gelieferten Chunkgrenze. Dadurch werden unvollständige Blöcke
über mehrere Aufrufe korrekt vervollständigt und nach Rollback neu berechnet.
Der Indexer verschiebt kv.offset nicht; das bleibt Aufgabe von Attention.
Unterhalb/einschließlich des Blockbudgets erfolgt der originale Rücksprung nach den Cache-Updates. Die dabei ungenutzte Query-Vorbereitung bleibt ein verworfener Lazy-Ausdruck; der Test prüft ausdrücklich, dass ihr CustomKernel nicht trotzdem dispatcht wird. Oberhalb des Budgets werden Query, gepoolte Ansicht und Frontier an die bereits verbundene Eager-Auswahl weitergegeben. Fused-/Compiled-Auswahl wird dadurch nicht stillschweigend ersetzt.
306 neue Receipts benutzen den unveränderten ursprünglichen QSAIndexer-
Aufruf und QSACache, mit kleinen lokalen Testgewichten und ohne Downloads:
BF16/F16/F32, Dense und übergebene nicht-kontiguierliche QK-Zeilen,
BF16-QuantizedLinear4/8bit, ganze/partielle RoPE, Prepare-Kernel an/aus,
Originalfallback bei D256 bzw. abweichendem Norm-Dtype, TF32 on/off.
Die Referenzflags wählen regulär Eager-Selection mit beiden Prepare-Pfaden;
es werden keine Methoden ersetzt. Diese Fixturekonfiguration ist kein
Produkt-Performance-Arm.
Jedes Profil führt neun Aufrufe mit einem weiterbenutzten Cache aus: 3,1,5,2041,1,4 Tokens, dann fünf Tokens trimmen,8,33,1 Tokens. Das umfasst Blockvervollständigung, die512-Block-Schwelle, Cache-/Spiegelwachstum, Rewriting nach Trim, Rows-Gather, Dense und Decode-Gather. Verglichen werden vollständige Roh-/Pooling-/Spiegel-Backings inklusive Shape/Kapazität, Frontiers und Auswahl-Ausgaben. Lazy/vorbereitete Ausführung über beide TF32-Prozesse ergibt2.108 bitgenaue Tensorvergleiche.
Beim ersten Rust-Vergleich wurden die physischen Bytes des transponierten
F32-Spiegels als Row-Major gehasht. Roh- und Poolingcache stimmten bereits;
der Fehler betraf nur die Test-Auslesereihenfolge. Der Fixture-Leser stellt
jetzt wie NumPy tobytes die logische Reihenfolge her, ohne Cache- oder
Modellberechnung zu ändern. Die unveränderten Referenzhashes bleiben Maßstab.
Fixture: tests/fixtures/mtplx-qsa-indexer-prefix.jsonl, SHA256
0f25280aab05b72158c7d596b67702c2bf67f2985bfa44fd9642430a14da5078.
Der fokussierte Standard-TF32-Vergleich besteht in2,76s.
Prüfprotokoll: local-eval-results/20260907-mtplx-port/indexer-prefix-check.log.
Finaler gemeinsamer Stand:126/126 Tests bei Standard-TF32 in76,36s, 126/126 bei TF32-off und unretained Command Buffers in78,51s. Die zusätzliche fokussierte FastSync-Sequenz besteht ebenfalls. Release-Test-Clippy, Format-/Diff- und unveränderte Quellenprüfung bestehen. Die genannten Prüfzeiten sind keine Inferenz-Performancewerte.
P08 bleibt offen: kanonische Fused-/Compiled-Selektoren samt durchgängigem
Routing und vollständiger Attention-Aufruf. prepare_rows ist kein
Ersatz für diese offenen Routen und kein neuer Produktionsfallback.
Der Port bleibt cfg(test); die vollständige Produktmigration und
Funktions-/Responsiveness-/2%-Performance-Abnahme sind weiterhin offen.
Fused-QSA-Selektor im kanonischen Arraygraph (2026-09-07)
qsa_select bildet nun den originalen qsa_indexer_select_metal-Aufruf
als Mehrfachausgabe-Primitive ab: Block-IDs/Gültigkeit/Scores, Token-IDs/
Gültigkeit oder Dense-Maske, jeweils mit dem privaten F32-Score-Scratch als
weiterem Graph-Sibling. Auswerten eines öffentlichen Ergebnisses führt den
gemeinsamen Kernel genau einmal aus. Verwerfen der Eingabehandles vor Eval
verliert weder Strides/Offsets noch dynamische Frontiers oder Scratch.
BF16, F16 und F32 werden für Query und Pool unabhängig gebunden, ohne Kontiguierungs- oder Typkonvertierungsdispatch vor dem Originalkernel. Der Host baut dessen unveränderten Header/Körper/Epilog mit den originalen Formkonstanten und NAX/TF32-Bedingungen zusammen. Alle Ausgabepuffer werden wie beim originalen CustomKernel vor der Kompilierung angelegt. Ein gemeinsamer Encoder übernimmt Bindings, Datenumfänge, Grid und Threadgroup-Größe; auch die bisherige Buffer-Schnittstelle verwendet jetzt diesen Backendpfad. Es wurde keine zweite Implementierung desselben Shaders eingeführt.
Indexer::select_fused übernimmt _select_fused: Query-Zeilen werden nach
32MiB Score-Scratch aufgeteilt, niemals die History. Dense-Ausgaben verwenden
die stabile physische Breite (backing_blocks+1)*ratio; nach Concatenate
folgt die logische Ansicht bis total. Zwischen den Chunks wurde kein
zusätzliches Eval oder Flush eingeführt.
126 neue unveränderte Referenz-Receipts umfassen alle drei Ausgabeformen,
BF16/F16/F32, gemischte Eingabedtypen, transponierte/gestridete/gebroadcastete
Ansichten, Top-k1/3/7/512, Ratio1/3/4, verschiedene Headgeometrien,
leere bzw. gepaddete History und eine echte 127+2-Zeilen-Aufteilung bei
65537 Backing-Blöcken. Für die Chunkfälle wird MTPLXs ursprüngliche
QSAIndexer._select_fused-Methode mit ihrem ursprünglichen Chunkhelper
aufgerufen; keine Ersatzmethoden. TF32 on/off und lazy/vorbereitete Eingaben,
zusätzlich Host-/Tensor-Frontiers für direkte Aufrufe, ergeben936 bitgenaue
Tensorvergleiche. Der Test prüft außerdem Sibling-Eigentümerschaft, verzögerte
Konstruktion und die tatsächlich dispatchten Geometrien.
Fixture: tests/fixtures/mtplx-qsa-fused-graph.jsonl, SHA256
56d8b82dd8978ecd8ab0d69d918744668ce7bf596ac61815f5c5e9cd666f3b19.
Prüfprotokoll: local-eval-results/20260907-mtplx-port/fused-selection-graph-check.log.
Der gemeinsame Stand besteht127/127 Tests bei Standard-TF32 in78,54s und127/127 bei TF32-off mit unretained Command Buffers in78,98s. Der fokussierte Fused-Graph-Test besteht zusätzlich mit FastSync, TF32-off und unretained Command Buffers in1,65s. Release-Test-Clippy sowie Format-/Diffprüfung bestehen. Die Quellenprüfung bestätigt weiterhin17 originale Körper,41 Custom-Entrypoints und22 Runtime- Einheiten mit183 Einträgen; an den Shaderdateien war keine Änderung nötig. Diese Testzeiten sind keine Modell-Inferenzmessung.
P08 bleibt offen: kanonischer vektorisierter Prefill-Selektor und Compiled-
Indexer, vollständiges Routing sowie Attention-Aufruf. Der neue Fused-Pfad
ist kein Ersatz für diese anderen Originalrouten und wird nicht als
allgemeiner Prefill-Fallback eingesetzt. Produktion bleibt unverändert auf
dem alten Graphen (qwen_mtplx ist weiterhin cfg(test)). Deshalb sind
Funktions-/Responsiveness-/2%-Performance-Parität des Gesamtmodells weiterhin
nicht nachgewiesen; dieser Schritt hat keine Performance-Auswahl oder
begründungslose Rücknahme eines MTPLX-Bestandteils vorgenommen.
Zweistufiger Prefill-Selektor im kanonischen Arraygraph (2026-09-07)
qsa_prefill::select verbindet jetzt den originalen
qsa_indexer_prefill_metal-Graphen: statische Score-Produzentenwahl,
produzentenabhängiges Workspace-/Alignment-Budget, Query-Slices, Scores,
exakter Top-k-Selektor und Concatenate aller öffentlichen Ergebnisblätter.
BF16/F16 mit gleicher Eingabedtype und H4/D128 verwenden bei originaler
NAX-Eligibility den unveränderten TensorOps-Score-Kernel. Sonst wird der
bereits geprüfte attention::qsa_scores-Ausdruck verwendet: F32-Matmul,
ReLU pro Head, F32-Summe, Division. Der transponierte F32-Pool entsteht
in dieser Route nur einmal und wird zwischen Chunks geteilt.
Es gibt keinen Laufzeit-Fallback nach ausgewähltem TensorOps-Dispatch. Ein Fehler bleibt sichtbar. Score-Workspace zählt dort nur eine Ebene, beim allgemeinen Ausdruck H+1; große Teilchunks werden nach unten auf32 Zeilen ausgerichtet, eine irreduzible Zeile darf ein kleineres Budget überschreiten. Wie im Original kommt kein zusätzlicher Chunk-Eval/Flush hinzu.
Beide neuen CustomKernel-Primitive teilen ihre Encoder mit den vorherigen
Buffer-Aufrufern. Der Top-k-Quellgenerator ist nun Ratio-parametrisch statt
auf4 festgelegt. Header/Körper/Epilog bleiben aus dem gepinnten Export.
Top-k besitzt den ursprünglichen Mehrfachausgabe-Vertrag ohne zusätzlichen
Scratch-Sibling. Der CustomKernel legt zuerst alle Ausgaben an, führt dann
bei nicht-row-kontiguierlichen Eingaben die originale General-Copy aus und
kompiliert/dispatcht anschließend. TensorOps konsumiert tatsächliche Strides
und Offsets ohne solche impliziten Eingabekopien. Dynamische Frontiers
bleiben im Graphen; auch pos+row_start wird nicht auf dem Host ausgelesen.
144 neue Receipts aus unveränderten MTPLX-Aufrufen prüfen BF16/F16/F32, gemischte Dtypes, Original-Fallbacks für andere Headgeometrien, transponierte/gestridete/gebroadcastete Eingaben, alle drei Ausgabeformen, kleinstes Workspace sowie produktionsnahe K512-/Ratio4-Geometrien. Der65-Zeilen-Fall erzwingt im TensorOps-Pfad32+32+1 Zeilen, im allgemeinen H4-Pfad8-Zeilen-Chunks plus Rest. Eigenständige Top-k-Fälle prüfen außerdem gestridete Scores und kleinere/mehrstufige Radix-Kandidatenmengen. TF32 on/off, lazy/vorbereitete Eingaben und Host-/Tensor-Frontiers ergeben 1.152 bitgenaue Tensorvergleiche. Tatsächliche Producer-/Top-k-Geometrien, Copy-Anzahl und verzögerte Konstruktion werden separat geprüft.
Die erste neue Testassertion zählte Concatenate fälschlich als einen Dispatch; tatsächlich kopiert das Original jedes Chunk-Blatt einzeln. Nur diese Erwartung wurde korrigiert, keine Referenzhashes oder Shader. Der anfängliche33-Zeilen-Fall passte noch in einen Chunk und wurde für einen echten Alignment-/Restchunk-Nachweis mit65 Zeilen neu aufgenommen.
Fixture: tests/fixtures/mtplx-qsa-prefill-graph.jsonl, SHA256
f223b1157d13833e899fb1b73e35a5343f26fb48940ee3c908829df14f6ae289.
Prüfprotokoll: local-eval-results/20260907-mtplx-port/prefill-selection-graph-check.log.
Der fokussierte Standard-TF32-Test besteht in2,17s; keine Inferenzzeit.
Gemeinsamer Stand:128/128 Port-Tests bei Standard-TF32 in82,49s und 128/128 bei TF32-off mit unretained Command Buffers in80,25s bestanden. Der fokussierte Prefill-Test besteht zusätzlich mit FastSync, TF32-off und unretained Command Buffers in2,04s. Release-Test-Clippy, Format-/Diffprüfung und die unveränderte Quellenprüfung (17 Körper,41 Custom-Entrypoints,22 Runtime-Einheiten/183 Einträge) bestehen. Die ursprünglichen Shaderdateien benötigten keine Änderung.
P08 bleibt offen: kanonischer Compiled-Indexer, vollständige Verbindung der
vorhandenen Selektoren mit Indexer-Routing und Attention, Full-SDPA sowie
Produktmigration. Der gesamte neue Graph bleibt cfg(test). Es wurde kein
Produkt-Performance-/Responsiveness-Pass aus diesen Kernelprüfungen abgeleitet.
Dynamische Cache-Fenster im kanonischen Arraygraph (2026-09-07)
Die noch fehlenden DynamicSlice/DynamicSliceUpdate-Operationen des
Compiled-Indexer-Graphen sind nun im gemeinsamen Array-/Eval-Pfad vorhanden.
Achsenprüfung, Broadcast/Cast des Updates, leere Ergebnisse/Updates,
Copy-/Donation-Auswahl und dynamische Geräteoffsets folgen dem gepinnten
Runtime-Original. Die Updates benutzen denselben General/GeneralGeneral-
Copy-Encoder wie statische Operationen, mit den ursprünglichen dynamischen
Runtime-Kerneleinträgen. Es kommen weder Host-Readback der Position noch
zusätzlicher Eval/Flush oder eine Ersatzimplementierung des Indexers hinzu.
Die Offset-Berechnung verwendet den erfassten ursprünglichen Shaderkörper
mit den originalen acht Integer-Typinstanziierungen. Auch die bisherigen
Buffer-basierten Cache-Aufrufer verwenden jetzt diesen gemeinsamen Encoder;
deren doppelte Offset-Implementierung ist entfernt.
Originales Last-use-Donation kann Metadaten des Indexpuffers unverändert an
den internen int64-Offset weitergeben, einschließlich abweichender Dtype,
Scalar-Rank und data_size. Dafür gibt es die originale unqualifizierte
copy_shared_buffer-Variante; die vorhandene explizite View-Prüfung bleibt
unverändert. Physische Zugriffsgrenzen werden weiterhin geprüft.
Beim Ergänzen des Donation-Tests fiel im Quellvergleich eine fehlende
Output-Byteoffset-Bindung auf; sie ist korrigiert. Tests mit Offset 0/8 prüfen auch,
dass vorangestellte Sentinel-Bytes unverändert bleiben.
30 Fälle aus unveränderten Referenzaufrufen liefern 360 bitgenaue Tensorvergleiche:
BF16/F16/F32, acht Integer-Indextypen, lazy/vorbereitete Eingaben,
behaltene/freigegebene Quellen, Transpose/Stride/Broadcast/negative Strides,
mehrere Achsen, leere und skalare Updates sowie verkettete Cache-Fenster.
Zusätzlich werden Dispatch-Anzahl, verzögerte Konstruktion und gemeinsame
beziehungsweise getrennte Pufferidentität geprüft.
Fixture: tests/fixtures/mtplx-dynamic-slice-graph.jsonl, SHA256
86d170991c68c9009b10eeead9479bc575e89b7eef6528e2a39677220d218acc.
Gemeinsame Regression: 129/129 Port-Tests bestehen mit Standard-TF32
(80,93 s) und mit TF32-off/unretained Command Buffers (81,71 s).
Der fokussierte neue Test besteht zusätzlich mit FastSync (0,81 s).
Release-Test-Clippy, Format-/Diffprüfung und die unveränderte Quellenprüfung
(17 Körper, 41 Custom-Entrypoints, 22 Runtime-Einheiten/183 Einträge) bestehen.
Protokoll: local-eval-results/20260907-mtplx-port/dynamic-slice-graph-check.log.
Dies sind Testlaufzeiten, keine Inferenz-Leistungsdaten.
P08 bleibt offen: Dies schließt eine Abhängigkeit des kanonischen Compiled-
Indexers, nicht dessen Graphbank/Replay und Routing. Full-SDPA, vollständiger
Attention-Aufruf und Produktmigration bleiben erforderlich. Weiterhin
cfg(test); kein Gesamtmodell-, UI- oder Performance-Paritätsnachweis.
Reiner Compiled-Indexer und kanonisches Graph-Replay (2026-09-07)
qsa_compile::Body verbindet nun die reine zehnargumentige Grenze von
QSACompiledIndexerCore: bereits projizierte Q/K-Zeilen oder interne
Projektion, explizite Norm-/RoPE-Eingänge, dynamische Raw-/Pool-Updates,
begrenztes rückwärtiges Pool-Fenster, Query-Vorbereitung und alle fünf
Ausgabeformen. Die vier State-Ergebnisse bleiben Array-Ausgänge; Position
und logische Blockzahl werden unverändert als Eingangsdescriptoren
zurückgegeben. Der Body mutiert keinen Host-Cache und liest keine Frontiers
auf dem Host aus.
compiled::Replay übernimmt die feste DFS-/Sibling-Tape-Struktur und
compile_replace-Semantik: einmalige Tracer-Platzhalter, danach neue
Ausgabe-Descriptoren mit gemeinsamem unveränderlichem Primitiv und jeweils
aktuellen Eingangsarrays. Konstanten/Load-Blätter bleiben geteilt, Shapes
und Dtypes sind fest, Strides/Offsets und Werte keine Trace-Konstanten.
Die Konstruktion und das Replay dispatchen keine GPU-Arbeit. Ein eigener
Hosttest prüft vertauschte Sibling-Root-Reihenfolge, Descriptor-/Primitiv-
Identität, neue Eingänge sowie Fehler für falsche Signaturen und unzulässig
geschlossene ursprüngliche Aufrufseingänge.
Die Clamp-/Multiply-/Chunk-Position-Knoten verwenden die unverändert erfassten fusionierten Compiled-Shader, keine Reihe einzelner Binary-Kernel. Sie teilen den bereits vorhandenen Compiled-Evaluator einschließlich Layout-/Donation-Auswahl. Auch die vorherigen Buffer-Aufrufer benutzen jetzt diesen Backendpfad; drei doppelte Skalar-Encoder sind entfernt. Quellgenerierung und JSON-Auswertung geschehen nur beim ersten Compile, nicht bei jedem Decode-Schritt. Der Prefill-Body teilt den bisherigen Zweistufen-Selektor; im Compiled-Aufruf ist die Chunk-Position ebenfalls der originale fusionierte Add-Knoten.
198 bestehende unveränderte Referenzfälle prüfen Q/K und vier affine Hidden-Projektionsvarianten (4/8 Bit, Gruppen32/64), alle fünf Modi, Zeilenzahlen1/4/5/33/65/2048, zwei Scratch-Budgets sowie wechselnde Q/K-Strides640/704. Ausgaben, neue/alte Cache-Hashes und die aus dem Original-DOT abgeleiteten geordneten Abhängigkeits-/Sibling-Fingerprints stimmen überein. Die Testbank verwendet bei Stride-Wechseln denselben Replay-Eintrag; sie ist nicht die noch ausstehende produktive Host-Graphbank. Die Referenzfälle sind BF16/H4/D128, Prefill verwendet MPP auf diesem M5 Max.
Der Test führt diese Fälle anschließend jeweils mit behaltenen und ohne behaltene Cache-Snapshots aus: 396 Replays und 2.052 Tensor-/Cache-Hashes. Mit Snapshot müssen alte Zustände unverändert bleiben und neue Backings entstehen; ohne Snapshot müssen Raw- und Pool-Ausgabe die ursprüngliche Data-Identität wiederverwenden. Die Graphbank selbst hält keine alten Aufrufseingänge und verhindert diese Donation nicht.
131/131 gemeinsame Port-Tests bestehen bei Standard-TF32 (80,79 s; vor
Erweiterung des neuen Tests auf beide Snapshot-Varianten) und bei TF32-off
mit unretained Command Buffers (82,09 s; alle 396 Replays).
Die 396 Replays bestehen zusätzlich bei Standard-TF32 mit FastSync (1,33 s).
Release-Test-Clippy, Format-/Diffprüfung und die unveränderte Quellenprüfung
(17 Körper, 41 Custom-Entrypoints, 22 Runtime-Einheiten/183 Einträge) bestehen.
Protokoll: local-eval-results/20260907-mtplx-port/compiled-indexer-replay-check.log.
Dies sind Testlaufzeiten, keine Modell-Inferenzmessungen.
P08 bleibt offen: der Host-Core mit Bucket-/Frontier-Validierung, vollständigen
Compile-Schlüsseln, Engagement-Statistik und Indexer-Routing; außerdem
weitere Compiled-Geometrien/Dtypes einschließlich der allgemeinen
Nicht-MPP-Score-Fusion, Full-SDPA, Attention und Produktmigration.
Replay ist ausdrücklich kein allgemeiner Ersatz für die ursprünglichen
Compiler-Simplify-/Fuse-Pässe. Deren Wirkung ist für die oben genannten
erfassten Graphen nachgewiesen, nicht pauschal für beliebige Ausdrücke.
Weiterhin cfg(test), keine Modell-/UI-/2%-Performance-Abnahme.
Kanonischer Compiled-Host-Core und Engagement (2026-09-07)
qsa_core::Core implementiert nun zusätzlich zum reinen Replay-Test den
Host-Vertrag von QSACompiledIndexerCore: unveränderliche Konfiguration,
Norm-/RoPE-Eingänge, optionale interne Projektion und getrennte Hidden-/QK-
Schlüssel. Sämtliche Shape-/Dtype-/Head-/Top-k-/Ratio-/Dense-Capacity-/Producer-
und Chunk-Felder des ursprünglichen _CompileKey werden berücksichtigt.
Werte, Strides und Offsets sind weiterhin keine zusätzlichen Schlüssel.
Die ursprüngliche Standardkonfiguration und benutzerdefinierte Bucket-
Untergrenzen sowie die abschaltbare Bucket-Pflicht bleiben erhalten.
Der Core prüft Projektions-/Cache-/Norm-Dtypes, Backing-Geometrien, feste Pool-Fenster, Host-Frontiers und Backing-sichere Dense-Ausgabebreiten vor dem Dispatch. Tensor-Frontiers werden lediglich auf ein int32[1]-Array normalisiert, nicht synchron auf dem Host ausgelesen. Die Rückgabe trennt Auswahl und vier explizite State-Blätter. Host-Cache-Commit und Aufrufroutenauswahl liegen weiterhin beim noch anzuschließenden Indexer.
Calls, Source-/Mode-/Producer-Zähler, Selector-Dispatches, Capacity-Transitions, Bucket-Zähler und vollständig sortierte Compile-Key-Berichte folgen dem Original. Ein nach erstem Trace-Fehler leerer Laufzeit-Eintrag bleibt im Host-Core bestehen: Wiederaufruf versucht den Trace erneut, ohne einen zweiten Core-Trace-Request zu zählen oder einen halb aufgebauten Replay zu verwenden. Bereits als Tracer übergebene Arrays bauen wie im Original direkt den Body, statt den gecachten Replay zu verwenden. Kein Eager-Fehlerfallback wurde ergänzt.
32 neue Receipts wurden mit unverändertem MTPLX-Core aufgenommen: elf echte aufeinanderfolgende Aufrufe mit wechselnden Shapes, Strides, Positionen, Kapazitäten, Hidden-/QK-Quellen und allen fünf Modi (66 bitgenaue Output-/State- Hashes), vollständige Zwischen-/Endberichte, 17 Validierungsfälle und zwei aufeinanderfolgende fehlgeschlagene Erst-Traces. Der zulässige Tensor-Frontier- Fall wird nur lazy aufgebaut und ausdrücklich nicht auf der GPU ausgeführt; sein Host-Gegenstück wird vorher abgewiesen. Neun zusätzliche Konstruktor- Assertions sichern die direkt aus dem Quellcode portierten Grenzen ab.
Fixture: tests/fixtures/mtplx-qsa-core-host.jsonl, SHA256
05d3642cbf08a12f6f1c1ad7cac0b529d2ef51f3bfb9c27ab6ab229aa1017022.
Der fokussierte Referenztest besteht (0,75 s; keine Inferenzzeit).
Gemeinsame Regression: 132/132 Port-Tests bei Standard-TF32 (82,51 s) und
TF32-off/unretained Command Buffers (82,61 s); fokussierter Host-Core mit
FastSync ebenfalls bestanden (0,07 s). Release-Test-Clippy, Format-/Diff-
prüfung und unveränderte Quellenprüfung (17 Körper, 41 Custom-Entrypoints,
22 Runtime-Einheiten/183 Einträge) bestehen. Protokoll:
local-eval-results/20260907-mtplx-port/compiled-host-core-check.log.
Die Laufzeiten sind keine Modell-Performance-Abnahme.
P08 bleibt offen: Parameter-Identitätssiegel und Core-Lebenszyklus im Indexer,
automatische Backing-Reservierung/Commit, vollständiges Fused-/Eager-/Compiled-
Routing, übrige Compiled-Geometrien/Dtypes und Nicht-MPP-Score-Fusion,
Full-SDPA, Attention und Produktmigration. Der Host-Core ist noch nicht der
vollständig verbundene Modellaufruf; weiterhin cfg(test) und keine
Modell-/UI-/2%-Performance-Abnahme.
Durchgehender kanonischer Indexer und Cache-Commit (2026-09-07)
qsa_indexer::Indexer verbindet jetzt den gemeinsamen Vorlauf, den persistenten
Compiled-Core sowie Compiled-/Prefill-/Fused-/Eager-Routing in einem Aufruf.
Die ursprünglichen Phase-/Shape-/Dtype-/Projektions-/Cache-Prüfungen entscheiden
vor der Reservierung; Dispatchfehler führen nicht zu einem Eager-Wiederanlauf.
Die vorhandene Modusregel wird auch vom alten Buffer-Aufrufer verwendet und
nimmt nun Ratio/Top-k explizit entgegen, statt die Modellgeometrie festzusetzen.
Die bereits geprüften Selektoren, Cache-Operationen und Engagement-Zähler werden
gemeinsam genutzt. Es gibt keinen zusätzlichen Flush, Wait oder Readback im
Compiled-Aufruf; ursprüngliche Eager-Kachel-Evals bleiben unverändert.
Das Identitätssiegel erfasst Normen, Frequenzen und Projektionsgewicht sowie
Quantisierungsskalen/-biases. Ein ausgetauschtes Blatt baut den Core neu auf;
gleiche Bytes genügen nicht zum Wiederverwenden. Unveränderte Blätter behalten
den Core und dessen ursprünglich erfasste Speicherbudgets. Fehlgeschlagene
Neukonstruktion lässt den bisherigen Core samt Siegel bestehen. Backings werden
vor dem Core-Aufruf reserviert; dessen explizite Ergebnisse ersetzen die
Cache-Arrayobjekte, aktualisieren die logische Pool-Länge und verwerfen den
F32-Spiegel. Alte Snapshots bleiben unverändert. cache.kv.offset wird nicht
vorweggenommen; dessen Fortschreibung gehört weiterhin zu Attention.
26 neue, unveränderte MTPLX-Aufrufe prüfen fortlaufend alle fünf Rückgabeformen,
Hidden-/QK-Quellen, dichte/quantisierte Projektion, Gewichtswechsel, Budget-
Wiederverwendung, Backing-Wachstum, Trim und gescheiterte Core-Ersetzung.
52 Rust-Aufrufe mit/ohne gehaltene Snapshots stimmen in 216 Output-/State-
Hashvergleichen überein; vollständige Core-Berichte stimmen ebenfalls.
Fixture: tests/fixtures/mtplx-qsa-indexer-commit.jsonl, SHA256
ed4dde278663e0f7d684fc78ea51474f68ab5326f467f3022ef521a7cf93939e.
Zusätzlich stimmen die 200 vorhandenen vollständigen Indexer-Referenzaufrufe einschließlich 2K-Prefill, aller Lane-Wechsel, Cache-Inhalte und Graphbank-Zähler mit dem kanonischen Arraygraph überein. Die 720 vorhandenen statischen Zulässigkeitsfälle stimmen ohne GPU-Dispatch überein, einschließlich inkonsistenter Frontiers und nicht gebucketeter/leer vorhandener Backings. Diese Nachweise betreffen die erfasste B1/BF16/H4/D128-Modellgeometrie, nicht beliebige Typen.
Gemeinsame Regression: 134/134 bei Standard-TF32 (84,69 s; vor Ergänzung der
720 statischen Assertions) und TF32-off/unretained Command Buffers (84,18 s;
einschließlich dieser Assertions). Die drei Indexer-Tests bestehen außerdem
bei Standard-TF32 mit FastSync (3,36 s), ebenfalls einschließlich aller
720 Assertions. Release-Test-Clippy, Format-/Diffprüfung
und die unveränderte Quellenprüfung (17 Körper, 41 Custom-Entrypoints,
22 Runtime-Einheiten/183 Einträge) bestehen. Protokoll:
local-eval-results/20260907-mtplx-port/indexer-lifecycle-routing-check.log.
Diese Laufzeiten sind Korrektheitstestzeiten, keine Inferenzmessungen.
P08 bleibt offen für übrige Compiled-Geometrien/Dtypes einschließlich der
allgemeinen Nicht-MPP-Score-Fusion, Full-SDPA, den vollständigen Attention-Aufruf
und die Produktmigration. Der Port bleibt cfg(test); die alte UI-Ausführung
ist damit noch nicht ersetzt und das 2%-Gesamtziel bleibt offen.
Verbundener Qwen-Attention-Modulaufruf (2026-09-08)
qsa_attention::Attention verbindet nun den vollständigen BF16/D256-Aufruf
der MTPLX-Klasse: separate Q/K/V-Projektionen oder gemeinsame Drei-/Vierfach-
Projektion, Indexer vor KV-Fortschreibung, per-Head-Norm, Query-/Gate-Aufteilung,
partielles RoPE/M-RoPE, KV-Update, sämtliche QSA-Consumer, Sigmoid-Ausgangsgate
und Ausgangsprojektion. Biased separate Projektionen sowie fehlender Indexer
sind ebenfalls abgebildet. Die bereits geprüften Operationen/Kernel werden
verwendet, nicht neu implementiert.
Ein beim Anschluss geschlossener Referenzunterschied: Die originale
Vierfachfusion entfernt indexer.index_qk_proj. Indexer::projection ist
deshalb jetzt optional. Zugelieferte QK-Zeilen funktionieren ohne diese
Projektion; das Identitätssiegel enthält dann nur Normen/Frequenzen und der
Compiled-Core erfasst keine versteckte zweite Projektion. Ein Hidden-Aufruf
ohne Projektion wird nicht durch einen erfundenen Ersatz bedient.
Die Consumer-Reihenfolge bleibt Flash-Skip, Prefill-Flash, optionaler Prefill-Gather, Dense-Rekonstruktion, Rows-Gather und gewöhnliches SDPA. Sparse-Flash liest die KV-Backings und ihre Kapazitätsstrides direkt. Die ursprünglichen Engagement-Zähler und die expliziten Gather-Tile-Evals bleiben erhalten; es gibt keine zusätzliche Aufmerksamkeitssynchronisation. Ein Vision-Request überspringt nur die Sparse-Auswahl, nicht den Indexer und seine Cache-Updates. M-RoPE verwendet innerhalb der Tabelle deren Achsen; danach die normale Positionsfolge mit Request-Delta. Ohne konfigurierte M-RoPE-Achsen bleibt das originale Plain-RoPE-Verhalten erhalten.
Keine stillschweigende Full-SDPA-Abkürzung: Qwens normaler D256-Aufruf
verwendet eine explizite Array-Maske oder keine Maske. Die gepinnte Runtime
selektiert hier für S>8 den Matmul-Fallback. Der NAX-D256-Split wird dagegen
nur für kausale String-Maske ohne Array-Maske und S>=1024 gewählt
(scaled_dot_product_attention.cpp:750–767). Der Modellport behält diese
Originalauswahl; die allgemeine Full-SDPA-Erweiterung bleibt separat offen.
56 Receipts stammen aus der unveränderten MTPLX-Attention-Klasse, je 28 mit
TF32 an/aus. Zehn fortlaufende Szenarien umfassen kalten 2K-Prefill,
Prefill ab 32768 mit ursprünglichem Sparse-Flash, Decode/Verify, alle Consumer,
Cache-Trim, Projektionsfusion mit wirklich entfernter Indexer-Projektion,
Bias/no-indexer und Vision inklusive des ersten Schritts nach dem Tabellenende.
Die Referenz protokolliert die tatsächlich aufgerufenen Consumer durch reine
weiterleitende Beobachter; keine Berechnung wird ersetzt. 288 Referenzhashes
decken Ausgabe und KV-/Raw-/Pool-/F32-Mirror-Backings ab. Rust prüft zusätzlich
Shapes, Frontiers, vollständige Core-Berichte, Engagement-Deltas und die
tatsächlichen Sparse-Flash-Graphknoten/-Dispatches.
Fixture: tests/fixtures/mtplx-qsa-attention-module.jsonl, SHA256
d0fdbd1ad13820004a672a7634e50a66cf50a708180a9d037720920619f02016.
112 Rust-Aufrufe (jeweils lazy/vorbereitet, TF32 an/aus) bestehen mit
576 bitgenauen Ausgabe-/Cache-Hashvergleichen. Gemeinsame Regression135/135
bei Standard-TF32 (120,88 s) und TF32-off/unretained Command Buffers
(121,01 s); vollständiger Attention-FastSync-Test ebenfalls bestanden
(1,34 s). Release-Test-Clippy, Format-/Diffprüfung und unveränderte
Quellenprüfung (17 Körper,41 Custom-Entrypoints,22 Runtime-Einheiten/183
Einträge) bestehen. Die Testlaufzeiten sind keine Modell-Performancewerte.
Protokoll: local-eval-results/20260908-mtplx-port/attention-module-check.log.
Der vollständige Modell-/Decoder-/Serving-Aufruf und die Produktionsumstellung
bleiben offen, ebenso andere SDPA-Dtypes/Geometrien und übrige Compiled-
Geometrien/Nicht-MPP-Score-Fusion. cfg(test) ist weiterhin aktiv;
dies ist weder eine UI-Responsivitäts- noch eine Gesamtperformance-Abnahme.
Aktuelle Reproduktionsbefehle für die Kernel-Korrektheit:
python3 tools/mtplx-kernel-source.py local-eval-results/mtplx-reference-e652d55 --gated-delta-source local-eval-results/mtplx-reference-env-0.32.2/lib/python3.12/site-packages/mlx_lm/models/gated_delta.py --check
cargo test --release mtplx_canonical_source_bodies_preserve_pinned_hashes -- --nocapture
cargo test --release mtplx_canonical_hyper_and_gdn_kernels_match_reference -- --ignored --nocapture --test-threads=1
cargo test --release qwen_mtplx -- --include-ignored --test-threads=1
Auftrag und Grenzen
Qwen muss funktional und hinsichtlich Durchsatz und Verzögerungen dem tatsächlich aktivierten MTPLX-Pfad entsprechen oder schneller sein. Die Referenzzuordnung ist verbindlich und gilt auch für spekulatives Decoding:
| Modell | Golden Master | Andere Implementierungen |
|---|---|---|
| DeepSeek V4 Flash | antirez/ds4, einschließlich DSpark | MTPLX nur als zusätzliche Optimierungsquelle |
| GLM 5.3 Flash | antirez/ds4, einschließlich integriertem MTP | MTPLX nur als zusätzliche Optimierungsquelle |
| Qwen3.8 Flash Next | MTPLX | DS4 nur für gemeinsame Infrastrukturideen, nicht als Qwen-Orakel |
Ein möglicherweise besserer MTPLX-Ansatz für DeepSeek/GLM ersetzt deren Golden Master nicht. Verbesserungen müssen die antirez/ds4-Verhaltens- und Sampling- Verträge erhalten; eine abweichende Semantik braucht vor Umsetzung eine ausdrückliche Nutzerentscheidung. Die UI und die Headless-Harness müssen dieselbe Produkt-Inferenz ausführen. Ein kleinerer Qwen-Prefill-Chunk, niedrigere Leistung oder zusätzliche Wartezeiten sind kein Ersatz für Ursachenklärung.
Dieser Abgleich inventarisiert die Ausführungskette und ordnet belegte Unterschiede, bereits korrigierte Fehler und noch fehlende Nachweise ein. Er behauptet nicht, dass jede numerische Operation und jeder seltene Fallback bereits als identisch bewiesen ist. Diese offenen Nachweise haben unten eigene Tasks mit Abnahmekriterien. Für die weitere Umsetzung gilt die verbindliche Auftragspräzisierung oben.
Nur vorhandene Modelle; keine Downloads. Keine neuen Projekt-Gates, externen Issues oder Codex-Tasks. Die folgende Liste ist die lokale Arbeitsquelle. Bestehende ungecommittete Änderungen bleiben erhalten.
Festgehaltene Referenzen und Belege
- DS4Server: Arbeitsbaum auf
b99ce2a, inklusive ungecommittierter Änderungen. - MTPLX:
local-eval-results/mtplx-reference-e652d55, Commite652d55e2652137a4abcf1312357abbf3eb9d692, installierte Runtime0.32.2. Am2026-09-06 identisch wiederhergestellt, nachdem im früheren temporären Checkout/private/tmp/MTPLX-analysis-20260901Quelldateien fehlten. - DS4:
/Users/gb/Projects/ds4, Commitec7642cdd9ec81d01ad4b1fd8f8a3d1511533748. C-Code nur lesen, nicht in DS4Server übernehmen, kompilieren oder als Inferenz-Backend aufrufen. - Qwen: vorhandenes Bare-Speed-Artefakt unter
/Users/gb/Library/Application Support/de.rfc1437.ds4server/models/qwen3.8-flash-next. - Messbelege und Methoden: Qwen-Responsiveness-Bericht.
Rohdaten:
/private/tmp/ds4-ongoing-verified.16vzVw/.
Der wiederholte MTPLX-AR-Lauf mit expliziter Session hatte maximal 2,974 ms GPU-Canary-Completion im Prefill, MTPLX-MTP 0,550 ms. DS4Server-AR hatte 4090,027 ms. Gleiche native Probe, im jeweiligen Inferenzprozess; keine fehlgeschlagenen Probes. Das belegt eine reale Responsiveness-Differenz, aber noch nicht deren vollständige Aufteilung auf Scheduling und einzelne Kernel.
Die bisherigen Durchsatzwerte sind keine saubere 2%-Abnahme: Tokenisierung und Cache-Wiederverwendung unterscheiden sich, die Canary war aktiv, und es fehlt eine wiederholte, vollständig normalisierte Sechs-Zellen-Matrix. Historische GLM-MTP-Daten mit überlappenden Workern sind ungültig.
Tatsächlich aktive Qwen-Referenz statt allgemeiner MLX-Defaults
Die /health-Receipts in mtplx-ar-session.jsonl und mtplx-mtp.jsonl belegen:
Turbo, Chunk 2048, Kontextkapazität 131072, Low, Temperatur 1, top-p 0,95,
top-k 20, Seed 12345; committed MTP history, batched verify,
linear-gdn-from-conv-tape, lazy target distributions, family capture commit.
Fused HC V3, GDN input/step/convnorm, verify convnorm und gate/up sind aktiviert.
NAX verify ist für diese Familie deaktiviert, trotz des generischen
Turbo-Profils. Aktiviertes Environment allein beweist noch keinen Kernel-Aufruf;
Form- und Gerätegrenzen müssen ebenfalls passen.
Die Referenz lädt den MTP-Kopf auch beim AR-Server. Ihr Ready-Receipt zeigt noch laufende Background-Warmup-Schritte. DS4Server lädt den Kopf bei abgeschaltetem MTP nicht und die Harness führt einen eigenen separaten Warmup aus. Ladezeit, Speicherbedarf und Kaltstart dürfen deshalb noch nicht direkt gleichgesetzt werden.
Veröffentlichte M5-Max-Zahlen: Orientierung, keine Ersatzmessung
Der lokal gepinnte MTPLX-Releasebericht 2.10.0 nennt für Flash-Next 61 tok/s AR und 63–76 tok/s MTP je nach Workload. 2.10.1 nennt für lange Prefills 175,7 → 114,5 s bei 98k Tokens und 810 tok/s bei 131k. Diese Angaben sind keine Referenz für einen beliebigen kurzen Summary-/Story-Chat. Die Online-Abfrage der gepinnten MTPLX-Dateien war nicht abrufbar; die Zahlen sind aus dem aktuell lokal geprüften Referenzcheckout, nicht als online neu bestätigt ausgegeben.
Der DS4-Speedabschnitt beschreibt dagegen 2048-Token-Schritte und 128 greedy Tokens mit Promessi sposi. Im lokalen Pin stehen bei Kontext 2048 rund 790,18 Prefill- und 39,35 Decode-tok/s. Das ist eine andere Arbeit als drei freie Antworten bis EOS. Nicht vermischen.
Abdeckungsmatrix der Ausführungskette
Status: M gemessen; Q Unterschied im Quellcode belegt, Kosten/Tragweite noch nicht vollständig gemessen; T Teilnachweis vorhanden; O Nachweis offen. Quellstellen beziehen sich auf den oben genannten Arbeitsstand.
| Bereich | DS4Server | Referenz / Befund | Status / Task |
|---|---|---|---|
| Frontend → Engine | src/app/generation.rs:780, src/model_eval.rs:803, src/runtime.rs:108 |
Gleicher GenerationService, eigener model-runtime-Thread, LocalChat. Harness hat keinen echten GUI-Eventloop und bildet nicht jede UI-Nebenarbeit ab. |
T/Q · P02, P04 |
| Systemprompt / Tools / Skills | src/app/generation.rs:2469 |
Headless-Helper lädt ExtensionRegistry und hängt verfügbare Skill-Instruktionen an. Kein Beleg für ausgeführte Tools, aber noch kein sauber isolierter Test ohne deren Prompt-Anteile. | Q · P02 |
| Qwen-Chatfortsetzung | src/engine/tokenizer.rs:524, src/engine.rs:1420 |
Zusätzliche Low-Systemnachricht bei Checkpoint-Fortsetzung erzeugte 30 zusätzliche Tokens. Lokal korrigiert und Regressionstest bestanden; End-to-end-Vergleich noch offen. | M/T · P02 |
| Cache / ongoing Chat | src/engine/metal/qwen.rs:5312, src/model_eval.rs:907 |
MTPLX AR wiederverwendete jedes Mal 5120 Tokens; MTP 5120/7840/8861. Vollständige History ist nicht gleich identischer Cache-Arbeit. | M · P03 |
| Laden / Warmup / Speicher | src/engine/qwen.rs:362, src/engine/metal/qwen.rs:409 |
Volle Kontextpuffer, andere Aktivierungs-Speichertypen; Referenz mit MTP-Kopf und Background-Warmup. | Q/O · P01, P09, P15 |
| Command-Buffer-Scheduling | src/engine/metal/qwen.rs:844, native/metal/ds4_metal.m:11878 |
Qwen bei 100% ein CB über alle Prefill-Layer. MLX automatische asynchrone Commit-Grenzen nach Operationen/Bytes. | M/Q · P05 |
| PLE-Hash / Gather / SSD | src/engine/qwen.rs:224, src/engine/metal/qwen.rs:1024 |
Beide 16 Leser und nominell 1 GiB Hot Rows. MTPLX staged vor Graphaufbau, große Gathers umgehen Row-LRU; Rust liest bei Layer 1 und cached auch große Gathers. | T/Q · P10 |
| HC / Normalisierung | src/engine/metal/qwen.rs:1247, metal/qwen38.metal |
MTPLX GatedResidual und hc_read_v3; Formgrenzen, Fusions- und Rundungsstellen nicht lückenlos durchgetestet. |
T/O · P09 |
| GDN Prefill / Decode / Verify | src/engine/metal/qwen.rs, encode_gdn_conv_norm_rows |
Große Conv/Norm-Prefills nun zeilenparallel mit referenzgleichen BF16-Grenzen; modellfreier Boundary-Test exakt. Delta-Threadgeometrie und vollständige Layer-/State-Parität weiter offen. | T/M · P06 |
| Router / MoE / Shared Expert | src/engine/metal/qwen.rs:2738, :2826, :2919 |
Rust sortiert ab S=5, MTPLX bei ≥64 Routen (bei top-10 ab S=7). Rust Prefill gate/up getrennt, aktive MTPLX-Fusionsklasse gemeinsam. | Q/T · P07 |
| QSA / KV / FlashAttention | src/engine/metal/qwen.rs:2134, :2551 |
Rust baut dichte KV-Stagingansichten erneut auf; F16-Flash-Staging versus BF16-Referenzpfad. Sparse-Grenzen und tatsächliche Kernel prüfen. | Q/T · P08 |
| QMV / QMM / Quantisierung | src/engine/metal/qwen.rs:3178, metal/qwen38.metal |
Frühere logische Output-Länge/BF16-Rundung korrigiert. Golden-Test gilt für geprüfte Formen, nicht alle Matmuls. | T · P09 |
| MTP Draft / Verteilung | src/engine/metal/qwen.rs:4428, :4894 |
Rust D3 fest, Referenz unterstützt D1..D5 (Default D3); Rust berechnet Target-Verteilungen für gesamten Verify-Block, MTPLX lazy entlang Acceptance-Pfad. | Q · P11 |
| MTP Commit / Repair / EOS | src/engine/metal/qwen.rs:4735 |
Rust kann gesamten Kontext scalar replayen; Referenz captured-prefix commit / begrenzte Repair-Pfade. Pending-/EOS-/Cancel-Zustände vollständig prüfen. | Q/T · P12 |
| DeepSeek DSpark | src/settings.rs, src/engine/metal.rs |
Default Confidence war 0,8 statt DS4 Metal 0,6. Jetzt lokal korrigiert, einschließlich temperaturabhängigem Exact-Default; End-to-end-Messung offen. | Q/T · P13 |
| GLM MTP | src/engine/metal/glm.rs:1788, src/engine/metal.rs:4531 |
Rust akzeptiert über einzelne Target-Forwards, DS4 verifiziert kompatibles Paar im 2-Row-Batch. Sampled Dispatch ist opportunistisch, nicht exact. | Q · P14 |
| DS/GLM Prefill / Power | src/engine/metal.rs:3910, src/engine/metal/glm.rs:4596 |
DS4 hat echte Keepalive-Commit-Grenzen; GLM-Rust Flush hängt an read_logits && rows>8, Referenz zusätzlich an Progress-/Stage-/Kontextbedingungen. |
Q/O · P15 |
| Metriken / Abschluss | src/model_eval.rs:327, src/app.rs:1354, native/metal/ds4_metal.m:1041 |
Gleiche native Probe, andere Host-Einbettung. Verifier-Zeit überlappt Repair; Prefill-Zähler nicht referenzgleich; Canary/Profiling können Messung verändern. | M/Q · P04, P16 |
Priorisierte Tasks
Für Qwen ist eine Abweichung von der geforderten Kernel-/Funktionsidentität ein offener Portierungsbestandteil, unabhängig vom isolierten Geschwindigkeitswert. Kein Task wird allein durch einen plausiblen Textoutput oder einen einzelnen schnelleren Lauf geschlossen.
P01 — Reproduzierbare Ausgangslage sichern
Priorität P0; keine Abhängigkeit; teilweise gesichert, neue Messbaseline offen.
Referenz-Warmup-Abnahme präzisiert (2026-09-06): Der bestehende MTPLX-Runner
wartet nun nach /health.ok zusätzlich auf warmup.background.state == done
und verwirft fehlgeschlagene/abgebrochene Schritte, bevor er den separaten
Chat-Warmup einreicht. Zuvor zeigte das archivierte Ready-Receipt noch einen
laufenden512er Schritt und einen ausstehenden2560er Schritt. Ein sofortiger
Foreground-Prompt kann diese laut gepinntem Servercode unterbrechen und später
fortsetzen lassen. Keine Veränderung am MTPLX-Server oder dessen Warmup-Defaults;
Probe und Fortschritts-/Speicherwatchdog laufen während der gesamten Wartephase.
Der neue Abschlussbeleg erfasst die vollständige Health-Antwort. Pending/Done/
Fehlerzustände wurden modellfrei geprüft; neue echte Läufe unter
local-eval-results/20260906-qmm-k-tile/. Unterschiedliche Warmup-Arbeit zwischen
Produkt und Referenz bleibt zu dokumentieren, nicht als identisch ausgeben.
-
Fortschritt: Erfolgreiche Qwen-Referenzbelege, Runner/Canary sowie aktueller Kern-Quellstand und vorhandenes Release-Binary archiviert. Hashes und Einschränkungen stehen im Snapshot-Manifest. Der SHA256 des Binary wurde auch aus dem Archiv erneut verifiziert. Quellstand und altes Binary sind ausdrücklich nicht als passender Build ausgegeben. Originaldateien unverändert; lokale Ergebnisarchive sind von Git ausgeschlossen.
-
Vorhandene gültige JSONL-Receipts, Runner und Eingaben dauerhaft unter einem lokalen Ergebnisverzeichnis sichern; ungültige Läufe eindeutig ausschließen.
-
Binary-/Kernel-/Source-Diff- und Artefaktidentitäten, Hardware/GPU-Cores, Modellparameter, effektive Flags, MTP-Vertragsdaten, Fan-/Thermalzustand festhalten. Keine erneuten Modell-Downloads oder unnötigen vollständigen Artefakt-Reads während einer Kaltstartmessung.
-
Abnahme: Ein zweiter Lauf kann aus dem Manifest dieselben effektiven Bedingungen herstellen. Background-Warmup ist beendet oder ausdrücklich Teil der Kaltmessung. Keine Leistungsbehauptung anhand wechselnder ungehashter Arbeitsstände.
P02 — Identische Texte, Tokens und toolfreier Produktpfad
Priorität P0; nach P01; teilweise korrigiert.
Plain-Chat-Konfiguration umgesetzt (2026-09-05): Config::plain_chat gilt im
gemeinsamen UI-/Headless-Systempromptbuilder. Sie entfernt Tool-/Skill-/A2UI-Anteile
und den eingebauten Coding-Agent-Standardprompt, erhält aber einen benutzerdefinierten
Systemprompt unverändert. In der UI unterbindet sie außerdem Workspace-/Datums-
Injektionen, Hooks, Tool-Ausführung, automatische Antwortkorrekturen und Ersttitel.
Der UI-Default bleibt false; die Harness weist ihren Default --plain-chat on
im Start-Receipt aus. Vergleich nur mit einer frischen UI-Session unter
plain_chat: true. Bestehende Chats werden nicht bereinigt. --plain-chat off
ist weiterhin nur ein Prompt-/Inferenzdiagnosepfad, kein Headless-Agent-Executor.
Der gemeinsame Prompt-Test über alle Modelloptionen, CLI-Overrides und YAML-
Roundtrip bestehen. tools/qwen-chat-reference.py verwendet den tatsächlichen
MTPLX-Runtime-Tokenizer-Loader und Server-Encoder _encode_messages_uncached, nicht
einen nachgebauten Jinja-Aufruf. Drei vorbereitete Low-Turns (README-Summary,
Story, Python; mit fest vorgegebenen Assistant- und Reasoning-Inhalten) stimmen in
gerenderten Bytes und Token-IDs überein: 2489 / 2541 / 2609 Tokens.
Beleg: local-eval-results/20260905-qmm-loader/plain-chat-reference.json und
plain-chat-tokens-after.log (einschließlich History-plus-Checkpoint-Append);
der erste Direktversuch ohne den MTPLX-Tokenizer-
Wrapper scheiterte und ist kein Referenzbeleg. Es wurde kein Modell generiert.
Das ist kein Beweis für alle live erzeugten Historien oder für DS/GLM. P02 bleibt
bis zur entsprechenden Frontend-/Referenzabnahme offen; alte Agent-Prompt-
Performanceläufe dürfen nicht mit neuen Plain-Chat-Läufen vermischt werden.
Echte erzeugte Historien nachgeprüft (2026-09-05): Der Fixture-Exporter
akzeptiert nun --source-run. Für die abgeschlossenen Plain-Chat-AR- und
MTP-Rust-Läufe stimmen Rust-Vollrendering und der tatsächliche MTPLX-Server-Encoder
in Bytes/Token-IDs sowie re-encodierter History-plus-Continuation überein.
AR: 2617/3056/4242; MTP: 2617/3042/4030 Tokens; beide Release-Tests bestanden.
Die live fortgesetzten Rust-Checkpoints meldeten dagegen 2617/3054/4238 und
2617/3041/4028. Das ist noch kein Beleg für identische live Tokenfolgen: erhaltene
Generationstokens versus erneut gerenderte/encodierte History müssen an der
konkreten Grenze verglichen werden; nicht ungeprüft als BPE-Effekt abtun.
Beleg: local-eval-results/20260905-plain-reference/manifest.md.
Live-Request-Anbindung und reproduzierter Turn-Abschlussfehler (10.09.):
Der kanonische Drei-Turn-Test ruft nun LiveSession::generate mit tatsächlichen
ChatTurn-Nachrichten und TurnSettings auf. Eingefrorene Prompt-IDs sind nur
noch Assertions, nicht die Eingabe an den Executor. Der Owner hält abgeschlossene
und Prefill-Snapshots getrennt; Abbruch vor/nach Streaming, Observer-Fehler und
Text-Stopp laufen durch diesen Owner. Ein CPU-Check prüft AR-/MTP-Übernahme von
Sampler, Seed und Kontext-/Ausgabelimit bei unveränderter Backend-Policy.
Der erste überwachte AR-Lauf scheiterte nach einer exakt referenzgleichen Summary
an Turn 2: Produktprompt 3410 statt 3411 Tokens, erste Differenz an Position 3383.
Der gespeicherte EOS-Token 248046 war vorhanden, der Template-Zeilenumbruch 198
vor dem nächsten User fehlte. Vorherige History-Append-Tests starteten mit erneut
gerenderter History, die diesen Zeilenumbruch bereits enthält. Sie deckten die
echte Decode-Grenze nicht ab. Der Fehlbeleg bleibt erhalten unter
local-eval-results/live-session-20260910.9RSmzd/ar.{stdout,stderr}.log.
engine::render_text_prompt vervollständigt nun ausschließlich bei einer
authentifizierten Qwen-Assistant-History den fehlenden Abschluss: unveränderte
vollständige Template-Grenze, Newline nach MTPLX-EOS oder EOS+Newline nach dem
skalaren Pre-EOS-Frontier. Generierte Tokens werden nicht neu gerendert und der
KV-Prefix bleibt erhalten. DS/GLM sind von dieser Verzweigung nicht betroffen.
Der Metadaten-Regressionstest prüft diese drei Frontiers und den Vollrender-Fallback
bei ungültigem Tag. Produktiver Controller-/Power-/Checkpoint-Anschluss und die
vollständige sechsstellige Performance-Abnahme bleiben offen; dies ist noch keine
Freigabe eines UI-Bundles.
Verifikation dieser Anbindung: Test-/Produktions-Clippy mit -D warnings,
Release-Testbuild, Format und Diffcheck bestanden. Finale Testbinary-SHA256:
d7705551bebd41c5568fef0f11d593d93fd76accda727f347b075079d3b89e70.
Logs: /tmp/ds4-live-session-{clippy,production-clippy,build}.log.
Die zwei Request-Checks und der erweiterte Metadaten-/Frontier-Test bestanden
unter Supervisor 2048 15 15. Vollmodell AR/MTP unter 81920 30 45, sequenziell,
SSD-Ngram, unveränderten Referenz-Flags, Chunk 2048, ohne Power-Drosselung,
Thinking Low und Seed 0; durchgängiger 100-ms-Canary mit 2-s-Abbruchgrenze.
Referenzen bleiben session-chat-20260910.jT3hf5/reference-{ar,mtp}-boundary.stdout.log.
Es wurden keine Referenztokens oder Assertions abgeschwächt.
Beide vollständigen Chats inklusive Owner-Abbruchprüfungen bestanden, ebenso
Prompt-/Output-Tokens, Reasoning/Text, Logits-/Hidden-Hashes, Boundary-Snapshots,
Cache-Fortsetzungen und MTP-Zyklen. AR Prompt/Cached/Output:
2748/0/635, 3411/3383/1347, 4791/4758/266; MTP:
2748/0/466, 3242/3214/1394, 4669/4636/326. Die tatsächlichen TurnSettings
(einschließlich f32-Samplerwerte) ändern diese Referenzergebnisse nicht.
AR: 583 Canary-Proben, keine Fehler/Stalls, Prefill-max 2,532 ms,
Decode-max 1,022 ms, Peak Physical 82.615.580.104 Bytes; Supervisor 62,241 s.
MTP: 562 Proben, keine Fehler/Stalls, Prefill-max 4,254 ms,
Decode-max 1,145 ms, Peak Physical 83.185.055.752 Bytes; Supervisor 58,907 s.
Rohdaten: local-eval-results/live-session-20260910.9RSmzd/,
{metadata,request-fixed,ar-fixed,mtp-fixed}.{stdout,stderr}.log.
Das sind Canary-beobachtete Funktionsregressionen, keine neue gepaarte Performance-
Abnahme und kein UI-Eventloop-Nachweis. Der Controller ist weiterhin cfg(test).
Nichtnull-min_p wird vom neuen Request-Adapter ausdrücklich abgelehnt, da der
MTPLX-Sampler diesen Filter nicht unterstützt; diese Produktoption ist damit
noch nicht integriert. EngineSettings-/Power-/Persistierungsanbindung bleibt offen.
- Qwen-Continuation-Fix bereits vorhanden: initialer Systemprompt nur bei
Vollrendering, nicht nochmals bei Checkpoint-Append. Regressionstest
engine::tokenizer::tests::qwen_checkpoint_continuation_matches_full_conversationist nach vorherigem Fehler bestanden. Noch kein frischer End-to-end-Nachweis. - Test-Konfiguration ohne Skill-/Tool-/A2UI-Anteile über denselben gemeinsamen Produkt-Promptbuilder herstellen, keine nur in der Harness geltende Nachbearbeitung. Effektive UI-Testkonfiguration und Harness-Konfiguration müssen übereinstimmen.
- Abnahme: Bytegleicher gerenderter Prompt und gleiche Token-IDs in UI-Headless und Referenz pro Turn, einschließlich Assistant-Reasoning, EOS und Template-Marker; keine Tools/Skills ausgeführt oder angeboten. Low bleibt modellgerecht.
- Kleinster vorhandener Check: mit installiertem
DS4SERVER_QWEN38_SOURCEcargo test --release engine::tokenizer::tests::qwen_checkpoint_continuation_matches_full_conversation -- --ignored --exact.
P03 — Cache-Arbeit und Chat-Fortsetzung aufklären
Priorität P0; nach P02; Ursache der AR-Referenz-Cache-Lücke reproduziert, vollständige Cache-/Zeitabnahme weiterhin offen.
Scope-Klarstellung des Nutzers (2026-09-10, maßgeblich für die Integration):
MTPLX ist für Qwens Modellausführung in Prefill/Decode, Kernel und Responsivität
die Referenz. Seine SSD-SessionBank samt CAS-Blobs, SQLite-Manifest, Writer-Queue
und Eviction muss nicht nachgebaut werden. Für die Persistierung ist auch das
bewährte DS4-Verfahren Referenz; die vorhandene Rust-KV-Verwaltung wird wiederverwendet.
Der in diesem Arbeitsschritt begonnene separate session_store.rs wurde vollständig
entfernt, bevor er ausgeführt oder produktiv angebunden wurde. Keine Benutzercaches
wurden verändert oder gelöscht.
Konkrete Integrationsgrenze im aktuellen Code:
src/engine/kvstore.rsverwaltet unabhängig vom Modellzustandslayout die Checkpoint-Dateien, Prefix-Schlüssel, Budget, Zugriffe und Eviction. Keine zweite Datenbank oder zweite Cache-Verwaltung für Qwen einführen.src/engine/metal/qwen.rs::save_checkpoint/load_checkpointimplementiert bereits den dateibasierten Persistierungspfad mit begrenzten IO-Chunks und Veröffentlichung nachsync_all/Rename. Das alte FP32-Scratch-Layout ist jedoch kein gültiger Ersatz für die BF16-/Recurrent-/QSA-/MTP-Zustände des neuen Executors.qwen_mtplx/session_cache.rs::SessionSnapshotund der vorhandene Tensorcodec bleiben für die korrekte Zustandsübergabe nutzbar; sie erfordern keine MTPLX- Speicherverwaltung. Ein Restore muss dieselben Folgetokens und Zustandsfrontiers liefern, ohne zusätzliche Voll-Prefills oder Präzisionskonvertierung im Decode.- Priorität hat die produktive Anbindung von
Execution::generate_textals vollständigem Turn an den gemeinsamen UI-/Harness-Pfad. Eine bytekompatible MTPLX-SSD-Datenbank ist dafür ausdrücklich keine Voraussetzung mehr.
AR-Auswahlfehler belegt (2026-09-05): Ein erneuter vollständiger MTPLX-Lauf
mit MTPLX_DEBUG_PREFIX_DIVERGENCE=1 reproduziert 5120 gecachte Tokens in allen
drei Antworten. Inhalt, Reasoning, Finish-Reason und Usage stimmen vollständig
mit dem alten AR-Lauf überein. Alle Antworten enden mit stop, Supervisor exit 0,
Peak-Footprint 83.78 GB unter der 116.82-GB-Grenze; kein zweiter Inferenzprozess.
Die konkrete Kette ist jetzt belegt:
generate_arsucht untermtp_history_policy="cycle"; der Server speichert den finalen Generation-Snapshot unter"committed".SessionBank.restorewählt zuerst den längsten exakten Prefix (bei Story 7836 Tokens), lehnt dessen Policy ab und versucht keinen kürzeren passenden exakten Eintrag (vorheriger Prefill: 7460 Tokens).- Der Near-Prefix-Fallback lehnt beide exakten Einträge ab, weil
matched >= entry.prefix_lengilt (matched_out_of_range). - Erst der teilweise passende Warmup-Eintrag wird an Recurrent-Grenze 5120 restauriert. Dasselbe tritt beim Python-Turn mit 8643/7896 Tokens auf.
Die Debug-Ausgabe bestätigt clean prefix und die Präsenz der größeren
Kandidaten. Fehlende Session-IDs, fehlgeschlagene Speicherung, Token-Drift oder
Eviction dieser Kandidaten erklären diesen Befund nicht.
tools/mtplx-cache-reference.py reproduziert die Auswahl mit echten MTPLX-
Funktionen und leeren Cache-Payloads. Kontrollfall: Nur den inkompatiblen längsten
Eintrag entfernen; der unveränderte Exact-Restore nutzt dann den gültigen
7460-Token-Prefix. Kein Modell- oder State-Paritätsbeweis durch diesen Kontrolltest.
Belege und Identitäten: Cache-Diagnosemanifest. Der Golden Master bleibt unverändert. Diese zusätzliche Referenzarbeit wird nicht zur künstlichen Verlangsamung in Rust nachgebaut. Die alten Agent-Prompt-Läufe sind keine Matched-Work-/2%-Abnahme und dürfen nicht mit der neuen Plain-Chat- Baseline vermischt werden. Rest: Save/Restore/Commit-Zeiten und tatsächlich neue Tokens in der neuen laufenden Chat-Matrix, einschließlich MTP, erfassen.
- MTPLX
generate_ar/generate_mtpk,restore_or_prefillund Server-SessionBank gegenEngine-Checkpoint-Tag, Save/Restore und Pending-Token-Finalisierung verfolgen. Die oben belegte AR-Referenz-Auswahlgrenze in Messungen ausdrücklich ausweisen. - Produktlauf bleibt ein ongoing Chat. Cache-Strategie nicht heimlich verändern, um gleiche Zeiten zu erzeugen. Zusätzlicher Matched-Work-Test mit identischem Prefix/Suffix darf die Engine-Kosten isolieren, ersetzt aber nicht den Produktlauf.
- Abnahme: Für alle drei Turns vollständige Tokens/Reasoning/Cache-Frontiers, tatsächlich neu berechnete Tokens sowie Save/Restore-Zeiten; kein unerklärtes Re-Prefill, kein vorzeitiges Ende. Warmup gehört nicht zur Chat-History.
P04 — Messvertrag für Responsiveness und Zeitanteile vereinheitlichen
Priorität P0; nach P01; Lade-/Canary-Phasenzuordnung korrigiert und im Produkt-Runtime-Kontrolllauf geprüft; Gesamt-Messvertrag weiter offen.
- Native Canary-Scheduling/Completion, Host-Timer-Verzögerung und echte
UI-Eventloop-Verzögerung getrennt ausweisen. Die Engine läuft bereits auf einem
eigenen Thread (
src/runtime.rs:108); ein weiterer Thread beweist keine GPU-Fairness. - Harness-Thread und UI-
Task::performbenutzen zwar dieselbe native Probe, aber unterschiedliche Scheduling-Umgebungen. Blocking Probe nicht als kooperatives async-Warten interpretieren. Headless misst ohne GUI keinen tatsächlichen Beachball. - Ganze Lebensdauer: Start, Laden, Warmup, Restore, Prefill, erster Token, Decode, Save, Abschluss. Phase bei Probe-Start und -Ende erfassen; p50/p95/p99/max, Samplezahl, In-flight-Alter und Fehler. Fortschritt nur durch echte Modellarbeit.
run_warmupstartet vorservice.generateund umfasst damit auch das erstmalige Modellladen.warmup_result.elapsed_msund separat gemeldete Ladezeit dürfen nicht addiert werden. Der Loading-Event wird jetzt ausgewertet; der gemeinsame Runtime-EventLoadedmeldet dieselbe Ladedauer wie die UI-Metriken. Das neuetimingtrennt Ladezeit und restliche Request-Zeit, ohne letztere als reine Rechenzeit auszugeben. Nicht verfügbare Ladedauer bleibtnull.- Prefill-tok/s = neue Tokens / entsprechende Prefill-Zeit. TTFT und Gesamtzeit
separat. Draft, Verify, Acceptance, Commit und Repair dürfen sich im additiven
Zeitbudget nicht überlappen (
note_mtp_verificationumfasst momentan auch Repair). - Abnahme: Identischer kleiner Kontrolllauf in UI/Headless mit gleichen nativen Messgrößen; künstlicher Host-Stall und GPU-Stall werden unterscheidbar erkannt. Canary an/aus A/B quantifiziert Messkosten; optional bleibt sie in der UI.
Teilnachweis Phasenzuordnung (2026-09-05): Release-CLI neu gebaut, zehn
model_eval::tests bestanden. Ein überwachter Qwen-Plain-Chat-Kontrolllauf bei
100%, Chunk 2048, Low, MTP aus und Canary an endet natürlich mit pong (mit
führenden Leerzeilen), Supervisor exit 0. Warmup gesamt 12785 ms, davon 8258 ms
Modellladen und 4526 ms übrige Request-Zeit (separate Abrundung auf Millisekunden).
140 erfolgreiche Canary-Proben, davon 80 während Loading; eine Probe überschreitet
eine Phasengrenze und behält beide Phasen. Zeitstempelreihenfolge, Phasenzahlen,
Zeitzerlegung, Ausgabe, Stop und Speichergrenze wurden per Assertions geprüft.
Maximale Canary-Completion 3,604 ms; kein erkannter Stall in diesem kurzen Lauf.
Startphase bleibt die explizite Zuordnung für Per-Phase-Statistiken; Abschluss-
und Beobachtungszeit werden nicht mehr verwechselt.
Beleg: local-eval-results/20260905-phase-attribution/manifest.md. Frischer
Inferenzprozess, keine Behauptung eines kalten OS-Dateicaches. Der gemessene
pong-Turn folgt dem separaten Warmup: keine Reproduktion des kalten UI-Pings,
kein GUI-Eventloop-Nachweis und keine Referenz-/2%-Abnahme. Release-Bundle nicht
neu gebaut. Restore/Save-Granularität, überlappende MTP-Zeitanteile und die
übrigen oben genannten P04-Abnahmekriterien bleiben offen.
Der Kontrolllauf belegte auch eine weitere Zeitgrenzen-Lücke: letzter
Decode-Progress bei 1294 ms, Request-Ende bei 1603 ms. timing.decode_ms=670
umfasst diese nachlaufenden 309 ms, während die UI-/Runtime-Rate 49,807 tok/s
aus dem letzten Token-Progress stammt (src/engine.rs, generation_started).
write_result beendete die Decode-Zeit erst am Finished-Event, das nach
Checkpoint-Arbeit gesendet wird. Die 309 ms sind nicht vollständig als
Save-Zeit belegt; EOS/Finalisierung/Checkpoint/Host-Zustellung müssen durch echte
Runtime-Grenzen getrennt werden, nicht aus dem letzten Token geschätzt werden.
Decode-Grenze korrigiert (2026-09-05): Ein lokaler Timer im gemeinsamen
Generator::generate_inner umfasst den Decode-Loop einschließlich Sampling,
Token-/Stop-Verarbeitung und Output-Callbacks. Er endet bei jedem Rückkehrpfad,
auch Fehler/Cancel/Stop innerhalb eines spekulativen Zyklus, vor nachgelagerter
Pending-Token-Finalisierung und Checkpoint-Arbeit. Keine Kernel-/Sampling-Änderung.
MetricsSnapshot.decode_duration_ns ist dieselbe Quelle für die neue Stats-Zeile
und Harness-timing.decode_ms. Die bisherige Host-Zeitspanne bleibt ausdrücklich
als decode_to_request_end_ms erhalten; historische decode_ms-Werte hatten
noch diese alte Semantik. decode_loop_tokens_per_second verwendet die ganze
Loop-Dauer, decode_tokens_per_second weiterhin den letzten UI-Progress-Wert.
checkpoint_io gibt vorhandene gemeinsame Zähler und letzte I/O-Dauern aus;
letzte Dauer wird nicht als Summe mehrerer Operationen ausgegeben.
Vier Metrics-Tests und zehn Harness-Tests bestanden; der neue Regressionstest prüft Fehler-Rückkehr, Ausschluss nachfolgender I/O und Reset zwischen Requests. Die zeitliche Canary-Zuordnung der nachgelagerten Finalisierung ist dadurch noch nicht korrigiert: ein Loop-Zeitwert ersetzt kein Live-Phasenereignis.
Vollständiger Qwen-Kontrollchat AR/MTP: Summary des eingefrorenen README,
Story, Python nacheinander als ein Chat, jeweils separater Warmup; 100%, Chunk
2048, Low, Canary an. Alle sechs Antworten natürlich abgeschlossen, 1/3/5
History-Nachrichten bestätigt, beide Python-Ausgaben bestehen neun Funktionsfälle.
Checkpoint-Schreiben pro Turn 341/377/376 ms (AR), 379/474/464 ms (MTP).
Gemeinsame Loop-Rate und letzte UI-Progress-Rate weichen pro Turn um weniger
als 0,05% voneinander ab; kein MTPLX-Paritätsnachweis durch diese interne Prüfung.
Loop-tok/s: AR 48,916/48,367/48,495; MTP 53,976/38,874/61,596.
Die Story bleibt mit MTP langsamer; Draft-Akzeptanz dort 479/1308 gegenüber
79/98 bei Python. Unterschiedliche gesampelte Texte/History und aktive Canary:
keine saubere Performance-A/B-Abnahme, aber die Timing-Korrektur beseitigt diesen
beobachteten MTP-Rückstand nicht. Canary max AR 102,483 ms / MTP 84,761 ms,
keine Fehler; kein GUI-Eventloop-Nachweis. Beide Supervisor exit 0, keine
verbleibenden Modellprozesse. Rohdaten, Hashes, Zeitzerlegung und Grenzen:
local-eval-results/20260905-decode-boundary/manifest.md.
Zusatzbefund 2026-09-05: Der vorhandene DS4SERVER_QWEN38_PREFILL_PROFILE=1
beendet/wartet jeden Layer separat und ist kein transparenter Profiler.
Vollständiger AR-Chat mit 100% / 2048 / Low und identischen Prompts: Summary-Prefill
21,500 s statt 5,291 s im normalen Lauf; ein anschließender normaler Kontrolllauf
wieder 5,257 s. Alle drei Antworten inklusive Reasoning und Tokenzahlen sind in
allen drei Läufen exakt gleich. Profiling-Gesamtprozess 91,115 s statt 60,579 s;
alle Turns trotzdem regulär beendet. Die Layerzeiten dürfen daher nicht als
Kostenverteilung des normalen Produktpfads ausgegeben werden. Einzelne Diagnose-
Layer dauern >1 s, obwohl das größte GPU-Command-Buffer-Intervall im Summary nur
263,579 ms beträgt: GPU-Zeit und zusätzliche Host-/Submission-Kosten trennen.
Die genaue zusätzliche Kostenursache ist noch offen; keine unbewiesene Zuschreibung
an Kernel, Cache-Eviction oder thermische Drosselung.
Apples installiertes xctrace bietet Metal System Trace. Eine gezielte
Aufzeichnung mit dem normalen Qwen-Worker als Attach-Ziel (nicht --all-processes)
wurde gestartet und beim Prozessende automatisch gestoppt. Der Export bestätigt
allerdings nur 18,114 s am Laufende: der große Summary-Prefill fehlt. Im
PID-gefilterten Ausschnitt liegen 871 GPU-Compute-Intervalle der Ebene 0 vor,
zusammen 12,959 s und maximal 35,604 ms. Das sind Ausführungsintervalle, keine
einzelnen Kernelzeiten; Shader Timeline ist im Standardtemplate deaktiviert.
Somit noch kein Prefill-Ursachenbeweis. Native Traces müssen früher starten.
Instruments erfasst trotz Attach auch System-/Prozessmetadaten; Rohtrace und
Umgebungsdaten bleiben lokal und werden nicht veröffentlicht. Das Tool benötigt für
seinen Instruments-Cache Rechte außerhalb der Workspace-Sandbox; der erfolgreiche
Start nach Freigabe ist kein Produktfehler. Diagnosebelege unter
local-eval-results/20260905-gdn-delta/qwen-layer-profile.* und qwen-metal-trace.*.
Die anschließende frühe Aufzeichnung qwen-metal-early.trace erfasst 56,838 s
inklusive des großen Summary-Prefills. Produktparameter unverändert, keine Layer-
Profiling-Flags. Der vollständige Chat endet mit denselben Antworten und Tokenzahlen
wie zuvor. Summary-Prefill 5,289 s, Prozess 63,728 s; Canary-Prefill-Maximum 119,609 ms.
tools/metal-trace-summary.py wertet die exportierten XML-Daten inkrementell und
PID-gefiltert aus; referenzierte Werte, fremde PIDs, verschachtelte Intervalle und
überlappende Intervalle sind im integrierten Self-Test geprüft.
Der große Summary-Buffer 29116535429 spannt im Trace 3848,372 ms auf, davon
3831,767 ms überschneidungsbereinigte GPU-Ausführung (234 Intervalle, längstes
85,788 ms). Das deckt sich mit dem nativen Harness-Maximum von 3848,390 ms.
Der nachfolgende Prefill-Buffer enthält weitere 1273,938 ms GPU-Ausführung. Somit
ist dieser Prefill-Rückstand hauptsächlich GPU-Arbeit, kein gleich langer
CPU-Eventloop-Stall. Das identifiziert noch keinen einzelnen langsamen Shader.
Gesamtes Trace-Maximum der GPU-Compute-Intervalle: 117,702 ms; kein Shader-Timeline-
Profil und keine pauschale UI-Freigabe.
Die rohe Instruments-Aufzeichnung belegt ca. 2,7 GiB; die Nachverarbeitung brauchte mehrere Minuten und zwischenzeitlich ca. 16 GiB RSS. Deshalb ausschließlich optionale Einzel-Diagnose, nicht Teil jedes Harness-Laufs. Rohtrace/TOC bleiben wegen enthaltenen System-/Prozessmetadaten lokal. Zusammenfassung: metal-early-summary.json.
P05 — Qwen-Submission-Grenzen am aktiven MTPLX-Pfad ausrichten
Priorität P0; nach P02, P04; Produktionsintegration und Abnahme weiter offen. Der kanonische Test-Port enthält Encoder-/Taskgrenzen, Streams, Events/Fences und jetzt den gemeinsamen Eval-/Async-Eval-Kontrollfluss einschließlich Abschluss und Fehler-Cleanup, leere materialisierte Daten/Null-Bindings und gemeinsame Array-Ownership anstelle einer externen Materialisierungsliste sowie typisierte Shapes vor der Auswertung sowie geteilte Slice-/Broadcast-/Transpose- Views mit Byte-Offsets bis zur Metal-/Fast-Fence-Bindung sowie Reshape mit geteiltem Backing oder Original-General-Copy sowie AsType-/Dtype-View-Backends mit referenzierten Donation-/Layout-Regeln. Lazy-Array-Konstruktoren und graph-eigene Payloads einschließlich normalisierter Slice-/Contiguous-Knoten führen diese Operationen ohne externe Fixture-Zuordnung aus; RMSNorm und der installierte BF16-Affine-Linear-Pfad sind jetzt mit normalen Input-/Gewicht-Graphkanten angeschlossen. Dessen Layout-/Offset-Pfade verwenden denselben originalen QMV/QMM/Split-K-Dispatcher wie die Modul-Fixtures. Die Unary-Payloads Negative/Square/Exp/Sigmoid/Tanh/Sqrt/Rsqrt übernehmen ebenfalls die originalen Layout-/Donation-/Dispatch-Regeln. Binäre Add/Subtract/Multiply/Divide/Maximum/Minimum/LogAddExp-Payloads samt Broadcasting und gemeinsamer vollständiger Dtype-Promotion sind angeschlossen. Shared-Expert-MLP ist als zusammenhängender Graph mit echter Split- Geschwisteroperation, erfasster compiled SiLU und Down-Projektion verbunden. Vollständige QSA-/Modelloperationen fehlen weiter. Prüfstände stehen in den jeweiligen Abschnitten; frühere Messungen sind dort nicht ersetzt. Weitere Array-Operationen/Promotion, Modellprimitive und vollständige Modellanbindung fehlen noch; P05 ist deshalb nicht abgeschlossen. P06 verändert auch Encoder-Grenzen; Canary-Messungen allein sind kein isolierter Scheduling-Beweis. Details im Abschnitt zum gemeinsamen Eval-/Async-Eval-Ablauf.
Encoder-Zählerdiagnose (2026-09-06): Optionaler nativer Timestamp-Profiler an
bestehenden Encoder-Grenzen, ohne neue CBs/Flushes/Waits. Der vollständige Qwen-MTP-
Chat bleibt text-/token-/acceptance-identisch. 588 Vierzeilen-CBs mit 22.932
vollständigen Encoder-Spans decken 99,708% ihrer GPU-Zeit ab. Gemischte Layer-Spans
(37/83 Qwen-Dispatches) tragen etwa 88% der instrumentierten Zeit; das isoliert
keinen einzelnen Kernel. Die Zähler verändern die Performance erheblich:
Decode 28,684/14,887/21,614 statt zuvor 57,166/37,921/52,799 tok/s. Daher keine
normalen Kernelkosten oder Referenzparität aus diesem Lauf ableiten. Canary-Max
141,889 ms, kein echter GUI-Eventloop-Nachweis. Messkosten und verbleibende
Submission-/Kernel-Ursachen bleiben offen. Vollständige Belege und Prüfkommandos:
local-eval-results/20260905-verifier-stage-counters/manifest.md.
- MTPLXs gepinnte Runtime: device.cpp
needs_commit/commitund eval.cpp gegenCommands, generischen Qwen-Dispatcher, Copy-/Flash-/MTP-Pfade vergleichen. Max-Defaultsops > 50/(data_size >> 20) > 50sind Batching-Grenzen, keine Millisekundengarantie.data_sizezählt Elemente, nicht Bytes. - Asynchrone Submissions, Waits, tatsächliche Ressourcen-/Operationszählung, In-flight-Ressourcenlebensdauer und Scratch-Wiederverwendung gemeinsam behandeln. Weder blind pro Layer blockierend warten noch vorhandene Kapazitätsbytes als referenzierte Array-Elemente zählen. Einzelne lange Kernel bleiben P06–P09.
- Abnahme: Chunk 2048, Power 100, keine künstlichen Sleeps; identische Ergebnisse, native Completion-Verteilung im wiederholten Referenzbereich ohne Mehrsekunden- Ausreißer. Durchsatz darf nicht zur Bezahlung geringerer Latenz verschlechtert werden. Profiling an/aus darf Submission-Politik für die Vergleichsmessung nicht wechseln.
P06 — GDN-Prefill und Verifier vollständig abgleichen
Priorität P0; nach P02, P04; Conv/Norm-Boundary korrigiert und gemessen, Gesamt-Task offen.
Graphstand 2026-09-07: Der gemeinsame GDN-Forward verbindet Fused-Step,
Fused-Conv/Verify, Conv1d-Fallback, Output-Fusion und Cache-Fortschreibung
mit den unveränderten MTPLX-Kerneln; alle 264 Forward-, 130 Staged- und
24 zusätzlichen Lifecycle-Receipts werden geprüft (siehe „Gemeinsamer
GDN-Forward, Output-Fusion und Cache-Fortschreibung“). Äußerer Modellablauf,
Maskenerzeugung, Cache-Batchoperationen, Capture-Commit/Repair und
Produktintegration bleiben offen. Die
historischen Detailbefunde unten beziehen sich auf den bisherigen Produktpfad;
der neue Graph ist weiterhin cfg(test) und P06 ist nicht abgeschlossen.
- MTPLX
models/qwen4_exp.py:388–664und installiertesmlx_lm/models/gated_delta.pygegengdn_rowsund die Metal-Kernelkernel_qwen_gdn_conv_norm_rows/kernel_qwen_gdn_delta_rowsvergleichen. - Ausgangsbefund: Rust Conv/Norm lief mit lediglich zehn 1024-Threadgruppen serial über alle Prefill-Zeilen; MTPLX nutzt diese Fusion nur für kleine Breiten, große Prefills nutzen Conv1d/Silu/L2 mit anderen Rundungsgrenzen. Die Delta-Rekurrenz selbst iteriert in beiden Implementierungen über Tokens; das allein ist kein Fehler.
- Delta: Rust 64 Threads/TG, 32 State-Werte pro Lane versus MLX 128 Threads/TG, vier State-Werte pro Lane. Registerdruck, Occupancy und Reduktionsreihenfolge messen.
- Abnahme: gleiche Eingaben/States für S=1,2,3,4,5,6,7,32,2048 einschließlich Chunk-Grenze; Conv-, q/k/v-, Delta- und Output-States gegen aktive Referenz. Einzelkernelzeit und komplette Layerzeit mit identischem Warmzustand vergleichen. Keine allgemeine Toleranzaufweitung, um abweichende Prefill-Rundung zu kaschieren.
P06-Teilnachweis: Conv/Norm, 2026-09-05
tools/qwen-gdn-reference.pyerzeugt ohne Modellladen mit der installierten MTPLX/MLX-Umgebung gleiche BF16-Eingaben, Gewichte und Conv-States. Kleine S verwenden den tatsächlichen MTPLX-Fused-Kernel; große S bilden die aktive Conv1d/SiLU/L2-Operatorfolge ab. Dies ist ein Boundary-Test, kein kompletter Modell- oder Delta-Referenzlauf.- Vorher: S=1..6 exakt; bei S=2048 2.383.531 q-, 2.381.323 k- und 6.185.718 v-Werte verschieden, maximale absolute Fehler 0,00024414063 / 0,00390625 / 0,0009765625. Auch S=7 und S=32 schlagen fehl. Conv-States schon vorher exakt.
- Korrektur: ab S>6 unabhängige Zeilen parallel dispatchen und die BF16-Grenzen nach Conv, SiLU, L2 und q-Skalierung erhalten. S<=6 bleibt unverändert. Wiederverwendung des vorhandenen GDN-Scratch-Tails für den neuen Conv-State; anschließender bestehender GPU-Copy verhindert In-place-Lese-/Schreibraces. Keine kleinere Chunk-Größe, Leistungsbegrenzung oder künstliche Pause.
- Nachher:
qwen_gdn_conv_norm_rows_matches_mtplxfür S=1,2,3,4,5,6,7,32,2048 mit null Abweichungen bei q/k/v und Conv-State, einschließlich In-place- State-Übernahme; unveränderte exakte Assertions. Wiederholung nach beiden Chats ebenfalls erfolgreich. Das ist keine Aussage über alle möglichen Eingangswerte. - Isolierte S=2048-Wall-Mediane, zehn Wiederholungen nach einem Warmup: vorher 1,935 ms, nachher zunächst 0,757 ms, MTPLX 1,513 ms. Eine spätere Rust-Wiederholung nach den Modellläufen liegt bei 1,543 ms. Host-/Graph-Overhead ist enthalten; erhebliche Streuung und nicht kontrollierter thermischer Zustand erlauben daraus keine belastbare 2%-Abnahme oder garantierten Beschleunigungsfaktor.
- Wichtig für P05:
Buffer::copy_from→ds4_gpu_tensor_copybeendet den aktiven Compute-Encoder und erzeugt einen Blit-Encoder im selben Command Buffer. Damit ändert die notwendige sichere State-Übernahme auch Scheduling-Grenzen. Die Canary-Verbesserung unten darf nicht allein dem schnelleren Conv-Kernel zugerechnet werden. Es wurde kein zusätzlicher Command-Buffer-Flush eingeführt. - Belege: Messmanifest, numerischer Wiederholungstest. Offen bleiben vollständige Layer-Outputs, gemeinsame Conv-/Delta-Chunk-States, Verifier-/Commit-State-Abgleich und die isolierte Scheduling-Ursache.
P06-Teilnachweis: Delta-Rekurrenz, 2026-09-05
Die andere Thread-Aufteilung ist kein belegter numerischer Fehler: der neue
modellfreie Test qwen_gdn_delta_rows_matches_mtplx vergleicht normalisierte,
deterministisch zufällige BF16-q/k-Eingaben, BF16-v/beta, FP32-g und einen
nichtleeren FP32-Startzustand mit dem tatsächlich verwendeten
mlx_lm.models.gated_delta.gated_delta_kernel. Der optionale MTPLX-Blocked-Prefill-
Patch ist im festgehaltenen Referenzlauf nicht aktiviert und wird nicht als
Golden Master untergeschoben.
- S=1,2,3,4,5,6,7,32,2048: Ausgaben und FP32-Endzustände bereits vor einer Kerneländerung exakt identisch. Die spätere Prüfung umfasst zusätzlich je zwei Teilchunks mit In-place-Zustandsfortsetzung (S=2048 → 1024+1024), ebenfalls exakt. Ganze und geteilte Ausführung werden jeweils gesondert geprüft.
- Produktionsdispatch für Prefill/Verify und Capture-Commit lediglich in den
gemeinsamen Helper
encode_gdn_delta_rowsextrahiert, damit der Test dieselben Parameter verwendet. Kernel, Geometrie und Mathematik bleiben unverändert. - Isolierter S=2048-Wall-Median: Rust 2,403 ms, Wiederholung 2,366 ms; MLX 3,382 ms. Das ist inklusive Host-Aufrufkosten, mit sichtbaren Startausreißern, und keine ganze Modell-Abnahme. Bei kleinen S liegen Aufrufkosten im Bereich von Zehntelmillisekunden; keine pauschale Aussage, jede Größe sei schneller.
- Die gemessene Rekurrenz liefert damit keinen Beleg für den mehrsekündigen Prefill-Rückstand. Kein Umbau auf die Referenzgeometrie allein wegen ihres anderen Layouts. Nächster Kostenabgleich: ganze Layer, insbesondere MoE sowie Submission-Grenzen (P05/P07), statt spekulativer Rekurrenz-Optimierung.
- Reproduktion:
tools/qwen-gdn-reference.py <Ausgabepfad> --delta; Rust-Test mitDS4SERVER_GDN_REFERENCE=<Ausgabepfad>und--release --ignored --exact. Rohbelege, abschließender Test. Noch kein vollständiger GDN-Layer-, Controls-, Fused-S1- oder MTP-Commit-Beweis.
Vollständige Qwen-Produktläufe nach der Korrektur
Je ein separater Warmup und anschließend Summary → Story → Python in einem Chat; 100%, Chunk 2048, Low, Kontext 131072, T=1, p=0,95, k=20, Seed 12345, Canary an. Systemprompt und drei rohe Prompts stimmen mit dem archivierten AR-Kontrolllauf überein. Die inzwischen korrigierte Tokenisierung reduziert den ersten Prompt von 7490 auf 7460 Tokens (wie MTPLX). Cache-Unterschiede bleiben offen (P03).
| Modus / Turn | Neue / cached Tokens | Output-Tokens | Prefill s / tok/s | Decode tok/s¹ | Nach-Prefill tok/s² | Gesamter Turn s | Draft-Akzeptanz |
|---|---|---|---|---|---|---|---|
| AR Summary | 2294 / 5166 | 464 | 5,291 / 433,6 | 47,46 | 45,62 | 15,604 | — |
| AR Story | 59 / 7924 | 861 | 0,812 / 72,7 | 47,04 | 45,93 | 19,557 | — |
| AR Python | 72 / 8844 | 91 | 0,858 / 83,9 | 47,50 | 37,89 | 3,260 | — |
| MTP Summary | 2294 / 5166 | 488 | 5,487 / 418,1 | 53,59 | 51,25 | 15,162 | 307/495 = 62,0% |
| MTP Story | 59 / 7949 | 640 | 0,832 / 70,9 | 40,20 | 38,92 | 17,280 | 350/869 = 40,3% |
| MTP Python | 72 / 8649 | 77 | 0,895 / 80,4 | 70,73 | 48,37 | 2,488 | 57/60 = 95,0% |
¹ Letzter Engine-Fortschrittswert; schließt nicht alle EOS-/Checkpoint-/Abschlusskosten ein.
² Completion-Tokens geteilt durch Harness-decode_ms bis zum Turn-Abschluss;
keine reine Kernel-/Steady-Decode-Zeit. P04 muss diese Grenzen explizit zerlegen.
Alle Output-Tokenzahlen umfassen auch Reasoning/Steuertokens.
| Vollständiger Lauf | AR | MTP |
|---|---|---|
| Prozess inkl. Load und Warmup | 60,579 s | 59,592 s |
| Laden / Warmup-Lifecycle inkl. Laden (nicht additiv) | 8,914 / 21,333 s | 9,406 / 24,020 s |
| Peak Physical Footprint | 84.360.337.288 B | 86.666.337.288 B |
| Canary Prefill p95 / max | 110,614 / 117,076 ms | 112,441 / 115,618 ms |
| Canary Decode p95 / max | 3,578 / 15,983 ms | 0,513 / 1,114 ms |
| Canary Maximum gesamte Laufzeit | 162,362 ms (Warmup) | 145,001 ms (Warmup) |
| Canary Samples / Fehler | 574 / 0 | 567 / 0 |
| Supervisor-Maximalverzögerung | 45 ms | 48 ms |
Beide Prozesse Exit 0; alle drei Turns finish_reason=stop. Keine Rückfragen,
beide Stories vollständig und kohärent. Summaries decken wesentliche README-Inhalte
ab; die MTP-Summary enthält allerdings einen falschen DS4-Link (github.com/ds4),
also keine pauschale Behauptung fehlerfreier Inhalte. Beide zuvor gelesenen Python-
Antworten bestehen elf kleine funktionale Fälle inklusive strikter Schwelle,
Duplikaten, leeren Listen und unveränderter Eingabeliste; ohne Tools/Netzwerkrechte.
Kein beobachteter >2-s-Canary-Stall in diesen beiden Läufen. Die maximale Prefill- Canary bleibt dennoch weit über der bereits gemessenen MTPLX-Referenz (AR 2,974 ms, MTP 0,550 ms). Mehrsekündige Command Buffer bestehen weiterhin (Summary AR 3,861 s, MTP 3,848 s); deren gesamte GPU-Laufzeit ist nicht gleich Canary-Blockierzeit. Kein Beleg für die Behebung aller UI-Beachballs und keine Sechs-Zellen-/2%-Abnahme. P02 (Skill-Metadaten im Systemprompt), P03/P04 und weitere GDN-/MTP-Pfade bleiben offen.
P07 — Router, sortierte MoE und Shared Expert
Priorität P1; offen wegen vollständiger Modellanbindung und Produktmigration. Die bisherigen verbundenen SparseMoeBlock-Belege betreffen die ältere Buffer-Ausführung mit fusionierten, getrennten und gemischten Expert-/Shared-Modulen sowie aktivierten Decode-/Verify-Flags, nicht den vollständigen kanonischen Arraygraph. Dessen GatherQMM und jetzt auch SwitchGLU, Routing, die zwei fused-MoE-CustomKernel- Knoten sowie der ganze SparseMoeBlock sind an den kanonischen Arraygraph angeschlossen (2026-09-09, siehe folgenden Nachweis). Decoder und äußerer Modellgraph und MTP-Head sind inzwischen verbunden; vollständige Compile-Fusion, Gewichts-/Serving-Anbindung und Produktionsmigration bleiben offen. Keine Produktabnahme.
Decoder-Verbindung 2026-09-09: qwen_mtplx/decoder.rs setzt
qwen4_exp.py:3741 (DecoderLayer) mit den bestehenden Arraygraph-Modulen um:
optional PLE plus Residual, Attention-Hyper-Connection, GDN beziehungsweise QSA,
BF16-Multiply/Reshape/Add, MLP-Hyper-Connection, SparseMoeBlock und erneutes
Multiply/Reshape/Add. GDN-, QSA- und PLE-Caches werden an ihre bestehenden
Implementierungen durchgereicht. Keine zusätzlichen Eval-/Wait-Grenzen,
keine neuen Kernel, keine Änderung von Power oder Prefill-Chunks.
Zwei gezielte Tests bestanden unter test-supervisor 2048 15 15:
- CPU-Graphprüfung: Residual behält BF16, getrennte Multiply-/Add-Knoten, Broadcast-Geometrie und ursprünglichen Hidden-Input; keine Auswertung.
- Verbundener GPU-Smoke: beide Attention-Typen jeweils ohne/mit PLE, pro Cache fortlaufend 17 Prefill-, 4 Verify- und 1 Decode-Zeile. Analytisch bekannte, von null verschiedene PLE-/QSA-Residualbeiträge werden bitgenau geprüft; GDN-State-, PLE-Conv-/History-Layouts und QSA-Frontier ebenfalls. Die künstlichen Gewichte verwenden zwei Experten und keinen QSA-Indexer. Dies ersetzt weder die vorhandenen nichttrivialen Komponenten-Referenzbelege noch einen vollständigen Decoder-/Modellvergleich gegen MTPLX.
Rohdaten: local-eval-results/decoder-graph-20260909.pL6JX4/ple.*.log.
Dieser ursprüngliche Decoder-Smoke allein deckt den äußeren Modellaufruf nicht ab.
Äußerer Modellgraph und Capture-Commit, 2026-09-09:
qwen_mtplx/model.rs verbindet nun die aufgerufenen Bausteine gemäß
qwen4_exp.py:3778–4134: dichte/quantisierte Embeddings, optionale übergebene
Embedding-Zeilen, SSM-Maske aus Padding/Lengths, erstes PLE-Staging vor der
Layerschleife, originales Tile, Decoder-Kette und finaler Mixer. Das letzte
Widened-Array bleibt für MTP erreichbar. emit_logits=false baut keinen Head;
logits_keep schneidet vor der Head-Projektion. Tied und untied Head verwenden
die vorhandenen Linear-Operationen.
Zusammenhängende GDN-Runs schließen PLE/QSA aus. Ein explizit falscher Wert
eines der beiden ursprünglichen Compile-Env-Aliase schlägt die AR-Lane-Freigabe.
S=1–4, keine SSM-Maske und vorhandener Cache sind die Eintrittsbedingungen;
fehlende Conv-/Delta-Zustände lassen den jeweiligen Run eager ausführen.
Der vorhandene Replay hält getrennte Traces nach Run, Capture und
Shape-/Dtype-Signatur; Zustandspaare und sechs Capture-Zeilen pro GDN werden
in Referenzreihenfolge zurückgeschrieben. Bereits ausgewertete Parameter
haben nach dem gemeinsamen Evaluator keine Primitive mehr und werden wie in
compile_replace als Konstanten gehalten, nicht als neue Projektionen gebaut.
Compile-Stand 2026-09-09: Die drei compile_simplify-Durchläufe und die
anschließende compile_fuse-Absenkung sind jetzt im Modell-Run-Pfad über
trace_compiled angeschlossen. Acht synthetische GDN-Run-Graphvarianten sind
inzwischen gegen tatsächliche MTPLX-Traces geprüft (siehe unten); der vollständige
Vergleich mit echten Gewichten und Dispatch-Sequenzen bleibt offen.
Der Pfad bleibt cfg(test); weder Serving-Integration noch
Performance-Parität sind damit behauptet.
Compile-Simplify 2026-09-09: qwen_mtplx/compile_graph.rs bildet den
DFS-/Parents-Graph und die drei CSE-Durchläufe aus dem gepinnten
mlx/compile.cpp:590–800 in Rust ab. Verfügbare Rang-0-Skalare werden über
Bits plus Dtype zusammengeführt. Äquivalente Primitive verlangen identische
geordnete Inputs und ursprüngliche Primitive-Parameter; identische Primitive-
Pointer werden wie in der Referenz ausdrücklich nicht zusammengelegt.
Frühere Tape-Position gewinnt, spätere globale Ausgaben bleiben geschützt,
Split-Siblings werden in kanonischer Reihenfolge zusammengeführt und die
High-Fanout-Gruppierung ab mehr als 100 Parent-Einträgen bleibt erhalten.
Neue Deskriptoren werden aufgebaut, ohne den eingefangenen Modellgraph oder
seine Gewichte zu mutieren. Der Modell-Run verwendet inzwischen trace_compiled;
bereits explizit abgesenkte QSA-Graphen verwenden weiterhin trace.
Slice und SliceUpdate behalten dafür zusätzlich ihre ursprünglichen Stop- Parameter im Primitive. Die GPU-Ausführung benötigt diese nicht, aber die Referenz-CSE vergleicht sie ausdrücklich: beispielsweise Stop=3 und Stop=4 bei Stride=2 sind trotz gleicher Werte keine äquivalenten Slice-Primitive. CustomKernel erbt in der Referenz die standardmäßig falsche Äquivalenz; gleiche Shadertexte allein lösen deshalb keine Zusammenlegung aus.
CPU-Graphprüfung bestanden: mehrstufige Zusammenlegung, geschützte Ausgaben,
Slice-Parameter, Split-Siblings, identische Primitive-Pointer und 110-facher
Fanout. Der angeschlossene Decoder-/Modell-/MTP-Smoke besteht weiterhin
beide Tests (local-eval-results/compile-graph-20260909.WCXIbS/model.*.log,
0,28 s, gesampelter Peak 313.705.264 Bytes), einzeln unter
test-supervisor 2048 15 15. Keine Modellgewichte geladen. Diese Prüfungen
ersetzen nicht den noch offenen vollständigen Compile-/Dispatch-Tracevergleich
gegen MTPLX und sind keine Durchsatzmessung.
Zusätzliche Skalarkonstanten-/Identitätsprüfung bestanden (simplify.*.log):
gleiche NaN-Bitmuster werden zusammengeführt, +0/-0, verschiedene Dtypes und
Rang-1-Einzelwerte nicht. CustomKernel-Äquivalenz bleibt falsch; ursprüngliche
Deskriptoren bleiben unverändert. Der abschließende verbundene Lauf am finalen
Build besteht erneut beide Tests (final-model.*.log, 0,27 s, gesampelter
Peak 313.492.296 Bytes). Release-Testbuild, warnings-denied Clippy, originale
Shader-Quellprüfung sowie Format-/Diffprüfung bestanden. Kein Bundle erstellt.
Compile-Fuse und dynamische Library-Verwaltung, 2026-09-09:
compile_graph.rs bildet die Fusionsgrenzen aus mlx/compile.cpp:805–1028
ab: Tiefe 11, Kandidatenlimit 24, Stream-Gleichheit, Schutz globaler Ausgaben
anderer Form, Mehrfachverbraucher und Broadcast-Splitting. Eine zweite DFS
ordnet Inputs, Zwischenwerte und mehrere Ausgaben. fused.rs erzeugt die
originalen Metal-Ausdrücke mit dem unveränderten gemeinsamen Funktor-Header.
Die Shadernamen werden umbenannt; die vollständigen 19 SiLU-Kernelkörper
stimmen nach ausschließlicher Symbolnormalisierung bytegenau mit dem gepinnten
Export überein. Der gemeinsame Compiled-Evaluator unterstützt eingebettete
Konstanten, Rang-0-Inputs und mehrere Ausgaben samt Referenz-Donation.
Verschachteltes SiLU, SwiGLU und compute_g legen bei Tracer-Eingaben ihren
Operationsgraph offen, statt bereits abgesenkte Compiled-Primitive einzusetzen
(mlx/compile.cpp:1136). Damit kann der äußere GDN-Run über diese Grenzen
hinweg nach den Referenzregeln fusionieren.
Der erste GPU-Test identifizierte eine Lücke der gemeinsamen Metal-Brücke:
eine dynamische Library hielt nur ihre zuerst erzeugte Pipeline erreichbar.
Beim Wechsel von contiguous zu strided fehlte die weitere Funktion.
ds4_gpu_mtplx_compile hält jetzt die Library mit allen ihren Funktionen;
ds4_gpu_mtplx_pipeline erzeugt die jeweils angefragte Pipeline verzögert.
Die anfängliche, eventuell ungenutzte Pipeline wird nicht vorab erzeugt.
Die Libraries werden mit dem Metal-Kontext freigegeben.
Eine weitere fehlgeschlagene Testassertion betraf die Test-Erwartung, nicht
die Engine: Die Referenz wählt den Compiled-Kernel vor der Ausgabe-Allokation
anhand von data_size (metal/compiled.cpp:384,419). Dieser Wert ist bei
frischen Array-Deskriptoren null. Deshalb muss auch bei 65536 logischen
Elementen zunächst _contiguous, nicht _contiguous_n, erwartet werden.
Der korrigierte Test prüft ausdrücklich den Nullwert, die gewählte Variante,
die vollständige Gridgröße und sämtliche Ausgabewerte; keine Änderung dieser
Referenz-Ausführungsreihenfolge.
Rohdaten: local-eval-results/compile-fusion-20260909.K2FLi8/.
Alle GPU-Läufe einzeln unter test-supervisor 2048 15 15, ohne Modellladen:
source.stdout.log: Konstantenschreibweise und alle 19 SiLU-Quellkörper bestanden; die beiden GPU-Tests bei diesem CPU-Aufruf ausdrücklich ignoriert.graph.*.log: drei Tests für Simplify, Konstantenidentität und Fusion bestanden; Mehrfachausgaben, Broadcast-Splitting, äußere Verbraucher, verschiedene Streams und Tiefengrenze geprüft.final-fusion.*.log: sechs SiLU-Layouts (Rang 1/4/8, positive/negative Strides), drei nichttrivialecompute_g-Fälle (1/4/17 Zeilen) und vier Mehrfachausgabe-/Skalarfälle (8/65536 Elemente, eingebettet/nicht eingebettet) bestanden. Je Fall eine fusionierte Dispatch; SiLU/GDN bitgleich mit den erfassten Originalkerneln, Mehrfachausgaben exakt zum arithmetischen Soll.silu.*.log: vorhandener Split-/SiLU-Layout-/Donationstest bestanden.qsa.*.log: alle 396 vorhandenen QSA-Compile-Referenzfälle bestanden.model.*.log: beide verbundenen Decoder-/Modell-/MTP-Tests bestanden, einschließlich Cache-Fortsetzung und Capture-Commit; 314.835.760 Bytes gesampelter Peak. Das bleibt ein synthetischer Modelltest.
Noch zu prüfen sind vollständige äußere GDN-Run-Traces mit echten Gewichten, die Referenz-Cacheäquivalenz der generierten Shader sowie verschachtelte Compile-Aufrufe mit ausschließlich partiell getraceten Eingaben. Die kurzen Funktionsprüfungen sind keine Messung der UI-Responsiveness oder des Modelldurchsatzes. Serving-/Generator-Verbindung und P16 bleiben offen.
Release-Testbuild, cargo clippy --offline --all-targets --all-features -j 1 -- -D warnings, originale Shader-Quellprüfung und Format-/Diffprüfung bestanden.
Cargo meldet weiterhin die bestehende Future-Incompatibility von block 0.1.6.
Keine Downloads, kein Bundle und kein Commit in diesem Arbeitsschritt.
Vollständige synthetische GDN-Run-Graphen und Ausgaben, 2026-09-09:
tools/mtplx-gdn-run-reference.py ruft die unveränderte ursprüngliche
Qwen4ExpTextModel._get_run_fn((0,), capture) auf. Reale GDN-/HC-Dimensionen,
zwei kleine MoE-Experten, synthetische Nullgewichte und Hidden=0,125; keine
Modellgewichte geladen. Acht Kombinationen: S=1/4, Capture aus/an und
HC-Fusion aus/an. Referenzmodell ausdrücklich eval(), Zustände zwischen
HC-Profilen zurückgesetzt und Compile-Cache beim Flagwechsel geleert.
Der vorhandene externe Wächter unterstützt dafür zusätzlich
test-supervisor MEMORY_MIB START_SECONDS IDLE_SECONDS --command EXECUTABLE ARGS....
Er startet den Referenz-Pythonprozess direkt, nicht Cargo oder eine Shell.
Direkte Worker-Argumente werden unverändert übergeben; im Rust-Testmodus bleiben
die bisherigen Testargumente erhalten. Die zwei CPU-Selbsttests prüfen beide
Aufrufarten sowie Speicher-/Start-/Fortsetzungsabbruch und Fehlerbehandlung.
Speichertelemetrie gilt weiterhin nur für den direkten Worker, nicht einen
beliebigen Prozessbaum. Alle nachstehenden GPU-Läufe einzeln mit 2048 MiB und
15 Sekunden Start-/Fortsetzungsgrenze, ohne Gesamtzeitlimit.
Rohdaten: local-eval-results/gdn-run-20260909.xTGA2h/.
reference.jsonl ist kein gültiger Inferenzbeleg: beim ersten Export fehlte
model.eval(), wodurch der Training-Rekurrenzpfad gewählt wurde.
hyper-profiles.jsonl enthält die acht gültigen Original-Inferenzbelege;
tests/fixtures/mtplx-gdn-runs.jsonl hält deren Formen, Ausgabe-Hashes und
Graphverträge ohne die umfangreichen DOT-Texte.
Der Vergleich identifizierte zusammenhängend folgende Abweichungen:
- GDN-Q-Skalierung und HC-Inject: Python
scalar * arrayläuft durcharray.cpp:631::__rmul__und erzeugtmultiply(array, scalar). Rust hatte Scalar zuerst. Gleiche Arithmetik, aber andere Broadcast-/Fusionsreihenfolge. Beide Aufrufstellen sind korrigiert; andere Scalar-first-Operationen wie C++-isclose, Reverse-Power und Reverse-Divide bleiben referenzgerecht. - Nichtfusioniertes HC: die Matmul-Factory erzeugte
Reshapestatt der ursprünglichen PrimitiveFlattenundUnflatten(ops.cpp:3515,3533). Beide Identitäten samt CSE-Parametern sind jetzt erhalten. Wie im Original benutzen beide denselben Reshape-View-/Copy-Evaluator, keine neuen Kernel. - Der Graphvertrag unterscheidet nun auch
BroadcastundAsTypeinnerhalb von Compiled-Namen. Die Emitterschreibweise bleibt unverändert; eine Normalisierung, die diese Unterschiede verstecken würde, findet nicht statt.
Ergebnisse am korrigierten Build:
final.*.log: beide verbundenen Decoder-/Modelltests bestanden; alle acht ursprünglichen GDN-Graphvarianten stimmen überein. HC-fusioniert 60–70, unfusioniert 97–107 Primitive, je 3 oder 9 Ausgaben.numeric.*.log: derselbe Test zusätzlich mit allen Hidden-/Conv-/Delta- und sechs Capture-Ausgaben pro Capture-Fall. Formen und Float32-SHA256 bytegenau zur Referenz, beide Tests bestanden (0,35 s Testzeit, 315.458.424 Bytes gemessener Peak-Footprint). Der zusätzliche wiederholte Ein-Zeilen-Aufruf prüft auch Fortsetzung nach Capture.dense.*.log: 114 Matmul-Fixtures in jeweils beiden Prepare-Modi bestanden, Peak 203.277.080 Bytes.compiled.*.log: vier Tests bestanden, darunter alle 396 QSA-Compile-Fälle, nichttriviale GDN-/SiLU-Fusion und 19 ursprüngliche SiLU-Quellkörper; Peak 282.493.816 Bytes. Warnings-denied Clippy und originale Shaderprüfung ebenfalls bestanden.
Grenze des Graphvertrags: er vergleicht Primitive-Namen, geordnete Abhängigkeiten und Ausgabe-/Siblingpositionen; konstante Blätter gehen nicht mit ihren Bytes ein. Die zusätzlichen Ausgabe-Hashes schließen diese konkrete numerische Fixture, nicht beliebige Gewichte oder alle Shaderparameter ab. Die Nullgewichte ersetzen keine Modellinferenz und diese Zeiten sind keine Durchsatzbelege. Vollständige echte Gewichtsbindung, Generator-/Serving-Anschluss, verbleibende Compile-Cache-/Partial-Tracer-Abweichungen und die sechs P16-Messzellen bleiben offen. Kein Bundle und kein Commit, keine 2%-Paritätsfreigabe.
Gewichtsbindung: Shard-Loader und alle drei Vorab-Fusionen, 2026-09-09:
qwen_mtplx/weights.rs lädt wie der ursprüngliche load_model die
model*.safetensors als verzögerte CPU-Load-Deskriptoren über den bereits
vorhandenen Safetensors-Loader. Danach bildet derselbe Vorbereitungspfad
_fuse_gate_up_sanitize, _fuse_gdn_in_proj_sanitize und
_fuse_qsa_qkv_sanitize in ihrer Referenzreihenfolge ab. Kein neuer Loader,
keine zusätzliche Runtime-Bibliothek und keine Gewichts-Materialisierung in
diesem Schritt.
Die Fusionsmetadaten enthalten Bits, Gruppengröße und Split-Positionen für die spätere Konstruktion der ursprünglichen Ersatzmodule. Gate/Up wird bei Experten entlang Achse 1 und beim Shared Expert entlang Achse 0 verbunden; GDN behält die Reihenfolge QKV/Z/B/A. QSA prüft Bias und tatsächliche Packgeometrie, lässt bei abweichender Indexer-Packung nur diesen separat und verzichtet ohne Indexer auf die gesamte QKV-Fusion. Fehlende Parameter oder nicht unterstützte GDN- Bitbreiten behalten den ursprünglichen Pfad. Layer-Indizes außerhalb des Modells werden mit Fehler beendet, nicht durch indizierenden Panic.
Originalreferenz: MTPLX e652d55e2652137a4abcf1312357abbf3eb9d692,
Unterbau 1f8e74e3f12f31365464a6867c6579f0e9b29d85 / Version 0.32.2.
tools/mtplx-weight-fusion-reference.py ruft die drei unveränderten
Sanitize-Funktionen auf. Die Modellattrappen stellen ausschließlich die
gelesenen/ersetzten Modulattribute bereit; sie ersetzen keine Fusionslogik.
Rohdaten: local-eval-results/weight-fusion-20260909.pqMBBu/.
reference.jsonl/rust.*.log: 18 Varianten bestanden, alle acht Schalterkombinationen plus zehn Bias-/Missing-/Mixed-Pack-/Indexer-Fälle. Rust lädt echte kleine temporäre Safetensors-Dateien, prüft vollständige Namen, Formen, Fusionsmetadaten und sämtliche Float32-Ausgabe-Hashes. Schwache Referenzen auf die ursprünglichen Load-Blätter belegen vor Eval, dass die Fusion die Quellen erreichbar hält, aber noch nicht materialisiert. Testzeit 0,18 s, Peak-Footprint 154.288.872 Bytes.installed-reference.json/installed-rust.*.log: Header des aktuell vorhandenen vollständigen Checkpoints, 2.466 ursprüngliche Parameter, 1.782 vorbereitete Parameter und 144 Fusionen (96 Gate/Up, 36 GDN, 12 QSA). Namen/Formen/Dtypes als geordneter Metadaten-Hash und sämtliche Rezepte/Splits stimmen mit MTPLX überein. Alle ursprünglichen Blätter und vorbereiteten Ausgaben bleiben ohne Daten; aktiver kanonischer Allocator = 0 Bytes. Kein Eval des Modellpayloads. Rust-Testzeit 0,07 s, Peak-Footprint 10.699.424 Bytes; Referenz-Peak 59.720.256 Bytes.
Installierter Pfad:
/Users/gb/Library/Application Support/de.rfc1437.ds4server/models/qwen3.8-flash-next.
Konfigurations-SHA256:
826302af9ff3293cfc9975c9a5a96546fa0aa9f0808505adfc30a62fef806965;
Index-SHA256:
81e77f5b25bb29e25e239ae2f9f324c9cada379ee600441d6c229f1d95a13443.
Vorbereiteter Metadaten-SHA256:
fb7106c8a24a6dc1073cbc386d57c9e60a9f30858ecf294bd9bba215b1bfa8b8.
Dies sind keine vollständigen Gewichts-Hashes.
Wichtige Artefakt-Präzisierung gegenüber älteren Notizen: In diesen vorhandenen
Shards sind Q/K/V 4 Bit, der Indexer ist 8 Bit (je Gruppe 64). Deshalb enthalten
alle zwölf QSA-Fusionen nur drei Projektionen; Splits [12288,12800].
Der ältere Produktpfad prüft diese Packkompatibilität ebenfalls bereits
(qwen.rs::attention_input); der Befund belegt hier keinen neuen Produktfehler.
Eine frühere Aussage über vier gleichartig gepackte Projektionen darf nicht
als Eigenschaft dieses aktuellen Artefakts in Messverträge übernommen werden.
Alle Prozesse einzeln unter test-supervisor 2048 15 15, ohne Modell-Download.
Abschließender gemeinsamer Lauf am finalen Build (final.*.log): beide Tests
bestanden, 0,20 s Testzeit, Peak-Footprint 154.223.336 Bytes. Zusätzlich geprüft:
ungültiger Modell-Layerumfang wird vor der ersten Fusion ohne Parameterverlust
abgewiesen. Release-Testbuild, warnings-denied Clippy sowie Format-/Diffprüfung
bestanden; kein Bundle und kein Commit.
Die neuen APIs sind noch Teil des testinternen kanonischen Ports. Offen:
restliches Sanitize/Norm- und Quantisierungsbinding, echte persistente
Decoder-/MTP-Modulkonstruktion aus diesen Parametern, PLE-Sidecar-Anschluss,
Generator/Serving und anschließend vollständige Modellmessungen. Die geprüfte
Ladevorbereitung ist kein Ersatz für diese Integration und keine
Performance-Paritätsabnahme.
Vollständige installierte Modulbindung und Sidecar-Lebenszyklus, 2026-09-09:
qwen_mtplx/binding.rs bindet jetzt alle 48 Decoder (36 GDN / 12 QSA),
beide Hyper-Connections pro Decoder, MoE, PLE auf Layer 1, Embedding,
Ausgabemixer/-kopf sowie optional den eigenen MTP-Decoder aus dem installierten
Checkpoint. Bits/Gruppen werden aus der tatsächlichen Modulkonfiguration bzw.
der ursprünglichen MTP-Packgeometrie bestimmt. Nur die zwei MTP-Pre-FC-Normen
erhalten den ursprünglichen Float32-+1-Schritt mit Rückkonvertierung;
Trunk-Normen werden nicht erneut verschoben. Fehlende oder ungebundene
Checkpoint-Parameter führen zu Fehlern. Raw-HF-Sanitize ist ausdrücklich noch
nicht implementiert und wird nicht stillschweigend als konvertiertes Format geladen.
BoundModel hält die Gewichtsbank und ihre entlehnten Module dauerhaft zusammen,
einschließlich veränderlichem Compile-/Staging-Zustand. Dazu wird die bereits
transitiv vorhandene, unveränderte self_cell 1.3.0 direkt verwendet. Kein
lokaler unsicherer Selbstreferenz-Code und keine Kopie der Gewichtspayloads.
Der Test prüft unveränderte Moduladresse und erhaltenen Zustand beim Verschieben
sowie Rückgewinnung der Gewichtsbank nach Freigabe der Module.
TextModel::post_weight_load verbindet die bestehenden Tabellenfunktionen wie
MTPLX: Sidecar je PLE-Layer, optional Resident-Anschluss, bestehender SSD-Fallback
bei gescheitertem Resident-Bind. Die originale Policy verwendet
MTPLX_NGRAM_RESIDENT bzw. ab 160 GiB physischen RAM den residenten Modus.
Die neue Integrationsprüfung pinnt ausdrücklich SSD-Modus; sie lädt keine
vollständige Tabelle und behauptet keine neu geprüfte residente Modellinferenz.
Referenz: dieselben oben gepinnten MTPLX-/Runtime-Versionen.
tools/mtplx-binding-reference.py konstruiert die echten unveränderten
MTPLX-Module über load_model(lazy=True, strict=True) und attach_mtp.
Die Variante --post-weight-load ruft zusätzlich die originale Anschlussfunktion
und den echten Tabellen-Gather auf. Keine Modellattrappen oder ersetzte
Referenzfunktionen. Fixtures: tests/fixtures/mtplx-binding{,-sidecar}.jsonl;
Rohdaten: local-eval-results/binding-20260909.ikUh5D/.
- Vier Varianten, alle drei Fusionen gemeinsam aus/an × MTP aus/an: 2.466 / 1.782 / 2.524 / 1.840 Parameter und 626 / 398 / 639 / 411 quantisierte Module. Sämtliche Namen/Formen/Dtypes und Packrezepte exakt; beide MTP-Normausgaben als Float32-SHA256 exakt.
- Sidecar in allen vier Varianten auf Layer 1, nicht resident, Prefetch an,
ursprüngliche abgerundete Hot-Cache-Kapazität 1023 MiB. Vier echte Lookup-Zeilen
[0,1,255,1], Form[4,160], vollständiger Float32-SHA256 exakt. AR-Pipeline-Freigabe bleibt wie im Original ohne residente Tabellefalse. - Finaler Rust-Test (
final.*.log) bestanden, 0,12 s Testzeit. Alle übrigen Modellparameter bleiben ausdrücklich ohne materialisierte Daten. Benachbarte Fusionsprüfungen: zwei Tests bestanden, 0,17 s; Tabellen-Routingprüfung bestanden, 0,06 s. Release-Testbuild, gezieltes warnings-denied Clippy für Tests und Format-/Diffprüfung bestanden. - Referenz und Rust ausschließlich einzeln unter externem
test-supervisor 2048 15 15. Bei diesen sehr kurzen Prozessen sind die 100-ms-Ressourcenstichproben kein lückenloser Peak-Nachweis. Keine neuen Downloads, kein Bundle und kein Commit.
Verbleibender kritischer Integrationspfad: originale Trunk-Materialisierung
einschließlich Parameterbaum-/Eval-Reihenfolge; dauerhafter Engine-/Session-Besitz
mit dem neuen BoundModel; Generator/Sampler mit AR- und spekulativen Pfaden;
Anschluss an den gemeinsamen UI-/Headless-Runtimepfad. Der kanonische Port ist
weiterhin cfg(test); das produktive QwenExecutor verwendet weiterhin den
alten FP32-Scratch-Pfad. Deshalb wird dieser Abschnitt nicht als behobenes
UI-Performanceproblem oder Abschluss von P16 gewertet. Die sechs vergleichbaren
End-to-End-Messzellen und die 2%-Abnahme aller drei Modelle bleiben offen.
Parameterbaum-/Eval-Reihenfolge, 2026-09-10:
Die echte MTPLX-Module.parameters()-Traversal wurde jetzt zusätzlich erfasst
(tools/mtplx-binding-reference.py --parameter-order). Sie verwendet die
Einfügereihenfolge der Module; auch der Python/C++-tree_visit vor mx.eval
sortiert Dictionary-Schlüssel nicht. Die Rust-Bindung zeichnet deshalb die
ursprüngliche Modul-Konstruktionsreihenfolge auf, statt die alphabetische
BTreeMap-Reihenfolge als Auswertereihenfolge zu verwenden:
- GDN: Conv, unverknüpfte Eingangsprojektionen, dt_bias, A_log, Norm, Ausgang;
der Sanitize-Ersatz
in_proj_fusedwird wie im Original hinten angefügt. - QSA: Q/K/V einschließlich jeweiligem Bias, Ausgang, Q/K-Normen, Indexer;
qkv_fusedebenfalls nach den verbleibenden ursprünglichen Kindern. - MoE: Router, SwitchGLU, Shared Expert, Shared Gate. Das nicht fusionierte Shared-MLP konstruiert Gate/Down/Up, SwitchGLU dagegen Gate/Up/Down.
- MTP: Embedding-Norm, Hidden-Norm, Embedding-FC, Hidden-FC, Decoder, Mixer.
TextModel.parameter_order hält diese Reihenfolge über die Lebensdauer der
Modulbindung. Bank::materialize reicht die benannten Wurzeln gemeinsam an
den vorhandenen synchronen Graph-Auswerter weiter; keine Einzel-Evals pro
Gewicht, zusätzliche Gruppierung oder neue Datei-Ladelogik. Fehlende Namen
werden vor dem Eval abgewiesen. Der vorhandene Bindungstest prüft jetzt die
vollständigen geordneten Namen gegen die vier originalen SHA256-Belege in
tests/fixtures/mtplx-binding-order.jsonl. Er übt den Materialisierungspfad
an den zwei echten MTP-Normen aus, nicht am gesamten 72.640.204.792-Byte-Trunk.
Belege im bestehenden Rohdatenverzeichnis binding-20260909.ikUh5D:
reference-order.jsonl enthält die vollständigen Namen, order.*.log den
bestandenen Rust-Lauf (vier Varianten, 0,16 s Testzeit). Die zwei verbundenen
Decoder-/Cache-Regressionstests bestanden ebenfalls (order-decoder.*.log,
0,47 s). Die Prozesse liefen
einzeln unter test-supervisor 2048 15 15; keine vollständige Gewichts- oder
N-Gram-Tabellenmaterialisierung. Release-Testbuild, warnings-denied Clippy für
Tests sowie Format-/Diffprüfung bestanden. Kein Bundle, kein Commit.
Die zuvor offene Reihenfolge ist damit belegt und der gemeinsame Auswertepfad
implementiert. Noch nicht belegt: vollständige Trunk-Materialisierung,
produktiver Executor-/Generator-Anschluss und die sechs End-to-End-Messzellen.
Dieser Befund ist kein Durchsatz- oder UI-Responsiveness-Nachweis.
Vollständiger Trunk und fortlaufender Ping, 2026-09-10:
qwen_mtplx::execution::Execution hält jetzt BoundModel, Streams und den
modellweiten Cache dauerhaft. Der nicht-lazy Lader materialisiert den gesamten
Trunk in der originalen Parameterreihenfolge und schließt den SSD-Sidecar an.
forward baut denselben Modellgraphen auf; logits_f32 verwendet den vorhandenen
Auswerter. Dieser Ausführungspfad bleibt bis zum Generator-/Produktanschluss
cfg(test), nicht der produktive QwenExecutor.
Der erste echte Forward deckte eine fehlende Spezialisierung auf:
QuantizedEmbedding indiziert gepackte U32-Gewichte mit I32-Token-IDs. Der
Rust-Gather wies diese Kombination bislang ab. Der Export enthält nun auch
U32/I32 und F16/I32 für Front-Gather und den allgemeinen Gather-Wrapper;
die gepinnten Kernelkörper sind unverändert. Der bestehende Layouttest prüft
beide Kombinationen mit negativen Indizes und zusammenhängenden/strided
Quellen. Bestanden unter test-supervisor 2048 15 15; Export-Identität ebenfalls
bestanden. Keine Cast-Umgehung im Embedding, keine kleinere Testform.
Rohdaten: local-eval-results/execution-20260910.Ngpzu7/.
tools/mtplx-execution-reference.py verwendet den tatsächlichen Server-Encoder
für Ping/Thinking-low, load_model(lazy=False, strict=True), den originalen
Modellaufruf und persistenten Cache. --decode folgt für diesen numerischen
Oracle greedy bis zum natürlichen EOS; es ersetzt nicht den Serving-Sampler.
--server-defaults übernimmt die zwölf Einstellungen unmittelbar aus
_server_runtime_env_overrides (Qwen-Familiendefaults, nicht zusätzlich ein
generisches Serverprofil). Die Rust-Paarläufe verwendeten dieselben Werte.
| Numerischer Vollmodell-Lauf | Exakt geprüfte Logit-Reihen | Canary max MTPLX / Rust | Ergebnis |
|---|---|---|---|
Direkte Modell-Defaults (reference-decode / canonical-decode) |
41 Prefill + 56 Decode, je 248.320 Float32-Werte | 4,053 / 4,853 ms | alle SHA256 und Argmax gleich, natürliches EOS; Antwort „Pong! …“ |
Qwen-Server-Familiendefaults (reference-server / canonical-server) |
41 Prefill + 46 Decode, je 248.320 Float32-Werte | 3,650 / 3,962 ms | alle SHA256 und Argmax gleich, natürliches EOS; Antwort „pong“ |
Alle Vollmodellprozesse liefen nacheinander unter test-supervisor 81920 30 45:
80-GiB-Abbruchbudget, Start-/Fortsetzungsgrenzen statt Gesamtlaufzeitlimit.
Zusätzlich durchgehende native UI-GPU-Probe (4-KiB-Blit/100 ms), Testabbruch bei
2-s-Probenstall oder Probe-Fehler. Python verwendet den aus der vorhandenen
ObjC-Brücke gelinkten Canary; Rust den vorhandenen model-eval-Monitor.
Keine Canary-Fehler oder unvollständigen Proben. Höchster Lifetime-Peak im
Familienpaar: Referenz 76.258.077.296 Bytes, Rust 75.878.557.624 Bytes.
Keine neue Modellinstallation. Der anfängliche Referenz-Importfehler wurde durch
Wiederverwenden der bereits lokalen Python-3.12-Pydantic-Core-Erweiterung
derselben Version 2.46.4 behoben; Modell- und Runtime-Revision unverändert.
Die instrumentierten Kaltzeiten sind keine Performance-Abnahme: etwa 7,734/7,527 s Load, 5,860/5,424 s Prefill und 2,083/2,014 s summierte 46 Decode-Forwards für MTPLX/Rust im Familienpaar. Reihenfolge nicht alterniert, keine sauberen Warmup-Paare, Hash-/Readback-Diagnostik aktiv, kein produktiver Sampler/Generator. Die Tests schließen die zuvor offene reale Trunk-Materialisierung und diese beiden numerischen Cache-Fortsetzungen; nicht UI-Eventloop, spekulativen Generator, laufenden Drei-Prompt-Chat oder P16. Release-Testbuild, gezieltes warnings-denied Clippy sowie Format-/Diffprüfung bestanden; kein Bundle, Commit oder Push.
Sampler-Anschluss: originaler LogSumExp-Pfad, 2026-09-10:
Der tatsächliche serielle Generator ruft fast_sampling.py auf, nicht nur die
NumPy-Hilfen in sampling.py. _device_serial_support_arrays normalisiert die
Top-p-Masse mittels GPU-Float32-logsumexp über das gesamte Vokabular und liest
Kandidaten erst an der gemeinsamen Eval-Grenze zurück. Ein vollständiges
Host-Readback als Ersatz würde diese Ausführung nicht abbilden.
qwen_mtplx/normalization.rs ergänzt daher den bislang fehlenden kanonischen
Last-axis-LogSumExp-Knoten. Rust übernimmt den unveränderten Auswahl-/Layoutpfad
aus mlx/ops.cpp und mlx/backend/metal/logsumexp.cpp der gepinnten
MTPLX-Runtime: Original-block_logsumexp_* bis einschließlich 4096 Elemente,
darüber Original-looped_logsumexp_*, originale Threadgroup-Geometrie,
erforderliche Kontiguitätskopie, physische Zeilenreihenfolge, Ausgabe-Strides,
kein Input-Donation und keine zusätzliche Synchronisation. Die Kernel kommen
aus der bereits gepinnten Metallib, nicht aus einer Ersatzimplementierung.
Die Graph-Vereinfachung übernimmt auch LogSumExp::is_equivalent.
Rohdaten: local-eval-results/sampler-primitives-20260910.lnnnAf/.
Der vorhandene Original-Fixturegenerator enthält logsumexp_graph_fixtures:
150 Fälle aus drei Datentypen (BF16/FP16/FP32), fünf Achsengrößen
(1/17/4096/4097/248320), fünf Speicherlayouts und beiden Keepdims-Werten.
tests/fixtures/mtplx-logsumexp-graph.jsonl enthält die direkt gewonnenen
Float32-Ausgabe-SHA256. Fixture-SHA256:
c2e4a855f6f84a355b69e21f1be6fac96a82ac6e0cdeabbddd89260c03c05018.
- Original- und Rust-Läufe jeweils seriell unter
test-supervisor 2048 15 15, keine Gewichte geladen, keine Downloads. Original-Lifetime-Peak 322.339.608 Bytes; Rust-Lifetime-Peak 213.041.896 Bytes. mtplx_logsumexp_graph_matches_reference: alle 150 Hashes exakt, Ausgabeformen und Nicht-Donation geprüft, leere Eingaben und skalare Eingaben mit Last-axis-Reduktion abgewiesen. Rust-Test 0,73 s; dies ist keine Durchsatzmessung. Der erste Rust-Versuch scheiterte kontrolliert an einem lokalen RefCell-Borrow bei Ausgabe-Allokation; korrigiert, kein GPU-Hang.mtplx_compile_simplify_preserves_reference_parent_rules: bestanden, einschließlich Zusammenlegung äquivalenter LogSumExp-Knoten. Der anfängliche Aufruf mit unqualifiziertem--exactführte null Tests aus und zählt nicht; der vollqualifizierte Wiederholungsaufruf führte den Test tatsächlich aus.- Release-Testbuild, gezieltes Clippy mit
-D warnings, Format- und Diffprüfung bestanden. Kein Bundle, Commit oder Push; kein Testprozess bleibt aktiv.
Dies schließt eine benötigte Sampler-Primitive, nicht P11 oder P16. Die Kandidaten-GatherAxis-Typkombination und Cutoff-Tie-Selektion sind im folgenden Nachweis ergänzt. Offen bleiben originale Host-Normalisierung und RNG-Ziehungsfolge, Penalties/Fallback sowie der vollständige AR-/MTP-Generator-Anschluss an UI/Harness. Das bereits vorhandene NumPy-kompatible PCG64 wird wiederverwendet. Die vollständigen fortlaufenden Chat-A/B-Läufe aller drei Modelle mit/ohne Spekulation bleiben ausstehend.
Sampler-Anschluss: deterministische Kandidatenauswahl, 2026-09-10:
qwen_mtplx/sampling.rs::deterministic_top_k bildet den vollständigen Graphen
von MTPLX fast_sampling._deterministic_mlx_top_k_support ab: erster
ArgPartition, Gather der provisorischen Werte, Min-Cutoff, Greater/Equal,
I32-Summe der strikt höheren Werte, I32-Cumsum der Gleichstände, Auswahl
kleinerer Vokabular-IDs bis zur Restquote, Where(-inf), zweiter ArgPartition
und finaler Gather. Alle Operationen bleiben lazy; kein Host-Readback und
keine zusätzliche GPU-Synchronisation innerhalb des Graphen.
Die vorhandenen Reduktions-/Scan-Auswerter werden wiederverwendet: Min und I32-Sum nutzen die originalen Reduce-Kernel, Scan übernimmt für vier Byte die originalen N_READS=4-Threadgroup-Regeln, für den bisherigen I64-NGram-Pfad unverändert N_READS=2. GatherAxis ergänzt BF16/F16/F32/U32 mit I32-/U32-Indizes durch Instanziierungen des unveränderten Original-Templates. Die Originalquellprüfung bestätigt weiterhin 17 Custom-Körper und 22 Runtime-Einheiten; kein Kernelkörper wurde für diesen Schritt verändert.
Rohdaten: local-eval-results/sampler-selection-20260910.s0lvxY/.
Der vorhandene Original-Fixturegenerator ruft den tatsächlichen MTPLX-Helper
auf und erzeugt tests/fixtures/mtplx-sampler-selection.jsonl mit 48 Fällen:
Vokabular 17/4097/248320, eine/vier Reihen, Top-k 1/min(20,Vokabular), normales
Muster, große Gleichstandsgruppen, vollständig gleiche und nichtendliche Werte.
- Zusammenhängender Rust-Selektor: 96 Ausgabe-Hashes exakt, Token-IDs und Werte für alle 48 Fälle. Zusätzlich tatsächlich dispatchte Min-/I32-Sum-/ I32-Scan-Kernel geprüft. Zehn I32-Scan-Fälle decken alle Threadsize-Bereiche (17/4096/4097/8192/8193) sowie zeilen-/spaltenkontiguierliche Layouts ab.
- Bestehende Gather-Regression einschließlich neuer Float-/U32-Kombinationen, 232 ursprüngliche Summenfälle und ursprünglicher NGram-GPU-Test mit 120 Referenzfällen plus I64-Scan-/Donation-/Layout-Zweigen: bestanden.
- Original und Rust ausschließlich nacheinander unter
test-supervisor 2048 15 15, modellfrei, ohne Downloads. Original-Selektor Lifetime-Peak 248.890.040 Bytes; Rust-Selektor 262.374.144 Bytes. Selektortest 1,30 s, kein Durchsatzvergleich. Ein anfänglicher Buildfehler in der temporären Test-Shape-Bindung wurde vor GPU-Ausführung korrigiert. - Release-Testbuild, gezieltes Clippy mit
-D warnings, Originalquellprüfung, Format- und Diffprüfung bestanden; kein Bundle, Commit oder Push.
Keine Umstellung des heißen seriellen Pfads auf diese teurere Auswahl: MTPLX verwendet dort zunächst die M=4k-Kandidatenmenge mit nur einem ArgPartition und Host-Sortierung. Der oben portierte Graph wird bei Cutoff-Tie-Spill beziehungsweise vom entsprechenden gebundenen Batch-Pfad benötigt. Die M=4k-Route und Sparse-Normalisierung/RNG sind im folgenden Nachweis verbunden. Die vollständige Generator-Anbindung bleibt ausstehend. P11/P16 und die sechs Modell-/Spekulations-A/B-Abnahmen bleiben offen; diese isolierten Tests belegen keine UI- oder Gesamtperformance-Parität.
Sampler-Anschluss: serielle M=4k-Route und Sparse-Stochastik, 2026-09-10:
serial_support bildet _device_serial_support_arrays ab: F32-Cast und
Temperaturreziprok, ein ArgPartition über M=min(4k,Vokabular), Gather und
bei aktivem Top-p LogSumExp/Exp, anschließend eine gemeinsame Auswertung.
Das Host-Readback kopiert nur die M ausgewählten Spalten je Reihe, auch wenn
die Slice einen vollständigen Vokabular-Stride besitzt; kein zusätzlicher
GPU-Pack oder Full-Vocab-Readback. Host-Lexsort, Top-p-Präfixmasse und
Cutoff-Spill bleiben unverändert. Nur bei mindestens einem Spill folgt eine
zweite Auswertung des deterministischen Selektors für alle Reihen; ersetzt
werden anschließend ausschließlich die Spill-Reihen.
Der Sparse-Verteilungspfad übernimmt _serial_row_distribution, die zweite
Normalisierung im SparseDistribution-Konstruktor, erste Treffer bei
Token-Lookups, Vereinigung/Residual und die bedingte Korrekturziehung.
Kein neuer RNG: vorhandenes Rng::new_qwen/PCG64 wird verwendet.
NumPys paarweise Summierung
und CDF/Choice-Reihenfolge
wurden gegen Version 2.4.4 geprüft: kumulative Summe, Division durch den
letzten CDF-Wert, Searchsorted rechts. Eine Punktmasse verbraucht weiterhin
eine Ziehung; Verify zieht zuerst für Akzeptanz und nur bei Rejection erneut.
Die BSD-3-Clause-Mitteilung zum Summierungsport steht im Rust-Quelltext; bei
späterer Produktintegration ist sie auch in die ausgelieferten Lizenzhinweise
aufzunehmen. Der kanonische Pfad ist weiterhin nur im Testbuild enthalten.
Rohdaten: local-eval-results/sampler-serial-20260910.h4pidl/.
- 108 tatsächliche Original-Helper-Aufrufe: Vokabular 17/4097/248320, eine/vier Reihen, Top-p 0,1/0,95/1,0, Temperatur 0,6, k=20 (am Vokabular begrenzt), eindeutige Werte, Gleichstandsgruppen, uniforme/scharfe, nichtendliche und gemischte Spill-/Nicht-Spill-Reihen.
- Token-IDs und alle endlichen Float64-Werte bitgenau; NaNs werden in beiden
Receipts kanonisiert, ihre ungültige Verteilungsmasse bleibt erhalten.
Die Originalzahl expliziter
mx.eval-Aufrufe stimmt mit den expliziten kanonischen GPU-Commits überein (automatische Primitive-Commits getrennt). Der tatsächlich dispatchte Tie-Scan stimmt mit der Original-Fallbackzahl überein, nicht nur mit einer vorhergesagten Verzweigung. - 252 daraus erzeugte Sparse-Verteilungen: normalisierte Float64-Werte und 8.064 gewöhnliche Tokenziehungen exakt. Dazu 8.064 Verify-Entscheidungen, davon 7.559 Akzeptanzen und 505 Korrekturen, einschließlich exakter Akzeptanzmassen und Residual-Verteilungen. Je Sequenz ist der nächste PCG64-Wert ebenfalls exakt; keine versteckten zusätzlichen RNG-Ziehungen.
- Alle drei
mtplx_sampler_-Tests gemeinsam bestanden, 0,44 s Testdauer, Lifetime-Peak 258.835.224 Bytes. Original-Support-Peak 355.943.216 Bytes, ursprüngliche CPU-Verteilungsprüfung 87.933.600 Bytes. Alle Läufe seriell untertest-supervisor 2048 15 15, keine Modelle/Downloads. - Release-Testbuild, gezieltes Clippy mit
-D warnings, Format-/Diffprüfung bestanden; kein Bundle, Commit oder Push. Reine Diagnostikzeiten, keine Aussage zu Modell-Token/s oder UI-Latenz.
Sampler-Anschluss: Dense-Verteilung und Bad-mass-Fallback, 2026-09-10:
dense_probabilities übernimmt den Host-Float64-Pfad softmax und
apply_top_p_top_k, einschließlich deterministischer Top-k-Gleichstände,
Top-p-Präfixmasse und erneuter Normalisierung auch ohne aktive Filter.
Die abschließende paarweise Summierung behält die Nullpositionen des vollen
Vokabulars bei. Der plurale GPU-Einstieg sparse_distributions übernimmt die
serielle Route und liest volle Host-Logits erst bei der ersten ungültigen
Reihe; weitere ungültige Reihen verwenden diesen Readback wieder.
Der originale Sparse-Fallback liefert bei ungültiger Host-Masse Token 0;
der gewöhnliche Dense-Pfad meldet dagegen einen Fehler. Greedy oder
deaktiviertes Top-k liefern am pluralen Einstieg unverändert None.
Rohdaten: local-eval-results/sampler-fallback-20260910.Csse1Y/.
150 Originalfälle (30 GPU-Batches mit je vier Reihen und 120 Dense-Fälle)
stimmen überein: Sparse-IDs und Float64-Bits vollständig, Dense-Werte über
den vollständigen Float64-SHA256 beziehungsweise denselben Fehlerzweig.
Vokabular 17/4097/248320, uniforme/scharfe/eindeutige/nichtendliche/gemischte
Reihen, Top-p 0,95/1, Top-k 0/20, Temperatur 0/0,6.
Alle vier bisherigen Sampling-Tests gemeinsam bestanden (0,68 s);
Lifetime-Peak Rust 276.022.040 Bytes, Original 356.614.984 Bytes.
Beide seriell unter test-supervisor 2048 15 15, ohne Modell oder Download.
Release-Testbuild und gezieltes warnings-denied Clippy bestanden.
Keine Kernelkörper geändert. Das ist noch kein vollständiger
_sample_from_logits-Einstieg: Dense-Tokenziehung, Penalties und die
eigentliche Generator-Verbindung sind davon getrennt.
Sampler-Anschluss: originaler GPU-Argmax, 2026-09-10:
Der vorhandene Reduktionsbaustein enthält jetzt ops.cpp::argmax(axis) und
metal/primitives.cpp::ArgReduce::eval_gpu. Der Aufruf verwendet unverändert
argmax_bfloat16/argmax_float16/argmax_float32 aus der gepinnten Metallib,
keinen nachgebauten Kernel. Achsen-/Input-/Output-Strides, Scalar-Platzhalter,
uint32-Ausgabe und Dispatch entsprechen dem Original (vier Elemente je
Thread, Rundung auf 32, Begrenzung durch die tatsächliche Pipeline).
Singleton-Achsen liefern den originalen Zeros-Pfad; andere Eingaben werden
weder für die Reduktion kopiert noch als Output-Allokation gespendet.
Die CSE-Äquivalenz enthält die Reduktionsachse wie im Original.
Rohdaten: local-eval-results/sampler-argmax-20260910.nHvwG6/.
480 Originalvergleiche mit BF16/F16/F32, Achsenlängen
1/17/4096/4097/248320, keepdims an/aus, nichtendlichen Werten und
Gleichständen. Acht Layouts: gewöhnlich, transponiert, strided, Offset,
Broadcast, Vektor, Mittelachse und negative Strides. Alle uint32-Outputhashes
und Formen exakt; für jede nichttriviale Reduktion genau ein Originaldispatch
mit passender Grid-/Threadgroup-Geometrie, ohne zusätzliche Copy oder Sort.
Alle fünf damaligen Sampling-Tests gemeinsam bestanden (1,90 s),
Rust-Lifetime-Peak 283.820.776 Bytes, Original 322.323.200 Bytes.
Serielle modellfreie Läufe unter dem externen 2-GiB-/15-s-Wächter;
Release-Testbuild und gezieltes Clippy bestanden, keine Kerneländerung.
Der Primitive-Nachweis ersetzt noch nicht den vollständigen Greedy-Einstieg
mit Penalties und dessen vorgeschalteter Auswertung im Generator.
Sampler-Anschluss: Dense-/Sparse-Tokenziehung und Verify, 2026-09-10:
Distribution bildet die zwei originalen Verteilungsarten ab. Dense-Sampling
behält seine zusätzliche Float64-Normalisierung vor NumPy-Choice; Sparse
verwendet weiter die Konstruktorverteilung. Beide verwenden dieselbe
CDF-Reihenfolge und den bereits vorhandenen PCG64. Ungültige Dense-Masse
liefert einen Fehler vor der Ziehung, keine Token-0-Ersatzantwort.
Dense-/gemischte Residual-Verteilungen behalten die vollständigen
Vokabularpositionen, Sanitization und erneute Normalisierung. Beide
Sparse-Verteilungen verwenden weiter ihren vorhandenen Union-/Lookup-Pfad.
Bei leerem Sparse-Residual wird der Target wie im Original unverändert
weitergereicht; die bisherige zusätzliche clone()-Kopie entfällt (Cow).
Rohdaten: local-eval-results/sampler-mixed-20260910.y18CqV/.
Der erste Originaldatensatz belegte jede Sparse-Position des Vokabulars und
wurde bei 248320 Tokens vom Wächter nach 16,330 s ohne Fortschritt beendet
(reference.*, 83 vollständige Receipts). Dies erzwingt im originalen
Sparse-Residual quadratisch viele lineare Token-Lookups und bildet die
Top-k=20-Testkonfiguration nicht ab. Der korrigierte Datensatz
(reference-topk.*) enthält weiterhin das volle Dense-Vokabular, aber
maximal 20 über das Vokabular verteilte Sparse-IDs. Weder Runtime noch
Wächtergrenzen wurden dafür verändert. Der Fehlversuch bleibt dokumentiert.
- 100 Originalfälle: Vokabular 1/17/129/4097/248320, Dense/Dense, Dense/Sparse, Sparse/Dense und Sparse/Sparse; umgekehrte, identische, disjunkte, nichtendliche und Nullmassen.
- 2.560 Tokenziehungen exakt; 20 Sample-Fehlerfälle ohne abweichenden RNG-Verbrauch. 3.200 Verify-Ergebnisse exakt: 1.659 Akzeptanzen, 1.227 Korrekturen, 314 Fehler. Akzeptanzbits und jeweils der nächste PCG64-Wert stimmen ebenfalls überein.
- Residual-Art, vollständige Float64-Hashes, Sparse-ID-Hashes und Wiederverwendung des Targets exakt; 20 Residual-Fehlerfälle stimmen.
- Alle sechs Sampling-Tests gemeinsam bestanden (2,36 s Testdauer), Rust-Lifetime-Peak 298.763.008 Bytes. Korrigierte Originalprüfung: 1,197 s inklusive Wächter, Peak 101.057.184 Bytes. Dies sind Korrektheitsprüfungen und keine Modell- oder Performance-Benchmarks.
- Unveränderte serielle Überwachung mit 2048 MiB und 15 s Start-/Fortsetzungsgrenzen, keine Modellladung oder Downloads. Release-Testbuild und gezieltes warnings-denied Clippy bestanden. Bestehende Sparse-Prüfungen bestehen nach gemeinsamer CDF-Nutzung weiter.
Sampler-Anschluss: Raw-Logit-Penalties und Overlay, 2026-09-10:
apply_penalties_host und apply_penalties_gpu übernehmen die beiden
Originalfunktionen aus sampling.py und fast_sampling.py. Presence und
Frequency werden auf [-2,2] begrenzt; das nachgeschaltete sparse Overlay wird
nicht begrenzt. Counts beziehen sich weiterhin auf Completion-Tokens, nicht
auf Prompt-Tokens. Ohne aktive Counts/Overlay bleibt die Originalidentität
erhalten, auch wenn die unbenutzten Penalty-Parameter ungleich null sind.
Die GPU bildet die Float64-Deltas auf dem Host, rundet diese zu Float32 und
führt für Counts und Overlay je einen unabhängigen Scatter(Sum, axes=[0])
aus. Der allgemeine Scatter castet Updates vor der Addition in den
ursprünglichen Logit-Datentyp; BF16/FP16-Logits werden nicht zu FP32 befördert.
Der CPU-Pfad bleibt Float64 und verwendet die originale Read-all/Write-all-
Reihenfolge der indizierten Subtraktion je Stufe. Deaktivierte Penalties sind
keine Kopie und kein neuer Dispatch.
Der vorhandene Indexing-Baustein und Copy-/Donation-Pfad werden wiederverwendet.
Der neue eindimensionale additive Scatter verwendet die unveränderten
Originalkörper scatter_impl, Atomic-/Sum-Helfer sowie zwölf spezialisierte
Original-JIT-Wrapper (BF16/F16/F32, Updates contiguous/strided, 32/64-Bit
Offsets). Für rank-one Indizes wählt auch der Originalplan immer nwork=1.
Die Host-Exportnamen des namespaced Wrappers sind explizit gesetzt; der erste
Lauf ohne diese Alias-Angabe scheiterte vor dem ersten Scatter-Dispatch
(rust.*). Die Korrektur betrifft nur den Einstieg, keine Berechnung.
Rohdaten: local-eval-results/sampler-penalties-20260910.kW51NO/.
- 360 direkte Originalfälle: Vokabular 17/4097/248320, BF16/F16/F32, gewöhnliche/strided/Offset/reverse/Broadcast-Logits. Acht Profile: deaktiviert, keine Counts, Counts, Overlay, beide, begrenzte Penalties, Null-Overlay und ein einzelner Count-Eintrag.
- Alle vollständigen GPU-Float32- und CPU-Float64-Hashes exakt. Identität bei No-op, kein Dispatch bei No-op, Anzahl separater Scatter-Stufen und Erhalt der vom Aufrufer gehaltenen Eingabelogits zusätzlich geprüft.
- Korrigierter Einzeltest bestanden (
rust-export.*, 1,30 s), Rust-Lifetime-Peak 172.671.720 Bytes; Original 232.211.176 Bytes. Alle sieben Sampling-Tests gemeinsam bestanden (samplers.*, 2,70 s), Lifetime-Peak 313.541.472 Bytes. Auch der bestehende QSA-ScatterAxis-Test mit den gemeinsam verwendeten Originaldefinitionen besteht weiter. - Sämtliche Läufe seriell unter
test-supervisor 2048 15 15, keine Modelle geladen/heruntergeladen. Release-Testbuild, gezieltes warnings-denied Clippy und Originalquellprüfung bestanden. Die Quellprüfung ermittelt die Runtime-Einheiten nun aus dem Export statt einer veralteten Konstanten: 26 Runtime-Einheiten, 17 Custom-Körper/41 Custom-Einstiege plus dynamische QSA-Quellen unverändert zur gepinnten Referenz beziehungsweise ihrem Export.
Sampler-Anschluss: gewöhnlicher Generator-Einstieg, 2026-09-10:
SamplerConfig, distribution_from_logits und sample_from_logits verbinden
die geprüften Bausteine entsprechend generation._distribution_from_mlx_logits
und generation._sample_from_logits. Greedy verwendet unverändert den
Raw-Dtype-Penalty-Pfad, wertet dessen Logits vor der Argmax-Erzeugung aus
und verbraucht keinen PCG64-Wert. Der einzelne Sparse-Einstieg flacht die
Logits ab, wendet GPU-Penalties an, castet danach zu Float32 und verwendet
die serielle Unterstützung mit ihrem originalen Bad-mass-Fallback. Dense
castet die unbestraften Logits zu Float32, liest logisch zu Float64 und
wendet erst dort die Host-Penalties und Distribution/Choice-Normalisierung an.
Ein GPU-Penalty-Ergebnis wird nicht als Dense-Fallback wiederverwendet.
Beim Verbinden wurde die Einschränkung des bisherigen Full-Logit-Readbacks auf zusammenhängende Zeilen entfernt. Der bereits vorhandene Integer-Reader teilt nun seine evaluierte, span-validierte CPU-Ansicht mit Float32→Float64: auch negative/mehrdimensionale/Broadcast-Strides werden ohne GPU-Pack oder GPU-Flatten gelesen. Der heiße 4k-Support-Readback bleibt unverändert und kopiert weiterhin nur die ausgewählten Kandidaten. Der plurale Bad-mass- Fallback verwendet denselben vollständigen strided Reader einmal für alle ungültigen Reihen.
Rohdaten: local-eval-results/sampler-entry-20260910.WyVtqa/.
- 1.080 tatsächliche Aufrufeinstellungen des originalen MTPLX-
generation._sample_from_logits: BF16/F16/F32, Vokabular 17/4097/248320, gewöhnliche/Rank-3/strided/reverse/Broadcast-Logits, periodische/uniforme/nichtendliche Eingaben; Greedy, Sparse Top-k, Dense Top-p und Dense ohne Filter, jeweils Penalties/Overlay an/aus. - Pro Konfiguration drei aufeinanderfolgende Ziehungen mit einem PCG64 und fortgeschriebenen Completion-Counts. Alle 3.240 Ergebnisse stimmen: 810 Greedy-, 810 Sparse-, 1.080 Dense-Ergebnisse und 540 erwartete Fehler. Token, Verteilungstyp, vollständige Float64-/Sparse-ID-Hashes, Count- Reihenfolge und nachfolgender RNG-Wert exakt.
- Die Referenz-Python-Aufrufe von eval/argmax werden aufgezeichnet. Der Rust-Test prüft tatsächliche GPU-Commitgrenzen: Greedy hat zwei getrennte Auswertungen; ein bereits ausgewerteter Bad-mass-Host-Readback erzeugt keinen zusätzlichen GPU-Commit. Argmax bleibt dem Greedy-Pfad vorbehalten, Dense-Penalties dispatchen keinen GPU-Scatter.
- Alle acht Sampling-Tests gemeinsam bestanden, 6,99 s Testdauer, Rust-Lifetime-Peak 320.389.936 Bytes. Originalsequenzen: 4,114 s inklusive Wächter, Peak 286.769.968 Bytes. Unterschiedliche gesamte Testumfänge; diese Zeiten sind ausdrücklich kein Performance-A/B-Vergleich.
- Beide bestehenden N-Gram-Stage-Tests bestehen nach Wiederverwendung des
Integer-Readers weiter. Alle Läufe seriell unter dem externen
2048 MiB / 15 s Start / 15 s Fortschritt-Budget, ohne Modelle/Downloads. Release-Testbuild, gezieltes warnings-denied Clippy, Format- und Diffprüfung bestanden. Keine Änderung an Metal-Kernelkörpern.
Dieser Einstieg ist weiterhin Teil des kanonischen Testbuilds. Die Python- Owner-Progress-/Watchdog-Anbindung ist zusammen mit dem vollständigen Generator und den UI-/Harness-Metriken zu verbinden; der Methodenvergleich allein weist weder Produktintegration noch UI-Responsivität nach.
Residenter Keyed-GPU-Sampler, 2026-09-10:
sampling::lazy_sample bildet generation._mx_lazy_sample vollständig als
verzögerten Graphen ab. ArgPartition arbeitet auf den unveränderten
Modell-Dtypes; erst die k gewählten Logits werden F32. Top-p verwendet den
originalen inklusiven Scan, Bool-Sum, Maximum und Select. Die gepinnte
categorical(sv[None], key)-Route ist inverse CDF, nicht Gumbel-max:
Max/Inf-Behandlung, exklusiver Scan, Uniform und SearchSorted-right.
random.rs übernimmt U32-Key-Erzeugung, Split und F32-Uniform aus dem
gepinnten random.cpp; rbits/rbitsc, Scan, SearchSorted und Reduktionen
kommen unverändert aus der originalen Metallib. Der Host-PCG64 bleibt davon
getrennt. Keine Auswertung, Rücklesung oder Synchronisation im Graphaufbau.
Für Bool-Sum verwendet der gemeinsame Reduktionsplan die originale
remap_reduce_types-Zuordnung Bool -> Int8-Eingabe / Int32-Ausgabe, ohne
Cast-Dispatch. Die vorhandenen Gather-Exporte umfassen nun auch F16/F32 mit
U32-Indizes, einschließlich F16-GatherFront mit beiden Arbeitsbreiten.
Nur Original-Template-Instanziierungen wurden ergänzt, keine Kernelkörper
verändert. CSE berücksichtigt RandomBits-Outputshape und Scan-/Suchrichtung.
Belege: local-eval-results/sampler-resident-20260910.7576Ll/;
Fixture tests/fixtures/mtplx-sampler-resident.jsonl, SHA256
497e1175cf18e2d76d2b18f7547bc27c9138b9f3ea82f2b3bead0cf0f72ac7a3.
- 63 Original-RNG-Fälle: drei vollständige U64-Seeds, zusammenhängende, geslicte und rückwärts gerichtete Keys, leere/gerade/ungerade sowie mehrdimensionale Ausgaben (Uniform bis 4097, Split bis 8194 Elemente). Vollständige U32-Bits- und F32-Uniform-Hashes, vier aufeinanderfolgende Split-Keys und der nächste Key stimmen bitgenau überein.
- 324 Sequenzen des echten MTPLX-Samplers mit jeweils vier aufeinanderfolgenden GPU-Key-Ziehungen: Vokabular 17/4097/248320, BF16/F16/F32, vier Layouts, normale/gleiche/nichtendliche Logits, drei Temperature/Top-p/Top-k-Profile. Alle 1296 Tokens und Fortsetzungs-Keys stimmen exakt überein. Rust prüft zusätzlich skalare unevaluierte Ergebnisse, keine Dispatches/Commits beim Aufbau sowie acht RandomBits- und vier SearchSorted-Aufrufe pro Sequenz.
samplers-export.*: alle neun Samplertests bestanden, 7,86 s Testzeit, Lifetime-Peak 337.036.080 Bytes. Original-Oraclereference-fixed.*: 1,289 s einschließlich Wächter, Peak 282.280.704 Bytes. Verschiedene Testumfänge; ausdrücklich keine Performance-A/B-Messung.- Frühere Versuche im selben Verzeichnis sind nicht als Erfolg gewertet:
Python exportiert
bitsnicht öffentlich (Oracle nutzt danach den echtenrandom.split-Einstieg); Rust fehlten zunächst Bool-Sum-Kernelzuordnung und F16-GatherFront-Instanziierungen. Die Referenzwerte wurden nicht an Rust angepasst. Alle GPU-Läufe seriell unter dem externen 2048-MiB-/15-s-Start-/15-s-Fortschritts-Wächter, ohne Modell/Download. - Release-Testbuild, gezieltes warnings-denied Clippy, Format-, Diff- und Originalquellprüfung bestanden. P11/P16 bleiben offen: der Sampler allein ist weder ein integrierter Generator noch ein UI-/Performance-Nachweis.
- Der bestehende gemeinsame Sum-Graph-Test mit 232 Referenzfällen besteht
ebenfalls (
sum.*, 2,41 s, Lifetime-Peak 396.804.960 Bytes).
Gebundene und seriale Batch-Verteilungen, 2026-09-10:
BatchedDistributions und BoundBatchedDistributions übernehmen die zwei
verschiedenen Wege aus MTPLX fast_sampling.py. Der normale Batch-Einstieg
verwendet die vorhandene Serial-Support-Auswertung und _from_execution_arrays:
Zeilensumme vor Vokabularsortierung, dann einmalige Matrix-Normalisierung.
Eine einzige ungültige Zeile schaltet alle Zeilen auf Host-Sampling um;
-1-Padding und Nullwahrscheinlichkeiten bleiben erhalten. Das ist nicht der
bereits vorhandene Sparse-Listenpfad mit einzelnen Zeilen-Fallbacks.
Der vorgebundene Weg friert Temperature/Top-p/gekappte Top-k/Vokabular vor dem Decode-Loop ein, bestimmt den Support auf den rohen F32-Logits und wertet Rows/Indices gemeinsam aus. Anschließend laufen Full-Vocab-Softmax und Top-p in Host-F64 wie im Original. Ungültige Masse bleibt hier ein Fehler, ohne automatische One-hot-Ersetzung. Vorhandene Auswahlgraphen, Readback, PCG64, CDF-Ziehung und Sparse-Konvertierung werden wiederverwendet; kein neuer Kernel.
Die Batch-Methoden behalten ihre getrennten Regeln: probability nimmt den
ersten passenden Eintrag, sample filtert positive Einträge ohne zusätzliche
Normalisierung, to_distribution normalisiert über den originalen
Sparse-Konstruktor erneut. Der gemeinsame Choice-Validator wird auch vom
bisherigen dichten Sampler benutzt. Ungültige Ziehungen verbrauchen keinen RNG.
Der erste Vergleich deckte bei Broadcast-Rows eine Ein-Bit-Abweichung auf.
np.asarray(rows).astype(float64) verwendet order='K': aus Strides (0,4)
wird eine Fortran-Anordnung (8,32); die Zeilensummen entstehen dann
sequenziell statt paarweise. Das separate Originalexperiment layout.*
belegt die unterschiedlichen Normalisierer. Rust wählt jetzt anhand der
evaluierten 2D-Inputstrides die entsprechende Summationsreihenfolge, ohne
Referenzwerte oder Toleranzen zu verändern. Referenzimplementierung:
NumPy 2.4.4 Keep-order allocation,
absolute-stride ordering.
Belege: local-eval-results/sampler-batched-20260910.5QvwOq/;
Fixture tests/fixtures/mtplx-sampler-batched.jsonl, SHA256
60e35333cc2f11ca950fdef1c3c1bcbc56da76331ce33867ad50a8d9f8719b6c.
- 324 Originalfälle je Route plus fünf Konstruktorfälle: Vokabular 17/4097/248320, BF16/F16/F32, zusammenhängende/strided/reverse/broadcast Vier-Zeilen-Batches, normale/gleiche/gemischt ungültige Logits und drei Temperature/Top-p/Top-k-Profile. 108 globale Fallbacks und 111 erwartete Konstruktor-/Auswertungsfehler. Die vollständigen IDs-/F64-Matrix-Hashes, Einzelkonvertierungen, Probability-Lookups einschließlich negativer und ungültiger Zeilenindizes sowie 17.344 Sample-Versuche mit anschließenden RNG-Werten stimmen exakt. Ablehnungen sind Teil des Vergleichs.
- Tatsächliche explizite Commit-Grenzen passen zu den Originalauswertungen;
der bereits erledigte Readback bei Host-Fallback erzeugt keinen neuen
GPU-Commit. Binden und abgelehnte Greedy-/Top-k-Anfragen lösen keine
Inferenz aus.
samplers-layout.*: alle zehn Samplertests bestanden, 11,96 s, Lifetime-Peak 797.639.856 Bytes. Der fehlschlagende früheresamplers.*-Lauf bleibt als Diagnosebeleg erhalten. - Original-Oracle: 2,286 s einschließlich Wächter, Peak 393.233.200 Bytes. Die Testumfänge unterscheiden sich; daraus wird keine Performance-Parität abgeleitet. Alle GPU-Läufe seriell unter 2048 MiB / 15 s Start / 15 s Fortschritt, ohne Modelle/Downloads. Release-Testbuild, gezieltes warnings-denied Clippy sowie Format-/Diffprüfung bestanden.
Device-side Target-prefix-Sampler, 2026-09-10:
sampling::sample_token_ids bildet jetzt die unveränderte
fast_sampling.sample_token_ids_from_mlx_logits-Operationsfolge ab: Float32-
Division durch Temperatur, deterministischer Support, begrenzte paarweise
Rangordnung (Wert absteigend/Token-ID aufsteigend), Full-vocabulary-LSE und
Top-p-Maske beziehungsweise Token-ID-Sortierung vor der Ziehung. Der positive
Top-p-Pfad lehnt k > 32 nach Begrenzung auf die Vokabulargröße ab; k <= 0
mit aktivem Top-p bleibt nicht unterstützt. Beide Pfade verbrauchen keinen
RNG-Schritt. Greedy verwendet den originalen Logit-Datentyp ohne RNG.
random::categorical_last übernimmt die tatsächlich unterschiedlichen
Referenzpfade: ein einzelner Verteilungsvektor ohne Prefix nutzt Gumbel-Max,
ein Singleton-Prefix inverse CDF, mehrere Reihen Gumbel-Max. Die Log-Operation
verwendet das originale Runtime-Metallib; die vorhandenen Reduce-, Scan-,
Gather- und Threefry-Graphen werden wiederverwendet. Keine neuen Metal-Körper,
keine CPU-Ziehung und keine vorgezogene GPU-Auswertung beim Graphaufbau.
KeySequence bildet Seed, Split und fortgesetzten Zustand ab. Dies ist noch
kein angeschlossener produktiver threadlokaler Default-RNG: Owner-
Lebenszyklus, gemeinsame unkeyed Aufrufe, zeitbasierter Initialseed und Wechsel
des Default-Streams müssen im Generator integriert werden. Der aktuelle
Sequenzhelfer hält den beim Anlegen übergebenen Stream fest; diese Tests
belegen den unveränderten Default-GPU-Stream, keine Streamwechsel-Parität.
Nachweis: tools/mtplx-kernel-fixtures.py::prefix_sampler_fixtures ruft den
originalen MTPLX-Einstieg auf. 162 Fälle mit Vokabular 17/4097/248320,
BF16/F16/F32, Vektor/Singleton/2x2-Prefix sowie strided/reverse/broadcast,
Muster/Gleichständen/NaN und Unendlichkeiten. Je elf aufeinanderfolgende
Aufrufe mit Greedy, nicht unterstützter und abgelehnter Konfiguration zwischen
Zufallsziehungen; expliziter Reseed innerhalb derselben Folge. Rust prüft
Token-IDs, Rückgabeform, Fehlermeldung und den vollständigen RNG-Zustand nach
jedem Aufruf exakt. Zusätzlich keine Dispatches oder Commits beim Graphaufbau.
- Fixture
tests/fixtures/mtplx-sampler-prefix.jsonl, SHA-256e74e239d30749f66d74d92eb9124f47de460fbf3f01b338b3adc65fef7bdbd07. - Rohdaten:
local-eval-results/sampler-prefix-20260910.SIdwjQ/. Original-Oracle regulär beendet, 1,616 s inklusive Wächter, gemessener Lifetime-Peak 447.480.696 Bytes. - Alle elf
mtplx_sampler-Tests bestanden, 13,34 s Testzeit / 14,042 s inklusive Wächter, gemessener Lifetime-Peak 815.416.520 Bytes. Original und Rust jeweils einzeln unter 2048 MiB / 15 s Start / 15 s Fortschritt, ohne Modellgewichte oder Downloads. Die Umfänge unterscheiden sich; dies sind keine vergleichbaren Gesamtmodell-Geschwindigkeitsmessungen. - Release-Testbuild, gezieltes warnings-denied Clippy, Originalquellprüfung (17 Körper/41 Custom-Einstiege/26 Runtime-Einheiten plus dynamische QSA), Format- und Diffprüfung bestanden. Keine Bundle-/Commit-/Push-Aktion.
AR-Decode-Verbindung, 2026-09-10: ar.rs und
Execution::decode_ar verbinden den bereits vorhandenen Modell-/Cache-Graphen
mit dem normalen Text-Decode-Zweig von generation.generate_ar:
- Klassischer synchroner und asynchroner AR-Pfad, Host-PCG64, Penalties nur über bereits generierte Tokens, Stop-Token intern behalten und nicht an den Text-Callback ausgeben. Keine zusätzliche CPU-Konvertierung residenter IDs vor dem Modell-Forward.
- Pipeline-Admissibilität, eigener
seed & 0x7fffffff-Key und originale Reihenfolge: erster Token aus Host-Sampler; aktuellen Schritt async auswerten, Folgeschritt bauen/async auswerten, erst dann aktuellen Token materialisieren. Vorangehende Logit-Zeile bis zum nächsten Schritt behalten. - Die Pipeline hat den finalen Token schon konsumiert; die klassische Schleife hat ihn nur ausgegeben. Finale Cache-Erfassung verwendet daher die vorhandene Pipeline-Zeile oder genau einen klassischen Tail-Forward. Der Modell-Owner schaltet den Pipeline-Modus vor dieser Erfassung zurück; auch Result-Fehler des Decode-/Callback-Pfades stellen den Modus zurück. Antwortzeit wird vor dieser Session-Nacharbeit beendet; Capture-Fehler bleiben separat und vernichten die fertige Antwort nicht.
Dieser Einstieg beginnt nach Prompt-Restore/Prefill und implementiert den
normalen Textzweig. Er ist noch kein Ersatz für den vollständigen Request-
Owner: Grammar/Constraint, Repetition-/Loop-/Thinking-Guards samt Übergang von
Pipeline zu klassischer Steuerung und die Owner-Progress-Hooks fehlen noch.
Die Pipeline-Admissibilität darf daher nicht allein zur Auswahl für solche
Requests benutzt werden. qwen_mtplx bleibt cfg(test); UI und model-eval
wurden nicht auf einen unvollständigen Generator umgeschaltet.
Orchestrierungsnachweis: ar_driver_fixtures ruft das unveränderte
MTPLX-generate_ar mit einer kleinen GPU-Transitionstabelle statt Modellgewichten
auf. Prefill, Sampling, Pipeline und finale Erfassung sind die originalen
Generatoroperationen, keine nachgebaute Python-Decode-Schleife. 480 Fälle,
1384 interne Tokens, 32 tatsächlich aktivierte Pipeline-Fälle und
192 finale Cache-Erfassungen. 96 Fälle stoppen durch EOS; die zusätzlichen
Stop-Sets erzwingen insbesondere den ersten und zweiten Pipeline-Token,
also sofortiges EOS und EOS mit bereits laufendem Folgeschritt. Rust stimmt
für Tokenfolgen, Callback-Ausgaben,
Forward-Eingaben/Reihenfolge/Hidden-Anforderung, Pipeline-Admissibilität,
Verify-Zähler und finale Logit-Bytes exakt überein. Dies testet den Decode-
Ablauf, nicht Qwen-Modellrechnung, den gesamten Session-Owner oder Speed.
- Fixture
tests/fixtures/mtplx-ar-driver.jsonl, SHA-2569916c29df3d937c36df1f12a477bcd1160683806b6941faa7ff108f8533307a5. - Rohdaten
local-eval-results/ar-driver-20260910.Ph2gDy/.reference.jsonl/driver.*dokumentieren den ersten fehlgeschlagenen Vergleich von JSON-Float64-Dezimalwerten. Finale Float32-Zeilen werden imreference-bits.jsonlunverändert als Byte-Hash erfasst;driver-bits.*besteht ohne Toleranzänderung. Der erweiterte maßgebliche Satzreference-eos.jsonl/driver-eos.*umfasst auch die erzwungenen frühen EOS-Fälle: 0,64 s Testzeit, 1,297 s einschließlich Wächter, gemessener Lifetime-Peak 173.589.272 Bytes. Original-Oracle 1,636 s einschließlich Wächter, Peak 231.129.880 Bytes; unterschiedliche Umfänge, keine Performance-A/B-Abnahme. - Alle elf vorhandenen Sampler-Referenztests (
samplers.*) danach bestanden. Modellfreie GPU-Läufe ausschließlich seriell unter 2048 MiB / 15 s Start / 15 s Fortschritt. Keine neuen Modellartefakte oder Downloads.
Angeschlossener Vollmodell-Decode: Der vorhandene installierte Ping-Test
behält seine 41 Prefill-Zeilen und 46 vollständigen Decode-Logit-Vergleiche.
Zusätzlich setzt er den Cache zurück, evaluiert denselben 41-Token-Prompt und
ruft Execution::decode_ar auf. Greedy mit max_tokens=usize::MAX, also kein
geschätztes Antwortlimit: alle 46 Antworttokens und das natürliche EOS stimmen
mit execution-20260910.Ngpzu7/reference-server.stdout.log überein. Der Callback
prüft jeden Token gegen diese Referenz und meldet tatsächlichen Fortschritt.
Das ist eine Verbindung zum echten Qwen-Trunk, nicht nur ein Tabellenmodell.
Maßgeblicher Lauf installed-phase.*: 9,05 s Testzeit / 9,758 s einschließlich
Wächter, Lifetime-Peak 75.893.991.712 Bytes, 86 Canary-Proben ohne Fehler/Stall.
Maximale GPU-Probenlatenz 3,579 ms beim Laden, 0,620 ms im Prefill und
0,505 ms im Decode. Beide Prefills sind ausdrücklich als Prefill markiert;
der erste Lauf installed.* hatte den zweiten Prefill noch im Decode-Abschnitt
und ist deshalb keine Grundlage für phasenbezogene Latenzvergleiche.
Unverändert 81920 MiB / 30 s Start / 45 s Fortschritt, nativer Canary während
des gesamten Workers mit 2-s-Abbruch, installierter Trunk ohne MTP-Head,
MTPLX_NGRAM_RESIDENT=0, originale AR-Server-Familiendefaults, Power 100 %.
Kein paralleler GPU-Prozess, kein Download.
Dieser diagnostische Test nutzt weiter den vorhandenen gemeinsamen 41-Token-Numerik-Prefill, nicht den noch zu verbindenden originalen Restore-/Body-/Tail-Requestablauf. Greedy aktiviert keine residente Pipeline. Die 9,758 s enthalten Laden, Referenzprüfungen und zwei Decode-Folgen und sind kein vergleichbarer Modell-Durchsatz. Release-Testbuild, gezieltes warnings-denied Clippy, Originalquellprüfung und Format-/Diffprüfung bestanden. Kein Bundle, Commit oder Push.
Kalter Text-Prefill mit echtem AR verbunden, 2026-09-10:
qwen_mtplx/prefill.rs führt den originalen _prefill-Body-/Tail-Ablauf aus:
Cache-Erzeugung nach dem ersten Abbruchcheck, Chunk-Views auf demselben
Promptkörper, bedarfsabhängige Logits-/Cache-Auswertung, Fortschritt nach
abgeschlossener Auswertung und separates letztes Prompt-Token. Die rohe
Cache-Wurzelmenge folgt _tree_mx_arrays über Objektattribute, nicht der
abweichenden cache.state-Ansicht: inklusive QSA-Kapazität, F32-Mirror,
GDN-/PLE-Captures und Alias-Deduplizierung. Nicht ausgewertete Head-Logits
werden im External-Emit-Cachepfad vor der Cache-Auswertung freigegeben.
505 originale Referenzfälle decken Wurzelreihenfolge und Prefill-Kontrollfluss
ab: 0/1/2/9/2050 Tokens, ungeteilter Körper oder Chunks 1/4/2048,
Final-Logits-/Cache-only-/External-Emit-Pfade, Hidden-Ausgabe und Abbrüche.
Fixture tests/fixtures/mtplx-prefill-driver.jsonl, SHA-256
5b5fb0ba51480507e6849020b3137af8af2bc4394d95e4277701f9441bb5041e.
Der erste Diagnoseadapter beobachtete fälschlich rt._count; originaler
Prefill schreibt über generation._runtime_count direkt in die Zähler.
Nach Anschluss an diesen tatsächlichen Schreibpfad stimmen auch die
Chunk-/Fortschrittsereignisse; keine Änderung der Original-Inferenz dafür.
unit-counted.*: bestanden, 0,874 s Supervisor, Peak 161.759.976 Bytes.
Rohdaten: local-eval-results/prefill-driver-20260910.XwGFhY/.
Execution::prefill_prompt ist mit derselben gebundenen Modellinstanz und
dem tatsächlichen AR-Decode verbunden. Der installierte Trunk wird ohne
Downloads, MTP-Head oder residente N-Gram-Tabelle geladen; Power 100 %, Low,
Sampler Temperatur 0,6 / Top-p 0,95 / Top-k 20 / Seed 0, originale
AR-Server-Familiendefaults, sustained Prefill 2048. Externer Wächter
81920 MiB / 30 s Start / 45 s Fortschritt, native GPU-Canary durchgehend
mit 2-s-Abbruch; ausschließlich sequenzielle GPU-Prozesse.
- Ping (
reference-ar.*,installed-ar.*): 41 Eingabetokens, ein Body-Chunk; exakte vollständige F32-Prefill-Logits, alle 68 gesampelten Tokens inklusive EOS und die vollständigen finalen Logits nach 67 AR-Schritten stimmen. Der Rust-Lauf hatte hier noch nur einen Prefill, die Referenz bereits zwei; kein zeitlich symmetrischer Vergleich. Diese Diagnoseasymmetrie ist anschließend im Rust-Test korrigiert worden, nicht im Inferenzkern. - README-Summary (
reference-summary.*,installed-summary.*): echter PromptGive a summary of the following text:plus README, 2748 Eingabetokens; Body-Spans 2048 + 699 und letztes Token separat. Exakte erste Prefill-Logits, alle 613 Tokens inklusive EOS, 612 AR-Schritte und volle finale Logits stimmen. Die Antwort ist eine abgeschlossene README-Zusammenfassung. README-SHA-25680c01ea096843312de6662d3cd8c94c8e14bdf286b58824752981fc4920fd1f8; der Oracle speichert außerdem vollständigen Prompt und dessen Hash. Beide Seiten führen jetzt erst den diagnostischen Fingerprint-Prefill und danach einen frischen Prefill mit anschließendem AR bis natürlichem EOS aus. Dies ist kein vollständiger Chat-Warmup und kein ongoing Dreiturn-Chat. - Summary: erster Prefill MTPLX 9,159 s / Rust 6,456 s, wiederholter Prefill 2,256 s / 1,755 s. Rust meldet danach 11,636 s Decode; MTPLX meldet 14,741 s Generation einschließlich des wiederholten Prefills. Diese unterschiedlich geschnittenen Rohzähler nicht als gleichnamige Decode-Metrik vergleichen. Supervisor-Gesamtzeit 31,391 s / 26,477 s, Peak-Footprint 81.212.995.568 / 80.948.295.160 Bytes. Kein 2%-Pass aus diesen Einzelmessungen mit Canary, Token-Logging, Fingerprints und nicht balancierter Laufreihenfolge.
- Summary-Canary: MTPLX 288 / Rust 243 Proben, keine Fehler/Abbrüche; Prefill-Maximum 0,726 / 0,720 ms, Decode-Maximum 0,520 / 0,737 ms. Diese GPU-Proben messen nicht den produktiven UI-Eventloop. Die Behauptung eines vollständig identischen Cache-Inhalts wäre ebenfalls zu weitgehend: geprüft sind hier Folge-Tokens und finale Logits, nicht jeder Cache-Puffer.
Gezielte Nachprüfung: AR-Driver-Regression (480 Referenzfälle, 0,62 s) und
alle elf bestehenden Sampling-Tests (13,26 s) unter 2048-MiB-/15-s-Wächter
bestanden. Release-Testbuild, warnings-denied Clippy für Binary/Tests,
Originalquellprüfung (17 Körper, 41 Einstiegspunkte, 26 Runtime-Einheiten
plus dynamisches QSA), rustfmt und Diffprüfung bestanden. Kein Bundle,
Commit oder Push. Der kanonische Modulpfad bleibt cfg(test); diese
vollständigen einzelnen AR-Interaktionen sind noch nicht die produktive
UI-/model-eval-Ausführung und kein Nachweis der sechs Endmatrix-Zellen.
Streaming-MTP-Historie am Modell verbunden, 2026-09-10:
prefill::committed portiert den kalten Textablauf aus
_prefill_committed_mtp_history_streaming; Execution::prefill_mtp_history
bindet dafür die bereits vorhandenen Trunk- und MTP-Cache-Graphen ein.
Body-Chunks liefern nur dann Hidden States, wenn das History-Fenster sie
benötigt; die Hidden-/Token-Paare werden um ein Token versetzt, passend
geschnitten und pro Chunk zwingend ausgewertet. Der letzte Prompt-Token
bleibt ein separater Trunk-Aufruf. Chunk-Callback-Fehler werden wie im Original
ignoriert, Abbrüche an den separaten Kontrollpunkten dagegen weitergegeben.
Target- und History-Zeit sind getrennt. Der explizite History-Positionswert
wird berechnet; Qwens originale mtp_update_cache ignoriert ihn zugunsten
des QSA-Cache-Offsets, und der Rust-Modelladapter tut dasselbe.
Rohdaten: local-eval-results/mtp-prefill-20260910.7S6cT2/.
656 unveränderte Originalsteuerungsfälle mit kleinen Modell-Testtensoren
prüfen Ergebnisse, Forward-/History-Eingaben, Hidden-Slices, Positionen,
Zähler-/Heartbeat-/Abbruchreihenfolge und Chunk-Callbacks. Eingaben 0/1/9/2050
Tokens; ungeteilter Körper bzw. 4/2048-Chunks; vollständige/0/1/3/2049-Historie,
Cache-/absolute Position, Full-Logits-/Cache-only-/External-Emit-Zweige.
Null-Länge des angeforderten History-Fensters wird wie im Original auf 1
geklemmt. Abbruchfälle vergleichen auch die schon ausgeführten Calls.
Fixture tests/fixtures/mtplx-mtp-prefill-driver.jsonl, SHA-256
ae00ab6c91b98382c35784309ee35f5d2e641e9f2333e050905d03a4fdae70cf.
Erzeugung mit dem endgültigen Adapter nochmals byteidentisch bestätigt;
Rust-Test bestanden (0,26 s, Supervisor 0,968 s, Peak 157.303.552 Bytes).
Der erste Fixture-Adapterversuch brach wegen eines fehlenden Runtime-Vertrags
vorzeitig ab; korrigiert wurde der Adapter, nicht MTPLX oder dessen Algorithmus.
Vollmodell-Nachweis (reference-installed.*, installed.*): installierter
Trunk plus tatsächlicher MTP-Head, README-Summary mit 2748 Eingabetokens,
Power 100 %, sustained Prefill 2048, originale MTP-Server-Familienflags und
SSD-N-Gram-Policy. Keine Downloads, keine parallelen GPU-Läufe. Externer
81920-MiB-/30-s-Start-/45-s-Fortschrittswächter und durchgehende native
GPU-Canary mit 2-s-Abbruch unverändert.
- Vollständige Historie: 2747 verschobene Token-/Hidden-Paare in zwei Chunks; Cache-Offset 2747 vor bzw. 2748 nach erstem Draft. Vollständige F32-Hashes für letzte Trunk-Logits, letzte Trunk-Hidden, erste Draft-Logits und Draft-Hidden sind exakt identisch zu MTPLX.
- Letzte drei History-Tokens: erster Body-Chunk ohne Hidden-Ausgabe, aus dem zweiten nur die letzten drei Paare für den Head; History-Positionsbasis 2744, Cache-Offset 3 vor bzw. 4 nach Draft. Dieselben vier Tensorprüfungen sind exakt; die Draft-Tensoren unterscheiden sich erwartungsgemäß vom Vollhistorie-Fall. Die Fixture prüft auch absolute Positionsmetadaten; der Vollmodell-Lauf nutzt Qwens normalen Cache-Positionsmodus.
- Rohzeiten MTPLX/Rust: vollständiger Target-Prefill 11,202/5,509 s, History 0,270/0,291 s; Drei-Token-History-Fall Target 2,221/1,710 s, History 0,0133/0,0154 s. Die höheren Rust-History-Einzelwerte sind damit ausdrücklich festgehalten. Keine Wiederholungs-/Reihenfolgebalance, kein sauberer Speed-Test und kein belegter 2%-Pass oder harter Rücknahmegrund.
- Supervisor insgesamt 20,833/13,477 s; Peak-Footprint 81.452.808.584/81.093.507.008 Bytes. Canary 189/126 Proben, kein Abbruch, Prefill-Maximum 1,391/0,918 ms. Die kurzen ersten Drafts trafen kein 100-ms-Probenfenster: keine gemessene Decode-Latenz aus diesem Test.
Alter AR-Prefill (505 Fälle) weiterhin bestanden. Release-Testbuild,
warnings-denied Clippy für Binary/Tests, Originalquellprüfung, rustfmt und
Diffprüfung bestanden. Keine neue Metal-Implementierung, kein künstliches
Cache-Leeren, keine Power-/Chunk-Absenkung, kein Bundle/Commit/Push.
Dies ist noch kein vollständiger generate_mtpk-Lauf bis EOS und keine
produktive UI-/Harness-Integration; der kanonische Pfad bleibt cfg(test).
Standard-MTP-Generator bis EOS mit Context-copy verbunden, 2026-09-10:
Execution::decode_mtp verbindet den echten MTP-Head, die vorhandenen
Sampler/PCG64-Verteilungen, batched Verify, Family-Capture-Commit,
Snapshot-Rollback/Reforward, persistente autoritative MTP-Historie,
Bonus/Pending-Correction und finalen Pending-Commit. Der Original-Oracle ruft
generate_mtpk auf; keine nachgebaute Referenzschleife. Natürlicher EOS,
Sampler 0,6 / 0,95 / 20, Seed 0, Draft-Tiefe 3, History committed, Qwen-Low,
Power 100 %, Prefill 2048, serverseitige Familienflags und SSD-N-Gram-Policy
sind innerhalb jedes Paares identisch. Rohdaten:
local-eval-results/mtp-generator-20260910.pYRdXK/.
Der erste vollständige Ping (rust-ping.*, nochmals rust-ping-trace.*)
scheiterte am 30. ausgegebenen Token: MTPLX 328, Rust 264. Die ersten neun
Draft-/Acceptance-Zyklen stimmten, im zehnten nahm Rust alle drei Drafts an,
während MTPLX den zweiten ablehnte. Ursache im neu verbundenen Generator:
der Family-Commit bekam weiterhin capture=true, obwohl MTPLX seinen
verify_capture_scope VOR dem Commit beendet. Beim Ein-Token-Replay der
PLE-Schicht verhinderte das den originalen Fused-GDN-Step und änderte den
Folgezustand. Korrektur: Commit mit GraphOptions::from_env(false, false),
wie im bereits geprüften Modelloperationsadapter. Keine Kerneländerung,
keine Toleranzlockerung und kein geänderter Seed/Prompt.
- Ping nach Korrektur (
rust-ping-capture-fix.*): alle 52 Tokens inklusive EOS, 19 vollständige Zyklen, 57 Drafts/33 angenommene Drafts, finale Logits und Hidden States als vollständige F32-SHA-256 sowie MTP-Offset 92 exakt wie MTPLX. Kein vollständiger Trunk-Cache-Hash behauptet. - Die ursprüngliche Summary enthielt fünf Runden mit leerer MTP-Draftliste. Das ist KEINE adaptive Verkürzung der MTP-Tiefe: MTPLX aktiviert auch in der batched Qwen-Lane standardmäßig Context-copy. Dieser Zweig wurde portiert und NICHT für den Vergleich deaktiviert: Prompt-only N-Gram-Index, rückwärtige Match-Verlängerung/neuester Tie-Break, Blockleiter, Probation, EMA/Backoff, Punktmassen-p/q-Akzeptanz, Family-Commit und dessen Original- Rückfall (gesamten Block zurückrollen, nur Primary nachfahren, Copy für den Request deaktivieren). MTP-History enthält die akzeptierten autoritativen Paare, nicht die noch ungeprüfte Korrektur. Auch die optionale RAMP-Fixed- und Fuzzy-Match-Auswahl ist im Index vorhanden; Vollmodell-Abnahme hier ausschließlich mit den unveränderten Standardwerten, RAMP aus.
- Summary (
reference-summary-copy.*,rust-summary-copy.*): 2748 Prompt-Tokens, 401 Tokens bis EOS, 135 Verify-Zyklen, 390 MTP-Drafts/247 angenommene MTP-Drafts. Alle fünf Copy-Ereignisse sind exakt: Block/Accept 8/0, 8/8, 16/4, 8/7, 24/0; auch Extension, Korrektur, Position und übrige Zyklen stimmen. Vollständige finale Logits/Hidden-F32-Hashes identisch, MTP-History-Offset 3148, finaler Zustand commit-fähig. Die Ausgabe ist dieselbe abgeschlossene README-Zusammenfassung wie im Original. - Summary-Rohzeiten: Rust Prefill 6,540 s, Decode 5,619 s, davon gemeldete Draft-Aufrufe 0,679 s, Verify 4,614 s, History 0,143 s; separate Reforward- Repair-Zeit 0. MTPLX meldet 10,330 s Generation inklusive 4,582 s Prefill. Diese Zähler haben noch keine vollständig vereinheitlichten Messgrenzen; aus Subtraktion allein keinen 2%-Pass ableiten. Supervisor-Gesamtzeiten MTPLX/Rust 17,671/18,022 s, Peak-Footprint 82.048.399.848/81.575.557.248 Bytes. Unterschiedliche kalte Prefill-Zeiten, Token-Logging, Canary, Endtensor-Readbacks und fehlende balancierte Wiederholungen schließen eine saubere Performance-Abnahme aus.
- Durchgehende Summary-GPU-Canary: MTPLX/Rust 159/170 Proben, keine unvollständige Probe/Fehler/Abbrüche, Prefill-Maximum 0,813/0,746 ms, Decode-Maximum 0,516/0,203 ms. Das ist keine Messung des UI-Eventloops. Alle Vollmodellprozesse liefen einzeln unter 81920-MiB-/30-s-Start-/45-s- Fortschrittswächter und 2-s-Canary-Abbruch. Keine neue Last ohne Wächter.
Gezielte Prüfungen: Context-copy-Match/Probation/Backoff/Promptende-Test,
bestehende AR-Driver-Regression (480 Fälle), Release-Testbuild, warnings-denied
Clippy für Binary/Tests, rustfmt und Diffprüfung bestanden. Kein Bundle,
Commit oder Push. Der kanonische Modulpfad bleibt cfg(test); die erfolgreiche
Standard-MTP-Interaktion ist noch NICHT die produktive UI-/Harness-Ausführung.
Capture-off-Rückfall, Greedy-Copy und optionale RAMP-Konfigurationen benötigen
zusätzliche Referenzfälle; sie werden durch die zwei Sampled-Läufe nicht als
vollständig abgenommen ausgewiesen.
Warmer Text-Suffix auf dem tatsächlichen MTP-Endzustand, 2026-09-10:
Die Integrationsprüfung der produktiven Generator::generate_inner-/
prefill_suffix-/Checkpoint-Verträge zeigte eine noch fehlende Voraussetzung:
der neue Modellpfad konnte bisher nur kalt vorfüllen. Ein direktes Umschalten
der UI hätte deshalb laufende Chats nicht mit MTPLX-Semantik fortgesetzt.
Execution::prefill_restored_suffix ergänzt den Live-/Restored-Cache-Pfad aus
generation._prefill_restored_prompt_suffix, ohne Reset oder Nachfahren des
bisherigen Kontexts. Es nutzt bestehende Modell-, History-, Slice- und
Auswerterfunktionen; keine neue Kernel-Implementierung und kein zweites Modell.
- Kurze Suffixe bis zum übergebenen Original-Limit (Default 512) werden in einem Forward mit final-only Logits verarbeitet. Lange Suffixe verwenden einen gemeinsamen Body-Eingabetensor mit Chunk-Views und separatem Tail.
- Vor dem ersten neuen Token wird der letzte gespeicherte Hidden-Zustand dem ersten Suffix-Token zugeordnet. Danach werden die um eins versetzten Hidden-/Token-Paare pro Body bzw. Fused-Forward in die bestehende MTP-Historie übernommen und zwingend ausgewertet. Kein MTP-Cache wird neu erzeugt.
- Rückgabe und Fortschrittsereignisse halten Target-/History-Zeit auseinander.
Der separate Tail meldet Fortschritt, zählt aber wie in MTPLX nicht zu
prefill_chunks; ein Fused-Forward zählt als ein Chunk. Chunk-Callbackfehler werden ignoriert, Abbrüche an den separaten Kontrollpunkten weitergegeben.
Rohdaten: local-eval-results/restored-suffix-20260910.OovSi9/.
Oracle: --mtp-generate --restored-suffixes README.md, echte originale
generate_mtpk bis EOS und danach der originale warme Suffix-Helper. Der
erste Referenzlauf sichert die Tensoren; reference-counters.* ergänzt die
echten Runtime-Zähler. Rust prüft zuerst erneut sämtliche 52 Ping-Tokens,
19 MTP-Zyklen und Endtensoren und danach die drei Suffixe auf demselben Cache:
| Warme Erweiterung | Tokens / bereits im Cache | Fortschritts-Chunks | Runtime-Chunks | Target MTPLX / Rust | History MTPLX / Rust |
|---|---|---|---|---|---|
| Story-Anweisung | 28 / 93 | 28 | 1 | 0,10313 / 0,10226 s | 0,00359 / 0,00343 s |
| README-Summary-Anweisung | 2720 / 121 | 2048 + 671 + 1 | 2 | 2,61440 / 2,58890 s | 0,04834 / 0,05187 s |
| Python-Anweisung | 33 / 2841 | 33 | 1 | 0,11914 / 0,11780 s | 0,00439 / 0,00518 s |
Alle sechs vollständigen F32-Endtensor-Hashes (Logits und Hidden je Erweiterung), die Fortschrittsfelder und MTP-Offsets 120/2840/2873 stimmen exakt. Die höheren Rust-History-Rohzeiten bleiben sichtbar. Dies sind einzelne instrumentierte Numerikläufe, keine balancierte 2%-Abnahme. Die drei Folge-Anweisungen wurden hier nur vorgefüllt: keine drei vollständig generierten Antworten und kein vollständiger SessionBank-/UI-/Harness-Chat werden daraus behauptet.
Canary MTPLX/Rust: 120/111 Proben, keine Fehler/Abbrüche; Maximum der gemeinsamen Prefill-Phase (kalter Ping plus warme Suffixe) 0,719/0,589 ms, Ping-Decode 0,161/0,182 ms. Kein UI-Eventloop gemessen. Supervisor-Gesamtzeit 13,374/12,461 s, Peak-Footprint 81.600.772.008/81.307.416.056 Bytes. Alle Modellläufe einzeln, 81920-MiB-/30-s-Start-/45-s-Fortsetzungsbudget und durchgehende 2-s-GPU-Canary. Release-Testbuild, warnings-denied Clippy und Format-/Diffprüfung bestanden.
Schutzkorrektur am Test-Wächter: Der bisherige Ausgabe-Watchdog konnte durch
workerinterne Canary-Meldungen einen Stillstand der eigentlichen Inferenz
übersehen. test-supervisor leitet diese Meldungen weiterhin vollständig
weiter, zählt die bekannten GPU-Canary-/Ressourcen-Messereignisse aber nicht
mehr als Fortschritt. JSON wird über Pipe-Lesegrenzen zusammengesetzt;
normale Teilzeilen wie Rust-Testbanner bleiben Fortschritt, Pufferung ist
begrenzt. CPU-Selbsttests prüfen auch Start-/Fortsetzungsabbruch trotz endloser
Canary-Ausgabe und erlauben einen tatsächlich fortschreitenden Lauf über
mehrere Timeoutfenster: drei Tests, 2,39 s, bestanden. Neues Release-Binary
des Wächters gebaut. Das bleibt ein kooperativer Ausgabe-Wächter, kein Beweis
für GPU-Fortschritt aus beliebigen Worker-Logs und keine Garantie gegen einen
nicht unterbrechbaren Treiberfehler. Kein neuer GPU-Lauf war dafür erforderlich.
Weiter offen am warmen Pfad: SessionBank-Auswahl, Snapshot-/Checkpoint-Restore,
Policy-Wechsel AR/MTP, optionale recurrent Boundary-Captures, Vision-Splicing,
Cleanup/Repaging und zusätzliche Abort-/AR-Referenzfälle. Der kanonische Pfad
bleibt cfg(test), bis seine produktiven Owner-Verträge verbunden sind.
Kein Bundle, Commit oder Push.
Trunk-/MTP-Snapshot und Restore, 2026-09-10:
qwen_mtplx/session_cache.rs verbindet die vorhandenen Cache-/Arraytypen mit
den originalen snapshot_cache, snapshot_cache_lazy_hybrid und restore_cache
aus dem gepinnten mtplx/cache_state.py:4334–4482. Recurrent/GDN/PLE-Zustände
werden wie _clone_tree durch lazy Add-zero-Ausdrücke kopiert. Trimmable
QSA-Zustände bleiben beim Lazy-Snapshot gehaltene Views; der Restore erzeugt
neue mutable Array-Container statt die gespeicherten Container einzusetzen.
Die vorhandene Donation-Prüfung schützt die gehaltenen Deskriptoren. Offset,
Raw-/Pool-Frontier und Kapazitäten kommen aus dem originalen QSA-State-Setter;
abgeleitete Mirrors und Verify-Captures sind keine Snapshot-Blätter.
Keine erzwungene Auswertung oder zusätzliche Synchronisation im Snapshot/Restore.
Der bestehende Vollmodelltest und sein Original-Oracle wurden um drei echte Snapshot-/Fresh-container-Restores erweitert: lazy / kopiert / lazy, mit 28 / 2720 / 33 Suffix-Tokens. Für sämtliche Cache-Blätter (Dtype, Shape, vollständige F32-Werte) werden gemeinsame SHA256-Belege geprüft, getrennt für Trunk und MTP. Gespeicherte Zustände müssen auch nach der Fortsetzung exakt unverändert sein. Alle sechs finalen Logits-/Hidden-Hashes, Chunk-Fortschritte, History-Offsets und die vorausgehenden 52 Ping-Tokens/19 MTP-Zyklen stimmen.
Rohdaten: local-eval-results/session-cache-20260910.KesHxk/reference.*.log
und rust.*.log. Erster Rust-Lauf bestanden in 14,27 s; dabei materialisiert
die diagnostische Hashprüfung den Snapshot noch vor dem Restore. MTPLX/Rust:
Supervisor 15,102/14,990 s, Lifetime-Peak 81.965.136.024/81.545.557.784 Bytes,
Canary 140/139 Proben ohne Fehler. Prefill-Maximum 4,643/6,774 ms,
Decode-Maximum 0,507/0,137 ms. Diese instrumentierten Einzelläufe sind kein
sauberer Performancevergleich; insbesondere lief jeweils zusätzlich ein
CPU-Build beziehungsweise Clippy. Kein UI-Eventloop und keine drei generierten
Folgeantworten gemessen.
Der strengere Regressionstest liest die gespeicherten Rust-Blätter erst
nach der Fortsetzung und vergleicht dann mit den unveränderten
Original-Belegen vor/nach Mutation. Dieser strengere Lauf
(rust-lazy.*.log) ist ebenfalls vollständig bestanden: 12,00 s Testzeit,
12,719 s Supervisorzeit, Lifetime-Peak 81.546.377.248 Bytes. Kein paralleler
Build/Clippy oder anderes Modell; 117 Canary-Proben, null Fehler, Maximum
3,146 ms. Der rohe OS-Disk-Write-Zähler liegt nahe u64::MAX und ist ungültig;
er wird nicht als IO-Leistungswert interpretiert. Alle gespeicherten Blätter
und sechs Fortsetzungstensoren stimmen weiterhin exakt mit MTPLX. Damit ist
auch Restore ohne diagnostisches Vorab-Materialisieren geprüft, nicht nur
der erste, bereits ausgewertete Snapshot-Lauf.
Release-Testbuild, gezieltes warnings-denied Clippy für App/Tests/Wächter,
cargo fmt --all -- --check und git diff --check bestanden. Keine Downloads,
kein Bundle, Commit oder Push; sämtliche Modellprozesse regulär beendet.
SessionBank-Auswahl/Metadaten, Disk-Checkpoints, AR/MTP-Policy-Wechsel und die produktive Owner-Anbindung sind damit noch nicht implementiert. Der neue Executor bleibt testintern; die sechs UI-identischen Paritätsläufe sind offen.
Vollständiger Session-Chat, 2026-09-10:
session_cache::SessionSnapshot hält nun Tokenpräfix, finale Logits/Hidden,
Trunk-, MTP- und recurrent Boundary-Zustände. capture_session und
restore_session verwenden die echten SessionBank-Payload-Regeln: Lazy-Trunk
abhängig von der Bankpolicy, MTP immer per vollständigem snapshot_cache und
beim Restore ebenfalls geklont, Logits/Hidden beim Speichern und Wiederherstellen
jeweils _clone_tree. Nicht passende Tokenpräfixe werden vor Mutation abgelehnt.
Dies ist die Zustandsübergabe im Executor, noch keine vollständige SessionBank
mit Identitätsauswahl, Eviction, SSD-Cold-Tier und UI-Anbindung.
tools/mtplx-execution-reference.py --chat --readme README.md nutzt jetzt die
originale SessionBank zusammen mit generate_ar beziehungsweise
generate_mtpk: README-Summary → vollständige Story → Python-Primzahlfunktion,
mit allen vorherigen Ausgabetokens im nächsten Prompt. Alle drei Antworten
enden natürlich; kein Tokenlimit als Testabschluss, keine Tools/Skills oder
Downloads. Seed 0, Temperatur 0,6, top-p 0,95, top-k 20, Low-Thinking,
2048er Prefill, SSD-PLE, MTP-D3/committed/batched, originale Serverdefaults.
Der bestehende Referenz-Runner wurde erweitert, kein weiterer Modellpfad gebaut.
Erst durch die Session-Reproduktion sichtbar gewordene Abweichung:
Der erste Rust-MTP-Chat (rust-mtp.*.log) bricht am achten ausgegebenen Token
des Summary-Turns ab: Soll 3766, Ist 19953. MTPLX aktiviert mit SessionBank
_gdn_boundary_capture_enabled und verfeinert den letzten Prefill-Body-Span
mit _prefill_spans_with_tail_grid: nicht 2048+699, sondern
2048+256+256+187, danach das letzte Token separat. Die bisherigen isolierten
Generator-/Suffixfixtures hatten keine SessionBank und prüften deshalb diesen
Requestpfad nicht. Die globale Chunkgröße wird ausdrücklich nicht reduziert.
Der gemeinsame Rust-Prefill-Treiber benutzt jetzt dieselbe Spanaufteilung bei
aktivierter Boundary-Policy. Nach dem History-Update werden nur recurrent
GDN/PLE-Zustände geklont; vorhandenes Hidden wird über contiguous ausgewertet
und gehalten, wie detach_array_leaf(..., mode="contiguous_eval"). Geometrische
Retention begrenzt die Snapshotzahl. Finale Sessions erben diese Grenzen und
ersetzen im geprüften geradlinigen Chat ältere Präfixeinträge. Explizite
Mandatory-Edges werden vom gemeinsamen Spanhelfer unterstützt; die produktive
Stable-Prefix-/Near-Prefix-Auswahl ist weiterhin offen.
Nach Korrektur beide vollständigen Chats bestanden: jede ausgesendete Token-ID, jedes natürliche EOS, alle finalen vollständigen F32-Logit-/Hidden- Hashes, alle MTP-Zyklen (inklusive Context-Copy), MTP-Offsets und geerbten Grenzpositionen sind exakt wie MTPLX. Die vier Grenzen bleiben in allen Turns 2048/2304/2560/2747. Rust hält Prompt-Snapshots während Decode und nutzt echte Snapshot-/Restore-Container für die folgenden Turns; kein stiller Cold-Replay.
| Modus / Turn | Prompt | davon wiederverwendet | Output einschließlich EOS |
|---|---|---|---|
| AR Summary | 2748 | 0 | 635 |
| AR Story | 3411 | 3383 | 1347 |
| AR Python | 4791 | 4758 | 266 |
| MTP Summary | 2748 | 0 | 466 |
| MTP Story | 3242 | 3214 | 1394 |
| MTP Python | 4669 | 4636 | 326 |
Rohdaten: local-eval-results/session-chat-20260910.jT3hf5/.
Maßgeblich reference-{ar,mtp}-boundary.*.log und
rust-{ar,mtp}-boundary.*.log; ursprüngliche Referenzen und der fehlerhafte
Rustlauf bleiben erhalten. Die ergänzte MTP-Referenz liefert gegenüber ihrem
ersten Lauf unveränderte Tokens, Zyklen und Endtensor-Hashes in allen drei Turns.
Ausgaben wurden gelesen: zusammenhängende Summary und vollständige Story ohne
Rückfrage, Python enthält die erwartete is_prime-Funktion mit fünf Assertions.
Generierter Code wurde dabei nicht ausgeführt; das ist noch keine automatische
inhaltliche Benchmark-Abnahme.
Alle Modellläufe einzeln unter 81920 MiB / 30-s-Start / 45-s-Fortsetzung und durchgehender 2-s-GPU-Canary. Keine Canaryfehler. AR MTPLX/Rust: 661/550 Proben, Prefill-Maximum 2,342/1,653 ms, Decode-Maximum 0,935/0,786 ms; Lifetime-Peak 82.686.638.304/82.424.002.208 Bytes. MTP: 566/561 Proben, Prefill-Maximum 97,546/0,810 ms, Decode-Maximum 0,540/0,715 ms; Lifetime-Peak 83.454.868.352/82.950.518.912 Bytes. Kein GUI-Eventloop wurde gemessen.
Keine 2%-Freigabe: instrumentierte numerische Läufe ohne separaten Warmup,
bei Referenzläufen teilweise paralleler CPU-Testbuild. Original-elapsed_s
enthält andere Phasengrenzen als der innere Rust-Decode-Zähler. Trotzdem bleibt
ein konkreter Performanceverdacht sichtbar: MTP-Story benötigt in Rust bereits
31,663 s Decode, gegenüber 29,938 s für den gesamten entsprechenden
Referenz-Generierungsaufruf. Das wird nicht durch die funktionale Gleichheit
oder die kurzen Canaryzeiten als erledigt behandelt. Saubere gepaarte
Performanceabnahme folgt am vollständig integrierten UI/Harness-Pfad.
Bestehende modellfreie Prefill-Regressionen unverändert bestanden: 656 MTP- und 505 AR-Receipts, zwei Tests in 0,32 s unter 2048-MiB-/15-s-Wächter. CPU-Policytest prüft Tail-Grid/Mandatory-Edges und geometrische Retention; die tatsächliche gepinnte Pythonfunktion lieferte zusätzlich exakte Cap-8-/64- Belege. Die native Ganzzahlrechnung sättigt das Potenzprodukt, um Python- Integersemantik auch bei großem Retentionslimit zu erhalten. Abschließender Release-Testbuild, Cap-8-/64-Policytest, gezieltes warnings-denied Clippy für App/Tests/Wächter sowie Format-/Diffprüfung bestanden. Die abschließende Änderung betrifft nur den Überlaufschutz bei großem Retentionslimit; die Vollmodellläufe benutzen vier Grenzen unter dem unveränderten Limit acht. Alle Modellprozesse sind regulär beendet. Kein Bundle, Commit oder Push.
Gemeinsamer Token-Turn-Einstieg, 2026-09-10:
Execution::session_turn in qwen_mtplx/session_cache.rs übernimmt jetzt
Cold-/Restore-Prefill, AR-/MTP-Decode, die während Decode gehaltene
Prompt-Snapshot-Referenz und den sicheren finalen Snapshot. Der vollständige
Chat-Test ruft diesen Einstieg auf; seine zuvor eigene Prefill-/Decode-Steuerung
ist entfernt. Vorhandene Treiber bleiben unverändert, keine neuen Kernel oder
Dependencies. Dies bereitet die gemeinsame Produktanbindung vor, aktiviert sie
aber noch nicht: qwen_mtplx bleibt cfg(test).
Finale MTP-Arrays sind nur bei angefordertem Capture und ohne Pending-Token oder
Capture-Fehler bankfähig. Ein fehlgeschlagener Snapshot wird separat gemeldet,
nicht als Verlust einer fertig generierten Antwort. Der CPU-Test
mtplx_session_final_state_requires_capture_and_safe_cache prüft fehlendes,
abgeschaltetes, erfolgreiches und fehlgeschlagenes Capture sowie den Pending-Fall;
er erzeugt nur unallokierte Array-Deskriptoren, keine GPU-Arbeit. Der unveränderte
Promptzustand bei null MTP-Ausgabetokens bleibt entsprechend der Referenz erlaubt,
wenn Capture ausdrücklich angefordert ist (generation.py:12291).
Beide vollständigen Chats gegen die vorhandenen reference-{ar,mtp}-boundary
Belege erneut bestanden: alle Tokens einschließlich natürlichem EOS, finale
Logit-/Hidden-Fingerprints, Cache-Präfixe und Boundary-Positionen; zusätzlich alle
MTP-Zyklen und History-Offsets. Keine Referenz neu erzeugt oder Erwartung geändert.
Rohdaten: local-eval-results/session-entry-20260910.F1yAZH/{capture,ar,mtp}.*.log.
| Modus / Turn | Ausgabetokens inkl. EOS | Prefill s | Decode s |
|---|---|---|---|
| AR Summary | 635 | 6,213481 | 12,075834 |
| AR Story | 1347 | 0,105876 | 25,776388 |
| AR Python | 266 | 0,124386 | 5,102924 |
| MTP Summary | 466 | 5,956198 | 6,339998 |
| MTP Story | 1394 | 0,114543 | 27,345384 |
| MTP Python | 326 | 0,154080 | 4,225220 |
Alle Prozesse einzeln mit test-supervisor: CPU-Test 2048/15/15, Modelltests
81920/30/45, SSD-Ngram, originale Server-Overrides, Chunk2048, ohne Drosselung.
Der permanente 100-ms-GPU-Canary hatte AR/MTP 516/468 Proben, keine Fehler;
Prefill-Maxima 0,747/0,727 ms, Decode 0,559/0,540 ms, Laden 3,229/11,644 ms.
Peak-Footprint 82.422.937.008/82.943.817.736 Bytes; Supervisor 55,407/50,261 s,
beide regulär beendet. Kein CPU-Build parallel zu den Modellläufen.
Diese instrumentierten Kalt-/Fortsetzungsprüfungen ohne vorgeschalteten Warmup
sind weiterhin keine saubere 2%-Performanceabnahme und messen keinen GUI-Loop.
Release-Testbuild (cargo test --release --offline --bin ds4-server --no-run -j 1),
gezieltes Clippy mit -D warnings, Format-/Diffprüfung bestanden. Testbinary SHA256:
14e13eaa14e810af12ad149e7b1ebe6bf231cef8129d7c951a5b4da661e74441.
Weiter nötig für den Produktanschluss: Session-Auswahl/Identität und Disk-Payload,
Erhalt von Prefill-Bankeinträgen bei Abbruch, Abbruch-/Text-Stop-Ausgänge im Turn-Adapter,
Power-Pausen sowie gemeinsame Metriken. Keine Umschaltung auf den neuen Executor,
bevor diese bestehenden Generator-Verträge angeschlossen sind.
Gemeinsame produktive Textausgabe, 2026-09-10:
Generator::generate_inner verwendet jetzt GeneratedText für den bisherigen
UTF8-/Thinking-/Stop-Zustand. Die vorhandenen Helfer append_generated_bytes,
emit_safe_text und flush_generated werden unverändert wiederverwendet. Die
scalar Decode-Schleife enthält keine eigene Kopie dieser Zustandsübergänge mehr.
EOS, Abbruchprüfung, Completion-Zähler und Cache-Gültigkeit bleiben unverändert
beim Generator. Keine Änderung an Sampling, Prefill-Größe, GPU-Dispatch oder
Power-Policy; keine zusätzliche Dependency oder Queue.
Der kanonische Vollmodell-Chat verwendet exakt dieselbe Textausgabe im
Token-Callback, mit dem installierten Produkt-Tokenizer. Zusätzlich zur bisherigen
Token-/Zyklus-/Cache-Parität prüft er jetzt Thinking- und Antworttext sowie deren
gestreamte Chunks bytegenau gegen chat_turn.text der bestehenden MTPLX-Belege.
Alle sechs Turns erneut bestanden; Referenzen und Erwartungen unverändert.
Zwei CPU-Regressionstests (generated_text_) prüfen geteilte UTF8-Sequenzen,
unvollständige Sequenzen beim Drain/Phasenwechsel, Thinking-Ereignisse, einen
tokenübergreifenden Text-Stop und duplikatfreies abschließendes Flushen.
Rohdaten: local-eval-results/shared-emission-20260910.IrS1L4/:
text-matched.*.log (2 tatsächliche Tests), ar.*.log, mtp.*.log.
Das vorausgehende text.*.log traf mit falsch qualifiziertem Filter null Tests
und ist ausdrücklich kein Testnachweis.
| Modus / Turn | Thinking / Antwort Bytes | Prefill s | Decode s |
|---|---|---|---|
| AR Summary | 194 / 2514 | 4,667441 | 12,064467 |
| AR Story | 226 / 5774 | 0,105925 | 25,786883 |
| AR Python | 142 / 711 | 0,125289 | 5,135448 |
| MTP Summary | 174 / 1837 | 5,230820 | 6,341459 |
| MTP Story | 270 / 5817 | 0,114802 | 27,293845 |
| MTP Python | 203 / 875 | 0,147034 | 4,231167 |
Unveränderte sequentielle Supervisor-Grenzen: CPU 2048/15/15, Vollmodell
81920/30/45, SSD-Ngram, Server-Overrides, Chunk2048, ungedrosselt, 100-ms-Canary.
AR/MTP: 504/460 Proben ohne Fehler oder 2-s-Stall; Prefill-Maxima 8,309/0,683 ms,
Decode 0,620/0,535 ms, Laden 3,334/4,606 ms. Peak-Footprint
82.497.910.432/83.026.982.920 Bytes; Supervisor 53,920/49,404 s, regulär beendet.
Keine parallelen Builds während der Modelltests. Release-Testbuild, gezieltes
Clippy mit -D warnings, Format-/Diffprüfung bestanden. Testbinary SHA256:
e02b2d809197d224a56423b029f8e8dbc66c4f35a0f3cdbe727de019d8b81fa8.
Dies verbindet die produktive Ausgabe-Verarbeitung, noch nicht den
kanonischen Inferenz-Executor mit UI/model-eval. Letzterer bleibt cfg(test).
Session-/Disk-Adapter, Whole-Turn-Abbruch/Stop, Power und Metriken sind weiter
anzuschließen. Die Messungen sind instrumentierte Funktionsregressionen ohne
vorgeschalteten Warmup, keine 2%-Abnahme und kein GUI-Eventloop-Nachweis.
Kein Bundle, Commit, Push oder Download.
Qwen-Checkpoint-Payload nach MTPLX, 2026-09-10:
Der neue qwen_mtplx/session_codec.rs bildet für die vorhandenen typisierten
Qwen-Zustände cache_bank/codec.py ab: JSON-Baum mit Tuple-/List-/None-Metadaten,
Trunk, Logits, Hidden, MTP-Head und innere GDN-Grenzen. Die Blob-Namen folgen der
originalen Besuchsreihenfolge. Axis-2-Tensoren werden ab 2 * block_size in
Blöcke zerlegt (Default der Referenz 256, null wird zu eins). Schreiben kann
über denselben Callback entweder gestaged oder direkt auf Disk erfolgen; die
fertigen Bytevektoren werden übergeben, nicht für den Speicher-Handler kopiert.
bytes(memoryview(array)) wird nach der Auswertung mit vorhandenen
Array-/Buffer-Helfern in logischer C-Reihenfolge gelesen, auch für negative,
transponierte und Broadcast-Strides. Kein zusätzlicher GPU-Cast/Contiguous-
Dispatch zum Export. BF16 bleibt als rohe 16-Bit-Darstellung erhalten; Restore
verwendet den ursprünglichen View-/Reshape-/Concatenate-Pfad. Der skalare
Referenzfall Shape [] wird beim Restore wie im Original [1], nicht heimlich
korrigiert. Abbruch wird vor jedem Tensor und jedem Block geprüft.
Vollständiger Payload-Restore und separat aufrufbarer Boundary-Restore bilden
die zwei originalen Routen ab. Ein exakter Restore kann Boundary-Blobs vollständig
überspringen; späterer partieller Restore liest ausschließlich diese Blobs.
Die separat gebatchte Boundary-Auswertung und anschließende Gesamt-Auswertung
bleiben erhalten. Ältere Payloads ohne gdn_boundaries und Records ohne
hidden_last werden wie in der Referenz akzeptiert. Ungültige Blob-Namen
(einschließlich Pfad-Traversal), falsche Bytezahlen und Lesefehler werden abgewiesen.
Referenz unverändert gepinnt auf e652d55e2652137a4abcf1312357abbf3eb9d692.
tools/mtplx-session-codec-reference.py verwendet dessen tatsächliche
encode_payload-/decode_payload-Funktionen mit kleinen synthetischen Tensoren,
keine Modellgewichte. Blockgrößen 0/256/1024 ergeben 1568/19/13 Blobs, jeweils
41.480 Payload-Bytes. Alle 1600 Blobs byteidentisch, ebenso Payload-Spec,
restaurierte Datentypen/Shapes/Hashes und erneute Serialisierung. Der Rust-Test
liest die originalen Python-Dateien, nicht nur seine eigenen Writes. Zusätzlich
geprüft: selektive Blob-Zugriffe, Legacy-Records, Lesefehler, ungültige Namen,
abgeschnittene Daten und Abbruch vor dem zweiten Block nach genau einem Write.
Belege: local-eval-results/session-codec-20260910.GQsCzv/.
Maßgebliche finale Fixtures unter compat/, Logs reference-compat.*.log und
rust-ready.*.log; rust.*.log ist der vorausgehende erfolgreiche Grundvergleich.
Alle Programme einzeln unter test-supervisor 2048 15 15, keine geladenen Modelle
oder Downloads. Finaler Rust-Test: 1 Test bestanden, 0,24 s Testzeit,
0,967 s Supervisor; Peak Physical 171.524.912 Bytes. Referenz-Supervisor 0,315 s,
Peak 156.140.192 Bytes; der winzige Referenzlauf überlappte einen CPU-Build.
Diese Werte sind Funktionsdiagnostik, kein Performance-A/B. Release-Testbuild,
gezieltes Clippy mit -D warnings, Format-/Diffprüfung bestanden; alle Tests beendet.
Import-Korrektur nach vollständigem Caller-Trace (10.09.): Die vorige
Forderung, hier einen Zero-Copy-Host-Owner zu portieren, war falsch. Zwar besitzt
python/src/convert.cpp:190,259 einen copy=None-Übernahmepfad. Aber der tatsächlich
von mtplx/cache_bank/codec.py:395–409 verwendete mx.array(...)-Konstruktor
übergibt in python/src/array.cpp:311 ausdrücklich create_array(v, t, true);
convert.cpp:706–722 reicht dieses copy=true an nd_array_to_mlx weiter.
Deshalb kopiert der Codec auch seitenalignierten Host-Speicher. Der Default eines
internen Helfers ist kein Beleg für das Verhalten seines konkreten Aufrufers.
Die modellfreie Probe tools/mtplx-host-import-reference.py bestätigt direkt in
der unveränderten installierten MTPLX-Runtime: alignierte 16-KiB-, unalignierte
16-KiB-, kurze 17-Byte- und leere Eingaben werden nicht übernommen; keine hält den
NumPy-Host-Owner fest. Nach der Freigabe liegen 16384/16384/17/0 Bytes im Pool.
Belege: local-eval-results/host-import-20260910.dfNdNK/reference-verified.stdout.log
(finale Probe mit Assertions; reference-default.stdout.log war der erste
erfolgreiche Lauf).
Der erste Versuch mit einem copy-Keyword wurde vom Python-Konstruktor abgewiesen;
reference.stdout.log / reference.stderr.log sind kein erfolgreicher Nachweis.
Die reale Abweichung war das Umgehen des kanonischen Allocators außerhalb einer
GPU-Scope. decode_tensor kopiert nun ausdrücklich über streams.allocator();
leere Tensoren behalten den bestehenden null-storage-Descriptor. Es wurde kein
Zero-Copy-/Host-Lifetime-Pfad oder neuer nativer Allocator eingeführt. Der gezielte
Rust-Test prüft Referenzgrößen, Copy-Semantik, View-/GPU-Hold-Lebensdauer, Pool-Rückgabe
und Wiederverwendung beim zweiten Import. Beide Codec-Tests bestanden:
mtplx_session_codec_host_import_matches_reference und
mtplx_session_codec_matches_original_blobs_and_restore (weiterhin alle 1600 Blobs).
Der neue Test läuft ausdrücklich ohne aktive GPU-Scope und würde bei der alten
scalar_buffer-Route an der aktiven Pool-Belegung scheitern.
Nachweise im selben Verzeichnis: rust.stdout.log / rust.stderr.log.
Supervisor 2048 MiB / Start 15 s / Fortschritt 15 s; keine Modelle, Downloads oder
parallelen Builds während der Proben. Beide Tests 0,24 s, Supervisor 0,938 s,
gemessener Peak Physical 168.657.664 Bytes. Der 0,105-s-Pythonlauf ist für eine
belastbare Peak-Speichermessung zu kurz; keine Performance-A/B-Aussage.
Release-Testbuild (/tmp/ds4-host-import-build.log), gezieltes Clippy mit
-D warnings (/tmp/ds4-host-import-clippy.log), Format-/Diffprüfung bestanden;
alle Prozesse regulär beendet. Testbinary SHA256:
39a0165f0e0aa26b6a4db2075cb3f59786bef9a21db2395c381c46ecdeb4ef6e.
Die native Bridge und Buffer-Lifetime-Implementierung wurden in diesem Schritt
nicht verändert. Die Python-Extension der unveränderten Referenz hat SHA256
5ff77c777a73864d2af86defd61b141467746636f0047b76b66a7ae645fa12fb.
Qwen-Request-Grenze und abbrechbare Ausgabe, 2026-09-10:
qwen_mtplx/request.rs::Execution::generate_text benutzt ausschließlich
session_turn für Prefill/AR/MTP und liefert das bestehende GenerationOutput
mit dem gemeinsamen GeneratedText. Es gibt keinen zusätzlichen skalaren
Sampling-/Decode-Loop. Tokenzähler schließen wie in der UI EOS aus, während der
Sessionzustand die vollständige Tokenfolge inklusive EOS behält. UTF-8,
Thinking-Wechsel und Text-Stops verwenden dieselbe Ausgabe-Verarbeitung wie die UI.
Ein tatsächlich im Adapter beobachteter Abbruch oder Text-Stop liefert den
bereits erzeugten Text, aber keinen finalen Sessionzustand. GPU-/IO-/Observer-
Fehler werden nicht als erfolgreiche Abbrüche verschluckt. Der Adapter versucht
nicht, einen möglicherweise vorausgerechneten AR-/MTP-Cache nach einem Stream-Stop
als vollständigen Chat zu speichern. Die nächste Generierung restauriert einen
gültigen Bankeintrag. Die Referenz speichert den Prompt bereits vor Decode
(generation.py::_maybe_store_prefix_snapshot, Zeilen 3888–3973); bisher hielt
Rust diesen Snapshot nur auf dem session_turn-Stack und verlor ihn bei Fehlern.
Nun übernimmt ihn ein Storage-Callback vor TurnProgress::Decode, sodass er
auch nach einem Abbruch beim Caller verbleibt. Ein fehlgeschlagenes Prefix-Store
bleibt wie in MTPLX nichtfatal (prefix_snapshot_error).
Der vorhandene Vollmodell-Chat-Test läuft jetzt durch diesen Request-Adapter, nicht mehr durch einen separat im Test zusammengesetzten Text-Callback. AR und MTP jeweils 1 Test bestanden: alle drei natürlichen Antworten, sämtliche Tokens und finalen Fingerprints, Boundary-Positionen und zusätzlich alle MTP-Zyklen und Head-Offsets unverändert zur gespeicherten Referenz. Zusätzlich je Modus: Abbruch vor Prefill ohne Ausgabe/Store, echter Observer- Fehler bleibt Fehler, Abbruch nach erster Ausgabe erhält Teiltext und Prompt- Snapshot, Literal-Stop leakt keinen Text, fehlgeschlagener Prefix-Store erreicht trotzdem den Decode-Einstieg. Die zwei folgenden regulären Chat-Turns restaurieren weiterhin exakt den gültigen Finalzustand, nicht die unterbrochenen Cache-Reste.
Belege: local-eval-results/request-turn-20260910.lh9PZ4/{ar,mtp}.{stdout,stderr}.log.
Nur installierte Qwen-Gewichte, sequentiell, kein paralleler Build; unveränderte
Referenz-Overrides, SSD-Ngram, Chunk2048, ungedrosselt, Supervisor 81920/30/45,
100-ms-GPU-Canary mit 2-s-Abbruch. AR/MTP 601/529 Canary-Proben, null Fehler/Stalls;
Prefill-Maxima 7,005/3,794 ms, Decode-Maxima 0,834/1,241 ms. Die zusätzlichen
Abbruch-Proben zwischen den regulären Turns liegen im äußeren Testabschnitt
finishing, nicht in einer nachgebildeten GUI-Phase. Kein GUI-Eventloop-Nachweis.
Peak Physical 82.724.992.648/83.067.795.392 Bytes; beide Supervisoren regulär beendet.
| Modus / Turn | Prefill s | Decode s |
|---|---|---|
| AR Summary | 10,480830 | 12,810777 |
| AR Story | 0,111735 | 27,830894 |
| AR Python | 0,141198 | 5,605803 |
| MTP Summary | 9,687827 | 6,756337 |
| MTP Story | 0,122406 | 29,269802 |
| MTP Python | 0,154803 | 4,568898 |
Diese Zeiten sind gegenüber mehreren vorherigen Diagnostikläufen schlechter,
insbesondere der kalte Prefill. Keine Performance-Parität oder unveränderte
Performance behauptet: kein Warmup, keine zeitnah gepaarte Referenz und zusätzliche
Abbruch-Proben. Die Ursache der Zeitdifferenz ist damit nicht belegt und muss in
der kontrollierten End-to-End-Abnahme geprüft werden; die Funktionsprüfung darf
sie nicht als erledigt deklarieren. Release-Testbuild und gezieltes Clippy mit
-D warnings (/tmp/ds4-request-{build,clippy}.log), Format-/Diffprüfung bestanden.
Testbinary SHA256 6c44e2150e9bc34e362d73fb5dd688357ca71e5f7fbed3179c9510ad42b12959.
Der Request-Adapter bleibt Teil des cfg(test)-Ports. Noch keine produktive
Umschaltung: Generator/UI/model-eval müssen erst denselben Owner einschließlich
Session-Auswahl/Identität/Disk-Store, Power-Pausen und laufender gemeinsamer Metriken
benutzen. Die sechs 2%-Vergleiche bleiben vollständig offen; kein Bundle/Commit/Push.
Gemeinsame Fortschritts-/Decode-Messung und frischer Golden-Master-Abgleich, 10.09.:
request::RequestProgress liefert nun den bestehenden UI-/Runtime-Callback
(used, limit, Option<decode_tps>) ab dem gecachten Frontier, für Prefill und
jeden ausgegebenen Token. Der warme Backend-Fortschritt ist bereits absolut;
gecachte Tokens werden nicht doppelt addiert. Der Adapter nutzt Metrics für
Prefix-Reuse und denselben DecodeTimer wie die UI. AR und MTP melden ihre
Decode-Endgrenze jetzt vor finalem Token-/Cache-Capture; bisher kam
TurnProgress::Finalize erst danach. Normale Ergebnisse übernehmen die gemessene
Backend-Decode-Dauer, Fehler/Abbruch verwenden weiterhin die gemeinsame RAII-
Zeitmessung. Weder Sampling noch Shader/Command-Submission wurden verändert.
Zwei modellfreie Tests bestanden: qwen_request_progress_uses_ui_frontiers_and_decode_timer
und decode_timer_excludes_later_work_and_resets_between_requests. Die AR-/MTP-
Referenz-Chats samt Abbruchfällen jeweils erneut bestanden; zusätzliche Assertions
prüfen Start-/Endfrontier, jeden Token-Fortschritt, Kontextlimit und die exakt im
gemeinsamen Metrikobjekt gespeicherte Decode-Dauer. Belege:
local-eval-results/request-progress-20260910.DvrBll/{timing,ar,mtp}.*.log.
AR/MTP: 607/529 Canary-Proben, keine Fehler/Stalls; Prefill-Maxima 10,841/0,906 ms,
Decode 0,690/0,901 ms, Finishing 0,789/0,580 ms. Peak Physical
82.719.667.704/83.067.533.128 Bytes. Negative/übergelaufene OS-Disk-Write-Zähler
in diesen Logs sind ungültig und werden nicht als IO-Leistung interpretiert.
Die wiederholten kalten Prefills nahe 10 s wurden unmittelbar am unveränderten
MTPLX-Master gegengeprüft. Der erste AR-Referenzlauf benötigte 11,367 s, der zweite
9,664 s: keine belegte Rust-spezifische Ursache für den Abstand zu älteren ~5–6-s-
Läufen, aber auch keine Erklärung der äußeren Ursache allein aus diesen Proben.
Dabei wurde die Referenz-Metrikgrenze vollständig nachverfolgt:
generation.py::_generation_rate_fields zieht Prefill, Restore und sonstige
Prompt-Phase ab; elapsed_s ist dagegen die Gesamtspanne einschließlich Prefill.
Der Recorder gibt nun direkt decode_elapsed_s, decode_tok_s und
prompt_state_total_time_s aus, statt einen Vergleich mit reiner Rust-Decode-Zeit
aus der Gesamtzeit ableiten zu müssen. Modellfreier Original-Stats-Gegencheck
(reference-rates.*.log): 14 s Gesamtzeit minus 10 s Prefill, 1 s Restore, 1 s
sonstige Vorbereitung = 2 s Decode und 50 Token/s bei 100 Tokens.
Zeitnaher diagnostischer Vergleich, kein Warmup/Median und keine produktive
UI-/Harness-Abnahme. Beide Seiten dieselben installierten Gewichte, Server-
Overrides, Chunk2048, SSD-Ngram, niedriges Thinking, ungedrosselt/100 %, durchgängiger
100-ms-Canary mit 2-s-Abbruch, Supervisor 81920/30/45, sequentiell ohne CPU-Builds.
README-Prompt-SHA256 auf beiden Seiten
69a37cf788e427fd384558517092e9a2a222f33910be63b48175516bf15ad84d.
Neue Referenz-Receipts stimmen nach Entfernung ausschließlich der Zeitfelder mit
den bisherigen Tokens, Texten, Cache-Fingerprints, Boundaries und MTP-Zyklen überein.
Quellen: reference-{ar,mtp}-rates.{stdout,stderr}.log im selben Verzeichnis.
| Qwen / Prompt | Prefill Rust / MTPLX s | Decode Rust / MTPLX Token/s | Rust-Decode-Differenz |
|---|---|---|---|
| AR Summary | 9,950 / 9,664 | 48,91 / 50,22 | −2,60 % |
| AR Story | 0,113 / 0,119 | 48,03 / 47,02 | +2,16 % |
| AR Python | 0,141 / 0,140 | 47,08 / 46,85 | +0,48 % |
| MTP Summary | 9,840 / 12,351 | 69,07 / 66,56 | +3,78 % |
| MTP Story | 0,121 / 0,125 | 47,89 / 45,83 | +4,49 % |
| MTP Python | 0,158 / 0,154 | 72,32 / 69,03 | +4,77 % |
Die Raten verwenden auf beiden Seiten Tokens inklusive EOS; die UI-Completion- Zahl bleibt unverändert ohne EOS. Positiv bedeutet schneller. AR Summary verfehlt in diesem Einzelvergleich 98 % der Referenzgeschwindigkeit; außerdem sind einzelne Prefill-Vergleiche außerhalb 2 %. Das Gesamtziel ist damit ausdrücklich nicht erfüllt. Native MTP-Akzeptanz (ohne Context-Copy-Zyklen), identisch in beiden Ports: Summary 301/444 = 67,79 %, Story 746/1920 = 38,85 %, Python 225/279 = 80,65 %. Das passt zum geringen MTP-Nutzen bei der Story und erklärt, warum kein pauschaler Speedup vorausgesetzt werden darf; es ersetzt keine Zerlegung der einzelnen Kosten. Die frischen Referenzen hatten 602/592 Canary-Proben ohne unvollständige Probes, maximal 3,066/2,516 ms über alle Phasen. Alle Prozesse sind regulär beendet.
Release-Testbuild, Test- und Produktions-Clippy mit -D warnings, Format-/Diffcheck
bestanden (/tmp/ds4-request-progress-{build,clippy,production-clippy}.log).
Testbinary SHA256 cfc781c74406ecef37d27c77ed9f204c6480b8326db1c2f14b1c277fae432eaa.
Offen: produktiver Owner/Session-Store, gemeinsame Executor-Verdrahtung und echte
Power-Pausen unter 100 % (bei AR-Lookahead genügt Schlafen im Token-Callback nicht),
danach warme wiederholte Abnahme aller drei Modelle mit/ohne Spekulation. Dieser
Schritt fügt keine Warte-/Flushpunkte bei 100 % ein und erklärt den Test-Port nicht
zur produktiven UI-Ausführung. Kein Bundle, Commit oder Push.
Backend-explizite Allokation als Integrationsvoraussetzung, 10.09.:
gpu::Buffer::{bytes,untracked} hatten zuvor unter cfg(test) automatisch die
MTPLX-Rundungs-/Pool-Policy verwendet, während Produktbuilds direkt DS4 allozierten.
Dieser versteckte Backendwechsel ist entfernt. DS4/GLM und der alte Qwen-Executor
verwenden dieselben nativen Allokationsfunktionen unabhängig vom Buildtyp. Alle
Aufrufe im kanonischen Qwen-Graph und seinen Fixtures wählen ausdrücklich
mtplx_bytes, mtplx_untracked oder mtplx_floats; Rundung, leere Deskriptoren,
aktiver Pool und GPU-Lebensdauer bleiben für diesen Pfad unverändert. Keine neue
Allokator-Abstraktion, kein geänderter Kernel und keine Scheduling-/Power-Änderung.
Neun überwachte modellfreie Tests bestanden: vier Bridge-/Lebensdauerprüfungen
einschließlich der neuen Backend-Isolation innerhalb und außerhalb eines Qwen-
Scopes, vier vorhandene Allokator-Referenzprüfungen und die Encoder-/Pool-Anbindung.
Die neue Prüfung weist insbesondere nach, dass DS4-Allokationen keine MTPLX-
Rundung übernehmen und auch bei aktivem Qwen-Scope dessen Pool nicht beanspruchen.
Rohdaten: local-eval-results/explicit-allocator-20260910.olnx1y/ mit
allocation, allocator und encoder stdout/stderr. Test- und Produktions-Clippy
mit -D warnings, Release-Testbuild, Format- und Diffprüfung bestanden.
Build-/Clippy-Logs: /tmp/ds4-explicit-allocator-{build,clippy,production-clippy}.log.
Testbinary SHA256 d070eaa625a15a8d1abc6c4b23a0b28b057495b05e8417c732ed8cedbfc32cc4.
Anschließend beide vollständigen Qwen-Referenz-Chats einschließlich der vorhandenen
Abbruch-/Text-Stop-/Cache-Fehlerfälle bestanden (ar/mtp stdout/stderr im selben
Verzeichnis). Unveränderte Referenzen session-chat-20260910.jT3hf5/reference-{ar,mtp}-boundary.stdout.log,
installierte Gewichte, Power100, Chunk2048, SSD-Ngram, sequentiell unter Supervisor
81920/30/45 und durchgängigem 100-ms-Canary; keine neuen Downloads. Referenztokens,
Texte, Cache-/Boundary-Zustände, MTP-Zyklen und gemeinsame Fortschritts-/Decode-
Metriken unverändert korrekt. AR/MTP: 604/551 Canary-Proben, keine Fehler oder
Stalls; GPU-Completion-Maximum Prefill 2,026/2,697 ms, Decode 0,658/1,175 ms.
Peak Physical 82.718.471.720/83.064.911.928 Bytes; Supervisor-Ende nach
62,657/58,785 s, beide exit 0. Diese kalten Einzel-Regressionsläufe sind weder
ein frischer gepaarter Performancevergleich noch die UI-/Harness-Endabnahme.
Gemeinsame Modell-Metadaten vom alten Qwen-Executor entkoppelt, 10.09.:
engine::ModelRef::Qwen verweist jetzt auf QwenMetadata, nicht mehr auf den alten
QwenModel mit dessen Gewichts-Mappings und PLE-Leserpool. Tokenizer, Chat-/History-
Rendering, Fortsetzung, Stop-/Thinking-Erkennung, Modellübersicht und Checkpoint-
Identität liegen in dieser gemeinsamen Struktur. Der bestehende Produkt-Executor
delegiert unverändert dorthin. Der separate Metadaten-Lader verwendet dieselbe
Artefakt-/Header-/Tokenizer-Validierung, öffnet aber keine Gewichts-Mappings,
GPU-Kontexte oder PLE-Leser; der kanonische Controller benötigt dafür keine zweite
Instanz des alten Modell-Executors. Sein vollständiger Chat-Test verwendet bereits
diesen Loader. Prefill-/Decode-Controller, Kernel und Persistierungsformat wurden
in diesem Schritt nicht verändert.
Vier überwachte Metadaten-/Artefakttests bestanden, darunter
pinned_qwen_metadata_matches_product_without_executor_state: mit/ohne MTP gleiche
Übersicht (2469/2527 Tensoren), gleiche Checkpoint-Identität, Direct-/Low-/XHigh-
Rendering, History und Fortsetzung einschließlich skip_previous_eos, Stop- und
Tokenbyte-Verhalten; zusätzlich bestehende Literal-Goldens und Fail-Closed-Prüfungen.
Rohdaten: local-eval-results/qwen-metadata-20260910.qJ4vq2/metadata.{stdout,stderr}.log.
Test-/Produktions-Clippy mit -D warnings, Release-Testbuild, Format-/Diffcheck
bestanden. Logs: /tmp/ds4-qwen-metadata-{clippy,production-clippy,build}.log.
Testbinary SHA256 067370d61a22354d8de9ffe7bbd98d150b647b75b8b617dd7e96447d6465c2d2.
Die vollständigen AR-/MTP-Chats mit dem separaten Metadaten-Lader bestanden danach
ebenfalls: gleiche eingefrorene Referenzen und Supervisor-/Power-/Canary-Einstellungen
wie oben, unveränderte Token-/Text-/Cache-/Boundary-/MTP- und Abbruch-Assertions.
Rohdaten ar/mtp stdout/stderr im selben Verzeichnis. AR/MTP: 571/553 Canary-Proben,
keine Fehler oder Stalls; maximale GPU-Completion im Prefill 2,261/2,347 ms, im
Decode 1,049/0,548 ms. Peak Physical 82.622.526.968/83.166.132.544 Bytes;
Supervisor-Laufzeit 59,333/57,389 s, jeweils exit 0. Keine neue gepaarte
Performance-Abnahme und keine Zuordnung der Prefill-Zeitstreuung zu diesem Patch.
Die produktive Turn-Auswahl bleibt noch auf dem alten Executor. Diese Entkopplung
schließt die gemeinsame Metadaten-Schnittstelle, nicht die Controller-/Cache-/Power-
Anbindung; noch kein neues UI-Bundle oder Nachweis der sechs Performance-Zellen.
Power-Steuerung am kanonischen Executor angebunden, 10.09.:
Execution::load nimmt jetzt den effektiven power_percent entgegen; 0 bedeutet
wie im DS4-Executor automatisch 100, Werte über 100 werden vor dem Modellladen
abgelehnt. Der reale Chat-Test bezieht den Wert aus ExecutionPreferences /
EngineExecutionSettings; Standard bleibt 100. DS4_QWEN38_TEST_POWER=75 ist nur
ein expliziter Diagnosearm, keine Änderung der Paritätskonfiguration.
Die bestehende DS4-Formel ist als throttle_delay wiederverwendet:
EWMA 0,875/0,125, Pause = Mittelwert * (100-power)/power. Separate persistente
Prefill-/Decode-Mittelwerte; keine Pause im Text-Callback. Der AR-Pfad pausiert an
seinen Forward-/Lookahead-Grenzen, MTP nach abgeschlossenen Verify-/Repair- bzw.
ContextCopy-Runden; Prefill nach ausgeführten Chunks, History-Updates und Tail,
einschließlich restaurierter Suffixe. Vor dem Schlafen wird der Modellstream
synchronisiert, damit bereits eingereichte GPU-Arbeit nicht durch die Pause läuft.
Bei 100 werden weder zusätzliche Uhren gelesen noch Commands eingereicht oder
synchronisiert. Keine Chunk-Verkleinerung, keine Kerneländerung.
Pausenzähler und tatsächliche Schlafzeit werden in den Chat-Receipts getrennt
ausgewiesen; Prefill-Zeit enthält die zusätzliche Warte-/Pausenzeit, Decode-Wallzeit
ebenfalls. Der neue kleine Metal-Test lässt ein GPU-Ereignis zunächst uneingereicht:
bei 0/100 bleibt es uneingereicht (Commit-Zähler 0, kein Sleep-Aufruf), bei 75 muss
es vor Beginn des Sleep-Aufrufs signalisiert sein. Ein Drain-Fehler darf nicht
schlafen oder einen erfolgreichen Pausenzähler erhöhen. Ein separater CPU-Test
prüft dieselbe DS4-Mittelung und ihren 100%-Bypass. Diese Power-Anbindung liegt
weiterhin im cfg(test)-Controller, nicht im produktiv ausgewählten QwenExecutor;
die gesamte EngineSettings-/MTPLX-Serverdefault-Auswahl und Produktumschaltung
bleiben offen.
Power-Verifikation: Zwei gezielte Power-Tests plus die drei bestehenden
AR-/Prefill-Treiberreferenzen bestanden unter Supervisor 2048 15 15.
Test-/Produktions-Clippy mit -D warnings, Release-Testbuild, Format und Diffcheck
bestanden; Logs /tmp/ds4-power-{clippy,production-clippy,build}.log.
Testbinary SHA256 88429c4652219fa1c3db3fd544ee672c80ef2df849631b96560fb0ec4b06380b.
Anschließend vollständige installierte Qwen-Chats, sequenziell AR100, MTP100,
AR75, MTP75, unter 81920 30 45 und durchgehendem Canary. Unveränderte
session-chat-20260910.jT3hf5/reference-{ar,mtp}-boundary.stdout.log-Referenzen,
SSD-Ngram, Chunk 2048, Low, Seed 0, gleiche Server-Flags wie im vorherigen Lauf.
Alle vier liefen bis EOS und bestanden sämtliche Prompt-/Token-/Text-/State-/
Boundary-/MTP-Cycle- sowie Owner-Abbruch-/Textstop-Assertions. Keine Assertion und
keine Referenz geändert. Zähler kumulativ über den Chat einschließlich kurzer
Abbruchproben; sie sind nicht mit der Anzahl sichtbarer Tokens gleichzusetzen.
| Modus | Supervisor s | Prefill-Pausen | Decode-Pausen | Canary-Proben | Prefill max ms | Decode max ms |
|---|---|---|---|---|---|---|
| AR 100 | 56,180 | 0 | 0 | 524 | 3,466 | 0,747 |
| MTP 100 | 56,282 | 0 | 0 | 527 | 3,780 | 0,720 |
| AR 75 | 90,502 | 7 | 2246 | 846 | 1,515 | 1,393 |
| MTP 75 | 90,247 | 15 | 892 | 844 | 2,645 | 1,130 |
Überall keine Canary-Fehler/Stalls. Bei 100 tatsächlich 0 s Schlafzeit. Bei 75
AR Prefill/Decode 7,464/22,663 s tatsächliche Schlafzeit, MTP 12,754/20,345 s.
Das Duty-Cycle-Setting ist keine Messung elektrischer GPU-Leistung; EWMA und
Aufwachlatenz erlauben keine pauschale lineare Laufzeitprognose. Peak Physical
AR100/MTP100/AR75/MTP75: 82.720.290.248 / 83.179.927.464 /
82.617.677.328 / 83.078.084.640 Bytes. Rohdaten:
local-eval-results/qwen-power-20260910.K856XD/,
{throttle,drivers,ar100,mtp100,ar75,mtp75}.{stdout,stderr}.log.
Die 100%-Läufe belegen Funktionsregression und ausgebliebene Drosselung; die
75%-Läufe belegen die aktivierte Steuerung. Kein frisches Referenzpaar, kein
Warmup-/Wiederholungsdesign, daher keine neue 2%-Abnahme aus diesen Diagnosezeiten.
Kein Bundle, Commit oder Push.
EngineSettings und MTPLX-Serverdefaults im kanonischen Einstieg (10.09.):
Execution::open(&EngineSettings) liefert Executor und bestehende TurnOptions.
Er übernimmt den installierten Modellpfad, integriertes MTP an/aus, Power und den
nativen Prefill-Chunk-Override (automatisch 2048). Die gemeinsame
effective_settings-Aufbereitung liefert nun auch im Drei-Turn-Test Engine- und
TurnSettings; die Referenzkonfiguration wird nur noch geprüft, nicht in die
Ausführungsoptionen kopiert. Der native Chunk-Vertrag entspricht dem begrenzten
Sustained-Pfad mit Final-Logits-Prefill. Die bisherige Execution::load-Methode
bleibt für unveränderte Modell-/Treiberdiagnosen ohne zusätzliche Serverdefaults.
Die Qwen-Verzweigung von MTPLX _server_runtime_env_overrides liegt als lokale
Override-Map vor: neun Family-Speed-Flags, gemeinsamer Compiled-GDN-Off-Schalter,
NAX-Verify-Default 0 und bei MTP zwingender Verify-Snapshot. Keine Env-Mutation,
keine TLS-Profilumschaltung. Gewichts-Fusion, CompilePolicy und alle produktiven
Graph-Options-Aufrufe des Controllers (auch ContextCopy-Repair) lesen diese Werte.
Explizite Operatorwerte bleiben gemäß Referenz erhalten; der zwingende Snapshot
ist dieselbe Ausnahme wie im Original. AR-Pipeline/Sync-Eval, native MTP-Tiefe 3,
Committed-History, Capture-/Repair-Flags, Cache-Snapshot-/Suffix- und Boundary-
Defaults werden in vorhandene Optionsstrukturen übersetzt. Das ist keine Abnahme
sämtlicher optionaler MTPLX-Generation-Lanes oder experimenteller Kernel-Overrides.
tools/mtplx-policy-reference.py ruft ausschließlich die Original-Konfigurations-
funktionen aus Commit e652d55e2652137a4abcf1312357abbf3eb9d692 auf, ohne Modellladen
oder Generierung. 268 AR-/MTP-Fälle: unset, explizit ein/aus, leere und ungültige
Werte, GDN-Interlock, numerische Grenzen und Boolean-Aliase. Der erste Recorder-
Lauf deckte auf, dass Capture-Commit/Deferred-Repair anders als einfache _env_truthy
mit env_bool arbeiten: Aliase enable/disabled akzeptieren, ungültige Werte
ablehnen. Rust bildet diese Leser getrennt ab. Der korrigierte Recorder behält
Fehlerfälle als solche, statt sie auszuschließen. Alle 268 Vergleiche bestanden.
Der Seed der bestehenden eingefrorenen Vollmodellreferenz bleibt explizit 0 im
Executor-Test; GenerationPreferences akzeptiert aktuell nur positive explizite
Seeds. Dieser Fixture-Override ist kein Nachweis einer Seed-0-UI-Eingabe.
Danach AR/MTP-Vollchats über Execution::open, jeweils 100 %, Low, 2K, SSD-Ngram,
Supervisor 81920 30 45 und durchgängiger Canary. Anders als zuvor keine manuell
gesetzten Qwen-Speed-, Compile-, Sustained- oder Snapshot-Flags: sämtliche 12/13
in qwen_runtime_setting protokollierten Umgebungswerte waren null; effektive
Werte exakt wie die eingefrorene Referenz. Beide Chats einschließlich aller
Prompt-/Output-/Logits-/Hidden-/Cache-/Boundary-/MTP-Cycle- und Abbruch-Assertions
bestanden. Keine Referenz und keine bestehende Assertion abgeschwächt.
AR: 562 Canary-Proben, Prefill/Decode-max 1,416/0,804 ms, Peak Physical
82.725.746.312 Bytes, Supervisor 58,395 s. MTP: 549 Proben, max 2,085/0,559 ms,
Peak Physical 83.187.169.336 Bytes, Supervisor 57,055 s. Keine Fehler/Stalls,
keine Drosselungspausen. Drei bestehende AR-/Prefill-Treiberreferenzen ohne
Servervorgaben bestanden anschließend ebenfalls.
Rohdaten: local-eval-results/qwen-policy-20260910.FBHrg3/,
{reference,reference-fixed,policy,drivers,ar,mtp}.{stdout,stderr}.log.
Finale Binary SHA256 2711ff2ae542a91d0c62d69fccc7e62de0deb4a91a884dfd9cb924e03ea559c5.
Test-/Produktions-Clippy, Release-Testbuild, Format und Diffcheck bestanden;
Logs /tmp/ds4-policy-{clippy-final,production-clippy,build-final}.log.
Der Controller ist weiterhin cfg(test); dieser neue Einstieg wird noch nicht
vom produktiven Generator ausgewählt. KV-Persistierung, produktive Umschaltung,
UI-/Harness-Abnahme und gepaarte sechsstellige Performance-Matrix bleiben offen.
Kein Bundle, Commit oder Push; keine 2%-Abnahme aus diesen Diagnosezeiten.
SSD-Checkpoint am kanonischen Live-Owner (10.09., nach dem Policy-Nachweis):
qwen_mtplx/session_checkpoint.rs verbindet den vorhandenen Referenz-Codec mit
LiveSession::save_checkpoint/load_checkpoint. Eine einzelne QWMTKV01-Datei
enthält rohe Tensorblobs und ein begrenztes Manifest; keine dtype-Konvertierung,
keine zweite Datenbank, keine neuen Writer-Threads. Die bestehende DS4-Verwaltung
übernimmt weiterhin Conversation-Key, Index, Prefix-Suche, Budget, Touch und Eviction.
Temporärdatei, sync_all und Rename folgen dem bestehenden Rust-DS4-Verfahren.
Modellidentität, Kontext, Vokabular, MTP, Tokenpräfix und vollständige Blobbereiche
werden geprüft. Abbruch-/IO-Fehler veröffentlichen weder einen partiellen Checkpoint
noch einen neuen Live-Zustand/Tag. Alte DS4QWN01-Dateien sind ausdrücklich inkompatibel
und müssen vom gemeinsamen Aufrufer als Cache-Miss/Rebuild behandelt werden.
Der modellfreie Metal-Test prüft bitgleiches Payload-/Blob-Roundtrip einschließlich BF16, Recurrent-State, MTP und Boundaries, bytegenaue IO-Zähler, fehlende Datei, Abbruch nach IO-Beginn, Modell-/Kontext-/MTP-Wechsel, ungültige Token, überlaufende und falsche Blobbereiche, falsche Tensorgrößen, Trunkierung und altes Dateiformat. Alle Fälle bestanden; ein fehlgeschlagenes Speichern bewahrt die vorherige Datei, fehlgeschlagenes Laden den vorherigen Live-Zustand.
Der bestehende vollständige Drei-Turn-Oracle besitzt nun einen optionalen
DS4_QWEN38_CHECKPOINT_DIR-Diagnosepfad: nach jedem natürlich beendeten Turn
Speichern und KvStore::record, alle Live-Snapshots und die Engine verwerfen,
Engine erneut öffnen, KvStore erneut öffnen/find/touch und von SSD laden.
Es handelt sich um eine prozessinterne Engine-Neuöffnung, noch nicht um einen
Neustart des produktiven UI-Prozesses. Die Folge-Turns behalten unverändert sämtliche
eingefrorenen Prompt-/Output-/Logits-/Hidden-/Boundary-/MTP-Cycle-Assertions. Kein
RAM-Prefix bleibt als alternative Quelle erhalten. Summary → Story → Python
bestand AR und MTP bei Power 100, Low, Chunk 2048; keine Drosselungspausen, keine
zusätzlichen Voll-Prefills der bereits gecachten History.
| Modus | Checkpointgrößen, Turn 0/1/2 (Bytes) | Speichern (ms) | Laden (ms) | GPU-Canary max, gesamt / Prefill / Decode (ms) |
|---|---|---|---|---|
| AR | 675831746 / 714926075 / 723427506 | 359,805 / 519,763 / 438,827 | 181,206 / 217,471 / 185,126 | 6,126 / 1,485 / 0,711 |
| MTP | 678764762 / 722567188 / 733621273 | 366,524 / 406,042 / 385,907 | 172,320 / 183,714 / 176,829 | 3,996 / 1,264 / 0,527 |
Canary durchgängig inklusive Speichern/Neuladen, 812/727 Proben, jeweils null
Fehler/Stalls. Die Gesamtmaxima liegen in Loading; dessen Phasenlabel umfasst
hier auch das SSD-Laden. Supervisor-Gesamtzeit 86,094/77,604 s, maximale Physical-
Footprints 81.629.560.424 / 82.099.961.736 Bytes. Genau ein Modellprozess, kein
Download, Supervisor 81920 30 45; kein Gesamtlaufzeitlimit. Der kleine Test lief
separat mit 2048 15 15. IO-/Neuladezeiten sind Diagnosewerte mit aktivem Canary
und warmem OS-Dateicache, keine SSD-Kaltstart- oder Performance-Paritätsabnahme.
Rohdaten: local-eval-results/qwen-checkpoint-20260910.clSZAD/,
{small,ar,mtp}.{stdout,stderr}.log, Testcheckpoints in {small,ar-cache,mtp-cache}.
Referenzen unverändert: local-eval-results/session-chat-20260910.jT3hf5/,
reference-{ar,mtp}-boundary.stdout.log.
Binary SHA256 8e87e337ac78c502d0d03fccd7f375b61e13ae4cb446c88fad5aa99bcf7feda3.
Test-Clippy und Release-Testbuild bestanden, Logs /tmp/ds4-checkpoint-{clippy,build}.log.
Historischer Integrationsblocker (durch den folgenden Anschluss überholt):
qwen_mtplx bleibt cfg(test); der produktive
Generator wählt noch den alten Executor. Der neue Dateiadapter ist mit dem realen
KV-Index im Vollmodelltest geprüft, aber noch nicht mit Bootstrap, Sessionwechsel,
Kompaktierung und der produktiven Backend-Umschaltung verbunden. Erst deren
Anschluss macht diese Nachweise für UI und produktive Harness wirksam. Keine
UI-/Harness- oder 2%-Abnahme, kein Bundle, Commit oder Push.
Produktiver Owner angeschlossen (10.09., nach dem SSD-Checkpoint-Nachweis):
Generator::open wählt Qwen jetzt vor dem alten LoadedModel-Loader über
Executor::open_qwen aus. qwen_mtplx ist nicht mehr test-exklusiv. Der neue
owner.rs delegiert vollständige Turns an LiveSession, einschließlich AR/MTP,
anstatt den alten skalaren Generatorloop zu benutzen. Bootstrap-/Suffix-Prefill,
Reset, Resident-Sessionwechsel und Checkpoint-Dispatch erreichen denselben Owner.
Die gemeinsame Runtime bleibt der Einstieg von UI und model-eval. Der alte
Qwen-Executor bleibt für Diagnosepfade vorhanden, wird vom Generator nicht gewählt.
qwen_product_generator_chat_matches_reference bestand AR und MTP mit den
unveränderten drei eingefrorenen Referenzturns: natürliche Abschlüsse, exakte
Prompt-/Output-Tokens, Reasoning/Text sowie finale Logits-/Hidden-Hashes. Nach jedem
Turn werden Resident-Sessionwechsel und SSD-Restore über den wirklichen Generator
geprüft. Zusätzlich bestehen kalter und fortgesetzter Pure-Prefill und dessen
Abbruch ohne Veröffentlichung eines partiellen Zustands.
Rohdaten: local-eval-results/qwen-product-20260910.8EeH8M/,
{ar,mtp}.{stdout,stderr}.log; Testbinary SHA256
4cb3f4e0b9e26f441088b8367f7d53a33f6a584a07424cc4ee0e356f44501e7d.
Testzeiten AR 59,52 s / MTP 52,49 s, Canary 555 / 489 Proben, null Fehler/Stalls,
Maximum 3,475 / 4,045 ms. Dies sind überwachte Integrationstests, keine gepaarte
Performance-Abnahme. Die groben Phasen umfassen auch nachfolgende Checkpointarbeit;
ein UI-Render-/Eventloop-Nachweis ist damit nicht erbracht. Der OS-Disk-Write-Zähler
enthält ungültige Werte und ist kein Durchsatznachweis.
Offen nach diesem Anschluss: tatsächlicher Bootstrap-/Kompaktierungsablauf und Abbruch/Fortsetzung im Generator, normaler Release-Worker mit prozesskaltem Ping, Release-Bundle samt UI-Nachweis sowie die vollständige Performance-Matrix. MTP-Zähler werden bisher am Turn-Ende veröffentlicht, PLE-Hot-Cache-Zähler sind angebunden, weitere SSD-Zähler noch nicht. Die gemeinsame Buffer-Ownership wurde für Produktion aktiviert; Auswirkungen auf DS/GLM müssen mitgemessen werden. Optionale Referenz-APIs und historische Diagnoseadapter sind kein Nachweis, dass alle optionalen MTPLX-Policies produktiv integriert sind.
Lebenszyklus-Nachprüfung, erster Lauf: Der ergänzte
DS4_QWEN38_TEST_LIFECYCLE=1-Pfad prüft nach dem Chat den echten
prepare_bootstrap samt Cache-Hit und Generator::compact samt Rebuild.
AR bestand die drei Referenzturns erneut, wurde danach im Kompaktierungs-Prefill
vom externen 80-GiB-Limit beendet: Physical-Peak 86.164.456.144 Bytes, Lauf
68,460 s, memory_limit. Kein erfolgreicher Kompaktierungsnachweis. Bis zum
Abbruch lagen Canary-Proben vor; eine finale Canary-Zusammenfassung fehlt wegen
des Supervisor-Abbruchs. Rohdaten ar-lifecycle.{stdout,stderr}.log im obigen
Produktverzeichnis. Wiederholung mit 88 GiB überwachten Speichergrenze, unveränderten
Modellparametern und unveränderter Ausführung; kein künstliches Cache-Leeren oder
Verkleinern von Prefill-Chunks. Testbinary SHA256
6c72d5d8ba2ef563a4b5d945d4dc7d0098b16f849be0f126fdc10998eac308d8.
Lebenszyklus erfolgreich nachgeprüft (10.09.): Die unveränderte Wiederholung
mit 88-GiB-Watchdog bestand AR und MTP einschließlich drei Referenzturns,
Bootstrap (37 Tokens), erneutem Bootstrap ohne Prefill und Kompaktierung samt
gespeichertem Rebuild. Rebuild 1961 / 2138 Tokens, jeweils tail_start=2,
nichtleere sinnvolle Task-State-Summary. Supervisor 69,176 / 64,457 s,
Physical-Peak 86.300.246.808 / 86.341.305.472 Bytes. Canary 643 / 599 Proben,
null Fehler/Stalls, Maximum 3,014 / 3,385 ms. Rohdaten
{ar,mtp}-lifecycle-88g.{stdout,stderr}.log. Die erhöhte Supervisorgrenze verändert
nicht die Engine oder ihre Speicherpolicy; kein Nachweis eines behobenen Leaks.
Normaler Release-Worker, kalter Ping (10.09.): --warmup off ist im
model-eval verfügbar, Default bleibt on; Options-Test bestanden. Normale
Binary SHA256 89d6ef5ea14fbfdb980d4512aee89fbbb77955964f6f52ad8e4c963dd58c9f97,
kein Testbinary-Einstieg. Power 100, Low, Chunk 2048, Kontext 32768,
Temperatur 0,6, top-p 0,95, min-p 0, Seed 42, Plain-Chat, maximaler Produkt-Tokenwert,
Canary an, 80-GiB-Watchdog, Startup 30 s / Fortschritt 45 s. Keine Downloads,
isolierte temporäre Sessions, kein Warmup und kein globales Leeren des OS-Dateicaches.
AR/MTP enden natürlich mit „Pong!“, 55 / 63 Completion-Tokens. Gesamt
10,157 / 9,384 s, Laden 6,406 / 5,495 s, gemeldetes Prefillfenster
2,617 / 2,296 s (einschließlich Systembootstrap), Decode 0,953 / 1,409 s.
Die 41 Prompttokens enthalten 30 im selben kalten Lauf aufgebaute Bootstrap-Tokens;
der Quotient aus 11 Suffix-Tokens und dem gesamten Prefillfenster ist deshalb
keine reine Kernel-Prefillgeschwindigkeit. Keine Paritätsabnahme aus kaltem Ping.
Canary-Maximum 3,703 / 3,935 ms, im Prefill 0,629 / 0,628 ms; kein Stall.
Headless-Control-Loop-Maximum 57 / 47 ms ist keine Messung des GUI-Eventloops.
Rohdaten cold-ping-{ar,mtp}.{stdout,stderr}.log im Produktverzeichnis.
Dabei neu belegt: normale GPU-Busy-/Command-Buffer-Zähler bleiben fälschlich null. Der bisherige Recorder hängt am nativen DS4-Wait, den der kanonische MTPLX-Pfad nicht benutzt. Die separate Canary-Messung ist davon unabhängig. Der Anschluss an MTPLX-Command-Completion ist in Arbeit; keine zusätzlichen GPU-Waits/Flushes als Instrumentationsersatz. Diese Nullwerte sind nicht als GPU-Leerlauf auszuwerten.
GPU-Busy-Instrumentation korrigiert und nachgeprüft (10.09.): Der vorhandene
native Recorder ist nun auch an die asynchrone MTPLX-Command-Completion angeschlossen.
Mutexgeschützte Snapshots verhindern konkurrierende Zugriffe von UI/Worker und
Completion-Thread; eine Mess-Epoche schließt nach Reset verspätet eintreffende
MTPLX-Completions aus dem vorherigen Messfenster aus. Keine neue GPU-Arbeit,
kein zusätzlicher Wait, Flush oder geänderter Kernel-/Submission-Plan.
Der bestehende Encoder-Regressionscheck prüft nun positive GPU-Zeit und exakt
eine Buchung je Command-Buffer auch nach späterem Wait; Canary-Probes bleiben
ausgeschlossen. Bestanden unter test-supervisor 2048 15 15,
busy-counter.{stdout,stderr}.log, Testbinary SHA256
c7cf8b3d524673dad7e1cfeec6de4b7e419129c34f073f042dc377b80234136e.
Erneuter normaler Release-Ping AR/MTP mit unveränderten Parametern, jeweils
prozesskalt: natürliches Ende, exakt gleiche Tokenzahlen, Reasoning und Antworten
wie vor der Messkorrektur. Binary SHA256
4763e16687ed53c787825a391f45d51d6fe793f8bb6dc157bf7d4dfd627458ec.
Rohdaten cold-ping-{ar,mtp}-busy.{stdout,stderr}.log im Produktverzeichnis.
| Messung | AR | MTP |
|---|---|---|
| Gesamter Request inklusive Laden (s) | 8,630 | 8,721 |
| Modellladen (s) | 5,505 | 5,494 |
| Prefillfenster inklusive Bootstrap (s) | 1,989 | 2,276 |
| Decode-Loop (s) | 0,950 | 0,773 |
| Completion-Tokens | 55 | 63 |
| Decode-Loop tok/s | 57,90 | 81,54 |
| GPU-Zeit, Summe der Command-Buffer (ms) | 2121,73 | 1980,39 |
| Längster Command-Buffer (ms) | 112,22 | 120,46 |
| Command-Buffer | 12730 | 9162 |
| GPU-Canary max, gesamt / Prefill (ms) | 3,444 / 0,616 | 3,873 / 0,620 |
| Headless-Control-Loop max (ms) | 52 | 59 |
Canary 82 / 84 Proben, null Fehler/Stalls, Supervisor Exit 0. Summierte GPU-Zeit ist keine queueübergreifende Vereinigungszeit. Unterschiedliche Pipeline-/OS- Caches zwischen Prozessstarts verhindern eine Performance-Aussage aus dem Vorher/Nachher-Ping; insbesondere die schnellere MTP-Wiederholung ist kein belegter Beschleunigungseffekt der Messkorrektur. CPU-Overhead der Completion- Instrumentation bleibt Teil der noch offenen warmen Referenzabnahme. Normaler Headless-Einstieg ist jetzt geprüft, ein neues GUI-Bundle und GUI-Eventloop-Nachweis bleiben offen. Keine Behauptung der vollständigen 2%-Parität.
Laufende MTP-Zähler und Abbruch/Fortsetzung nachgewiesen (10.09.):
Der kanonische decode_mtp meldet über den vorhandenen TurnProgress-Kanal jeden
abgeschlossenen Zyklus. Der produktive Owner veröffentlicht diese Werte sofort
in denselben atomaren Metrics, die UI und Harness lesen. Keine neue GPU-Arbeit,
kein zusätzlicher Thread und keine zusätzliche Synchronisation. Der bisherige
Turn-Ende-Sammelpass entfällt, damit keine doppelte Buchung entsteht. Verifier-
und Repair-Zeiten bleiben bis zur Umrechnung kumulativ innerhalb des Turns;
Sub-Millisekunden-Anteile werden nicht je Zyklus abgeschnitten. Bei Abbruch bleibt
der letzte beobachtete abgeschlossene Zyklus erhalten; unvollständige Zyklen
werden nicht als abgeschlossen behauptet.
Zusätzliche Zählkorrektur: Context-Copy-Runden führen ebenfalls einen gebatchten
Target-Verifier aus. Vorher wurden sie bei verifier_passes ausgelassen.
Der eingefrorene MTP-Chat enthält pro Turn 148+7, 640+2 und 93+2
MTP-/Context-Copy-Verifikationen. Native MTP-Draft-/Acceptance-Zähler zählen weiter
nur die nativen Drafts, nicht die kopierten Kontexttokens. Der modellfreie Test
prüft Live-Publikation ohne Turn-Ende, Zeit-Rundung, Context-Copy-Verify, Primary-EOS
ohne Verify und ausbleibende Doppelbuchung beim Finalize; bestanden.
Der vollständige Produkt-Generator-Test prüft jetzt zusätzlich, dass MTP-Zähler bereits während der Textausgabe eintreffen, und vergleicht nach jedem Turn deren Delta mit allen eingefrorenen Referenz-Cycles. AR muss die MTP-Zähler unverändert lassen. Beide Modi bestehen weiterhin exakte Tokens, Texte, Logits-/Hidden-Hashes, Resident-Switch und SSD-Restore.
Im erweiterten Lebenszyklustest wird auf einem kopierten Checkpoint ein ununterbrochener Kontrollturn erzeugt. Abbruch vor Decode und während Decode müssen die Originaldatei SHA256-identisch erhalten. Nach Aufhebung des Abbruchs muss derselbe Request dieselben finalen Tokens, Reasoning und Text wie der Kontrollturn liefern. AR und MTP bestanden jeweils mit 23 Completion-Tokens und „PONG“. Abgeschlossene MTP-Zähler bleiben auch nach Abbruch sichtbar. Bootstrap- Cache-Hit und Kompaktierung/Rebuild bestehen anschließend ebenfalls. Dies testet den produktiven Generator, nicht UI-Buttonzustände oder jeden denkbaren IO-Abbruch.
Rohdaten: local-eval-results/qwen-live-metrics-20260910.iD9AZm/,
{unit,ar,mtp}.{stdout,stderr}.log, isolierte Checkpoints in {ar,mtp}-cache.
Testbinary SHA256 d9c6fd174b51af793b61d0f06740cdc398fa85778fb8ec8d908ec442cbefa75b.
Power 100, Low, Referenz-Seed 0, Chunk 2048, Kontext 32768; nur installierte
Gewichte. Volltests test-supervisor 90112 30 45, kleiner Test 2048 15 15.
AR/MTP Supervisor 72,130 / 70,118 s; Physical-Peak 86.596.617.488 /
86.535.603.592 Bytes. Canary 672 / 651 Proben, keine Fehler/Stalls, Maximum
3,004 / 3,192 ms, im Prefill 0,887 / 0,998 ms. Keine warmen gepaarten
Performance-Abnahmen aus diesen Integrationsläufen. Clippy-Log
/tmp/ds4-live-mtp-clippy3.log, Build /tmp/ds4-live-mtp-test-build.log.
Die normale Harness serialisiert die kumulativen speculation-Felder nun auch
in runtime_sample, nicht nur als Turn-Delta im Endergebnis. Ein normaler
Release-Lauf zur Nachprüfung dieses JSON-Einstiegs ist wie folgt bestanden.
Warmer laufender Chat über die normale Headless-Binary (10.09.):
warm-chat-mtp.{stdout,stderr}.log im selben Verzeichnis, normale Binary SHA256
b74e3126e911b3f57d83829ee216c77d45fbe29fb597694ab28c2895ec1301dc.
model-eval --warmup on --plain-chat on, README-Summary → Lighthouse-Story →
Python is_prime mit fünf Assertions, ein zusammenhängender Chat. Power 100,
Low, Chunk 2048, Kontext 32768, Temperatur 0,6 / top-p 0,95 / min-p 0, Seed 42,
MTP an, Canary an, Speicherwatchdog 88 GiB, Startup 30 s / Fortschritt 45 s.
Keine Gesamtzeitbegrenzung; alle drei Messturns enden natürlich mit stop.
README SHA256 80c01ea096843312de6662d3cd8c94c8e14bdf286b58824752981fc4920fd1f8.
Der vollständige erste Prompt ist nach direktem JSON-Vergleich bytegleich mit
reference-mtp-boundary.stdout.log; die frühere Annahme eines abweichenden
README-Inhalts ist damit verworfen. Referenz-Seed 0 und erster Referenz-Prefill
ohne Bootstrap-Reuse unterscheiden sich von diesem Lauf: weiterhin keine
gepaarte Performance-Abnahme, keine Verrechnung als 2%-Pass.
| Messturn | Prompt / cached / completion | Gesamter Turn (s) | Prefillfenster tok/s | Decode-Loop tok/s |
|---|---|---|---|---|
| Summary | 2748 / 30 / 519 | 9,446 | 1304,22 | 72,14 |
| Story | 3296 / 3268 / 1450 | 28,113 | 264,15 | 52,13 |
| Python | 4780 / 4747 / 230 | 3,151 | 242,65 | 81,00 |
Während Decode enthält die Harness 7 / 27 / 3 runtime_sample-Ereignisse mit
steigenden kumulativen Cycle-Zählern 36→185 / 208→841 / 868→913, nicht erst
ein Endergebnis. Summary fachlich lesbar, abgeschlossene Lighthouse-Geschichte
ohne Rückfrage, Python-Code vor Ausführung geprüft. Die generierten fünf Asserts
und ein unabhängiger Trial-Division-Vergleich für -10 bis 5000 (5011 Fälle)
bestehen unter isoliertem Python mit 3-s-CPU-Grenze; keine Imports im generierten
Code, keine Netzwerk-/Toolnutzung. Beleg python-validation.stdout.log.
Gesamtprozess einschließlich Warmup 49,581 s, Supervisor Exit 0, maximaler
Fortschrittsabstand 1,625 s. Canary 456 Proben, null Fehler/Stalls, Maximum
3,293 ms; Headless-Control-Loop-Maxima 53 / 37 / 33 ms. Der Supervisor meldet
82.983.156.272 Bytes als abgetasteten Peak-Footprint; dieser ist kein lückenloser
Kernel-Lifetime-Peak. GPU-Busy-Zähler sind in allen Turns positiv. Clippy und
Formatprüfung bestehen (/tmp/ds4-live-mtp-final-clippy.log). Kein GUI-Bundle,
kein GUI-Eventloop-Nachweis und keine vollständige Referenzmatrix in diesem Schritt.
Warmer Bootstrap-Suffix: Vergleichsprofil und Boundary-Lücke (10.09.):
Die ersten Vergleichspaare unten sind Zwischendiagnosen, keine Freigaben.
Die strengere Zustandsprüfung deckte danach einen nicht angeglichenen Sustained-
Prefill-Modus auf. Maßgeblich ist die abschließende Profilkorrektur unten.
Der angeglichene Referenztreiber tools/mtplx-execution-reference.py --source-run
übernimmt den vollständigen normalen Harness-Startvertrag einschließlich
Warmup, Seed 42, Sampler-Floatwerten und Bootstrap-Reuse. Er akzeptiert nur drei
natürlich abgeschlossene Plain-Chat-Turns und prüft je Turn Prompt-, Cache- und
Ausgabetokenzahl sowie den vollständigen Text. Der erste Versuch gegen den oben
genannten alten Stand scheiterte ausdrücklich: Summary 448 statt 519 Tokens.
Rohdaten: local-eval-results/qwen-matched-warm-20260910.ig0qT1/.
Erste Untersuchung: MTPLX _prefill_restored_prompt_suffix übergibt die
Chunkgröße implizit. Ohne MTPLX_SUSTAINED_PREFILL ist zunächst der gesamte
Body ein Span, den die aktive rekurrente Boundary-Policy auf ihr 256er-Tailraster
aufteilt. Der kalte committed-MTP-Pfad dagegen übergibt 2048 explizit. Rust hatte
im warmen Pfad eine eigene gleichmäßige 2048er-Schleife und erfasste dort keine
Boundaries. Der erste Patch verwendete den vorhandenen prefill::spans-Helper
mit denselben Regeln und erfasst absolute rekurrente Zwischenzustände vor dem
History-Append. Optionale Capture-Fehler brechen wie im Original den Turn nicht ab.
Keine pauschale Änderung des UI-Chunkwerts und keine neue Cache-Persistenz.
Der neue normale MTP-Chat und der anschließende unveränderte MTPLX-Lauf stimmen für alle drei Turns in Prompt-/Cache-/Ausgabetokenzahlen und vollständigem Text überein: 2748/30/448, 3225/3197/997, 4256/4223/301. Beide enden natürlich. Summary-Prefill-Fortschritt nun in beiden Pfaden: 30, 286, 542, 798, 1054, 1310, 1566, 1822, 2078, 2334, 2590, 2747, 2748. Damit ist die neue Warm-Prefill-Lücke nicht bloß durch ein anderes gesampeltes Ergebnis verdeckt.
Rohdaten: local-eval-results/qwen-warm-suffix-20260910.vWPeE5/,
product-mtp-metal.{stdout,stderr}.log und reference-mtp.{stdout,stderr}.log.
Binary SHA256 bff5b55c15a101f236f6bf3466d62154417ef9a93ee235b7efbae6ee570eddd9.
MTP-Produkt: 401 Canary-Proben, null Fehler/Stalls, Maximum 3,158 ms,
Headless-Control-Loop-Maxima 38/32/44 ms. Prozess inklusive Warmup 43,565 s,
abgetasteter Peak-Footprint 80.643.439.968 Bytes. Referenz-Supervisor Exit 0,
44,238 s und Lifetime-Peak 81.251.187.272 Bytes. Sein Disk-Write-Rohzähler läuft
erneut über und ist kein brauchbarer IO-Nachweis.
Boundary-Regressionstest und Referenztreiber-Vertragstest bestehen, Release-Build und fokussiertes Release-Clippy bestehen. Ein erster Sandbox-Versuch endete vor der Inferenz mit fehlendem Metal-Gerät; der oben ausgewertete Lauf erfolgte mit Metal-Zugriff. AR-Vergleich und exakte finale Tensor-/Tokenprüfung des warmen Produkt-Generators folgen. Canary aktiv, Einzelpaare und teils parallele CPU-Kompilierung: ausdrücklich keine saubere 2%-Performance-Abnahme.
Strengerer Nachweis und abschließende Profilkorrektur: Der vorhandene
Produkt-Generator-Test unterstützt nun Bootstrap/Warmup vor dem laufenden Chat
und prüft neben exakten Tokens, Texten und finalen Logits-/Hidden-Hashes auch
rekurrente Boundary-Positionen. Der erste MTP-Turn scheiterte (exact-mtp.*):
Rust bewahrte Bootstrap-Boundary 29, die Referenz nicht. Ohne Sustained-Modus
wählt MTPLX für den kalten MTP-Bootstrap _prefill_with_hidden_sequence ohne
Boundary-Capture; die UI nutzt hingegen den begrenzten Streaming-Pfad.
Der vorhandene mtplx-policy-reference.py bildet diese native Policy bereits
mit MTPLX_SUSTAINED_PREFILL=1 ab. Dies fehlte im neuen Chat-Referenztreiber.
Der Treiber setzt jetzt denselben Sustained-Modus und den originalen request-lokalen Chunk-Override. Rusts warmer Pfad verwendet entsprechend den vorhandenen Spans-Helper mit 2048er-Hauptchunks und 256er-Unterteilung nur im letzten Body-Chunk. Die zwischenzeitliche Unterteilung des gesamten Bodys nach dem nicht angeglichenen Referenzprofil ist zurückgenommen. Die echte Korrektur sind das fehlende Tail-Raster und absolute Captures vor dem History-Append, nicht eine allgemeine Chunkverkleinerung. Optionales Capture bleibt wie im Original fehlertolerant. End-to-end-Nachweise dieses endgültigen Profils stehen zum Zeitpunkt dieses Eintrags aus; obige Text-Pässe ersetzen sie nicht.
Zusätzlich korrigiert: Der erste AR-Referenzlauf verlor den Bootstrap-Hit,
weil der Treiber hidden_variant=None statt der vom originalen Resolver
normalisierten Identität post_norm bankte. Nach Korrektur passen auch dort
die Texte aller drei Turns (reference-ar-policy.*), jedoch noch unter dem
zwischenzeitlichen Nicht-Sustained-Profil. Das war kein Produktfehler.
Endgültiges Sustained-Profil in beiden Modi bestanden (10.09.):
local-eval-results/qwen-warm-suffix-20260910.vWPeE5/manifest.md trennt alle
Zwischenstände von den maßgeblichen *-sustained.*-Receipts. Die normalen
UI-Runtime/Headless-Chats und originalen MTPLX-Chats stimmen in allen drei Turns
überein: AR 570/1129/266, MTP 438/1144/279 Ausgabetokens. Der erweiterte
Produkt-Generator-Test besteht für beide Modi außerdem exakte Tokens inklusive
EOS, finale Logits-/Hidden-Hashes, rekurrente Grenzen, laufende MTP-Zähler,
Resident-Wechsel und SSD-Restore. Die separate Lifecycle-Cancel-Erweiterung
wurde in diesen Wiederholungen nicht zugeschaltet. Python-Ausgaben bestehen
je fünf Assertions und 5011 unabhängige Fälle. Die fehlgeschlagenen strengeren
Tests bleiben erhalten; keine Abschwächung der Assertions für den grünen Stand.
Normale AR/MTP-Canary-Maxima 3,741/3,471 ms, null Fehler/Stalls; kein tatsächlicher
GUI-Eventloop-Nachweis. Release-Binary SHA256
0ecc5f13e94a78f71c116d877ab0fa0101edf76e2b9b4cfdecc40c927d7e1b90.
Fokussierte Tests, Clippy und Formatcheck bestanden. Die auffällig langsame
AR-Referenz in diesem Einzelpaar wird nicht als bewiesener Produktvorteil
gewertet: saubere alternierende Wiederholungen ohne Canary stehen aus.
GLM-2-Row-Verify, vollständige sechszellige Performance-Abnahme und aktualisiertes
GUI-Bundle bleiben offen. Die Warm-Prefill-Funktionslücke ist damit geschlossen,
nicht das gesamte Paritätsziel.
Drei alternierende Paare pro Qwen-Modus ohne Canary — keine Abnahme (10.09.):
local-eval-results/qwen-clean-pairs-20260910.Y2DWsl/{manifest.md,comparison.json}
enthält zwölf natürlich abgeschlossene Prozesse mit identischen Antworten und
vollständigen Settings-/Rohdatenbelegen. Reihenfolge pro Modus P1,R1,R2,P2,P3,R3;
Power100, Low, gleiche Warmup-/Bootstrap-/Sustained-Verträge, kein Build parallel.
Die Referenz kann mit --token-events progress die Token-JSON-Ausgabe auf echten
Fortschritt einmal pro Sekunde begrenzen; Tokens/Text bleiben vollständig in den
End-Receipts. Kleiner modellfreier Test prüft die Rate und verhindert Fortschritt
ohne neue Tokens. Beide Canary-Summaries bestätigen jeweils null Proben.
Der frühere günstige Einzelvergleich ist keine ausreichende Freigabe: Im zweiten Paar liegt Rust AR bei Summary/Story/Python 2,34/4,63/10,71% hinter MTPLX, MTP 6,48/4,26/3,24%. Im ersten und dritten Paar ist Rust schneller; beide Programme driften im Verlauf stark. Kein Aussortieren langsamer Läufe oder Median-Pass. MTP-Story behält 515 Cycles / 1539 Drafts / 624 Accepts, doch GPU-Busy steigt 17,193→21,100s und CB-Zahl 142256→147830; Checkpoint-Write bleibt 358→366ms. Das verengt die Suche, beweist aber weder thermisches Drosseln noch einen Rust-Schedulerfehler. Die GPU-Clock-/Temperaturzeitreihe fehlt.
Passive Diagnose: macOS meldete keine Thermalwarnung und normalen Speicherdruck. Powermetrics ist ohne Administratorpasswort nicht verfügbar. Das installierte mactop lieferte zwei Idle-Samples, beendete sich aber mit Exit139; dieser Hilfsprozess ist kein verlässlicher Zusatzmonitor und wurde nicht in die Benchmarkserie eingebaut. Die Rust-Speicher-/Fortschrittswächter blieben aktiv. Nächster Messblock: zuverlässige optionale passive Geräte-Telemetrie und Submission-/GPU-Zeitkorrelation; Prefill-Zeitgrenzen getrennt angleichen. Keine Behauptung, das gesamte Ziel sei nur durch Messrauschen verfehlt: Ursache bleibt zu belegen, GLM-2-Row-Verify und DS/GLM-Abnahme bleiben offen.
Prompt-Eval-Messgrenzen im gemeinsamen Produktpfad veröffentlicht (10.09.):
local-eval-results/qwen-prompt-timing-20260910.gPvUlU/{manifest.md,comparison.json}
belegt vier vollständige serielle Chats (Produkt/MTPLX, AR/MTP). Die bereits
berechneten Target-/History-/Restore-Zeiten werden vor Decode über dieselben
MetricsSnapshots veröffentlicht, die UI und Harness beobachten. Das bisherige
UI-Prefillfenster bleibt unverändert; nicht verfügbare Messung bleibt null,
gemessener Exact-Hit darf null Sekunden haben. Keine neue GPU-Arbeit oder
Änderung der Ausführungsstrategie. Regressionstest prüft Reset und dass spätere
Checkpoint-/Decode-Arbeit die Promptzeiten nicht verändert.
Alle Antworten/Tokenzahlen stimmen mit Original und vorheriger Clean-Serie überein. Die neue Sicht grenzt einen verbleibenden MTP-Summary-Rückstand ein: Eval Rust 2,999957s / MTPLX 2,887888s, also -3,736% Durchsatz; History 52,902 / 52,791ms, Target 2,947055 / 2,835097s. In diesem Paar liegt der Rest im Target-Intervall, nicht im History-Aufbau oder Checkpoint. Ursache innerhalb Target (GPU-Takt/Dispatch/Streaming/Kernel) weiter offen. Andere Turns in diesem Einzelpaar schneller, aber keine Aufhebung der vorherigen Drift und kein 2%-Pass. Originale Prompt-State-Gesamtzeit und UI-Phase bleiben wegen zusätzlicher Arbeit ausdrücklich getrennt. Alle Wächter beendet ohne Fehler; Canary aus, kein GUI-Eventloop-Nachweis. Fokussierter Regressionstest, Treibertests, Release-Clippy, Build, Format- und Diffcheck bestanden. P14–P16 und Bundle weiter offen.
Restumfang (historisch; nachfolgende Produktnachweise oben beachten): Nicht-streamender Hidden-Sequence-Prefill und Session-Restore, optionale Prefill-Cleanup-/Repaging- und recurrent Boundary-Snapshot-Pfade mit dem AR-Decode verbinden, Default-GPU-RNG in den Owner integrieren, verbleibende MTP-Options-/Requestpfade und die Guard-/Drain-Übergänge einschließlich Owner-Progress sowie die produktive UI/Harness-Integration abschließen. Die sechs vollständigen Geschwindigkeitsvergleiche sind noch abzuschließen. Diese Modulnachweise sind kein Nachweis der vollständigen spekulativen Generierung oder der Performance-Parität aller drei Modelle.
Realer MTP-Head mit Draft/Verify/Commit, 2026-09-10:
Der persistente Execution-Pfad besitzt zusätzlich den MTP-QSA-Cache und
verwendet die bestehenden TextModel::mtp_forward-/mtp_update_cache-Graphen
über draft und append_mtp_history. Trunk-Aufrufe geben den bereits
modellseitig gehaltenen Widened-Stream weiter; Float32-Diagnose nutzt denselben
Auswerter für Logits und Hidden States. Keine neuen Kernel oder Engine-Duplikate.
Der Vollmodell-Oracle tools/mtplx-execution-reference.py --mtp lädt den
installierten Head über das originale Model.attach_mtp. Er prüft eine
zusammenhängende echte Modelloperationsfolge, nicht den vollständigen
generate_mtpk-Sampler/Generator:
- Kalter Ping: Promptkörper (40 Tokens) und letztes Token getrennt, entsprechend
generation._prefill_with_hidden_sequence; 40 verschobene Hidden/Token-Paare für den Draft-Cache. Kein ungeteiltes 41-Token-MTP-Prefill. - Drei rekursive Draft-Aufrufe mit dem tatsächlich geladenen Head, anschließend Vier-Token-Verify mit originalem Capture-Scope und GDN-/PLE-Snapshots.
- Tatsächliche Greedy-Ablehnung nach dem ersten akzeptierten Draft: zwei von
vier Verify-Eingaben bleiben. Originaler
commit_verified_window, MTP-Trim von Offset 43 auf 41, Erhalt der ersten autoritativen Draft-Zeile, Ergänzung nur der folgenden Target-Historie bis Offset 42. Dies entspricht dem Retain-/Reappend-Pfad ingeneration.generate_mtpkum Zeile 12110. - Nächster Target-Aufruf und nächster Draft bei Offset 43 prüfen die Wirkung des Commits auf die Fortsetzung, nicht nur die Rückgabewerte des Trim-Aufrufs.
Referenz und Rust stimmen für alle 40 Prefill-Logit-Reihen sowie 16 vollständige
Logit-/Hidden-State-Fingerprints, Shapes, Greedy-Entscheidungen und Cache-Offsets
bitgenau überein. Zwei separat geprüfte Konfigurationen: direkte Modell-Defaults
und originale MTP-Server-Familiendefaults (13 protokollierte Werte, einschließlich
MTPLX_SKIP_VERIFY_SNAPSHOT=0). Das Rust-Testprogramm prüft diese Umgebungswerte
vor dem Laden, ebenso Vollständigkeit und Reihenfolge der Referenzoperationen.
Rohdaten im bestehenden execution-20260910.Ngpzu7/:
reference-mtp-retained.* / canonical-mtp.* (Familiendefaults),
reference-mtp-plain.* / canonical-mtp-plain.* (direkte Defaults).
Das frühere reference-mtp.* ist durch den Retain-Abgleich ersetzt: es baute
die erste bereits autoritative Draft-Zeile unnötig neu auf und ist keine
Abnahmegrundlage. Sein Disk-Write-Rohzähler enthält zudem einen offensichtlich
ungültigen OS-Wert nahe u64::MAX; daraus werden keine IO-Leistungswerte abgeleitet.
Alle vier maßgeblichen Prozesse einzeln unter unverändertem
test-supervisor 81920 30 45 und durchgehendem 100-ms-GPU-Canary mit 2-s-Abbruch.
Keine Canary-Fehler, alle Prozesse regulär beendet. Lifetime-Peak MTPLX/Rust:
76.770.450.672 / 76.379.298.192 Bytes (Familie),
74.458.239.088 / 74.179.498.048 Bytes (direkt).
Canary-Maxima MTPLX/Rust 4,170 / 15,104 ms (Familie) und
3,911 / 92,204 ms (direkt). Beide Rust-Ausreißer liegen im Laden, nahezu
vollständig bis zur Scheduling-Rückmeldung. Der Host-gemessene Wait-Wert
trennt hier GPU-Scheduling und verspätete Probe-Thread-Rückkehr nicht; die
Latenzdifferenz bleibt offen, wird nicht durch das 2-s-Risikoflag wegdefiniert.
Release-Testbuild, gezieltes warnings-denied Clippy und Format-/Diffprüfung
bestanden. Keine Downloads, kein Bundle, Commit oder Push.
Weiter offen: vollständiger Sampler/Generator einschließlich RNG, adaptiver
Draft-Tiefe, natürlichem MTP-EOS und laufendem Chat; produktiver Executor;
Serverprofil-/Lazy-Eval-/Submission-Vertrag. Die bisherige Bank erzeugt MTP-
Ladedeskriptoren noch vor der Trunk-Materialisierung (Head-Daten bleiben lazy),
während MTPLX den Head erst danach anhängt; auch diese Reihenfolge ist vor
Produktabnahme anzugleichen. Der neue Pfad bleibt cfg(test). Die 2%-Matrix
und UI-/Headless-Responsiveness-Abnahme sind damit ausdrücklich nicht erreicht.
Modellweiter Capture-Commit prüft zunächst alle Einträge. Erst danach erfolgen QSA-Trim, reine GDN-Rekurrenz über das akzeptierte Präfix beziehungsweise PLE-Snapshot-Restore, erneutes Staging und Layer-Forward des Präfixes. Ablehnungen bleiben ohne Cache-Mutation; Capture-Clear entfernt nur Capture- Referenzen. Keine zusätzlichen Eval-/Wait-Grenzen im Commit eingeführt.
Prüfbelege: vorhandene Decoder-Fixtures um den echten äußeren Modellaufruf
erweitert, beide Attention-Typen mit/ohne PLE, cache-only Prefill, Head-Slicing,
Capture an/aus und Trace-Wiederverwendung. Bekannte Embedding-/Widened-/Logits-
Werte bitgenau, fehlender Snapshot unverändert abgelehnt, Zwei-Token-Commit
erfolgreich; PLE-History ist danach [3,4] statt Verify-Tail [5,6].
Fortsetzung mit übergebenen Embeddings und separatem Head ebenfalls bestanden.
Zusätzlicher CPU-Test prüft Compile-Kill-Switch und Run-Grenzen.
Rohdaten: local-eval-results/model-graph-20260909.JbRO3E/commit.*.log;
GPU unter unverändertem test-supervisor 2048 15 15, kein Modell geladen.
Release-Testbuild, warnings-denied Clippy, Quell-Identität und Format-/Diffprüfung
bestanden. Die synthetischen Ein-Layer-Smokes sind keine vollständigen
Golden-Master-Modellfixtures oder Durchsatzmessungen. P16 und die Sechs-Zellen-
Performance-Abnahme innerhalb 2 % bleiben offen.
MTP-Head-Verbindung 2026-09-09: qwen_mtplx/mtp.rs und die Methoden
mtp_forward, mtp_update_cache, make_mtp_cache am äußeren Modell bilden
qwen4_exp.py:4134–4250 ab. RMSNorm über die volle Breite 10240 vor dem
Reshape in vier 2560-Streams, gemeinsame Hidden-Projektion, normierte und
projizierte Token-Embeddings als Broadcast-Add, eigener nicht-PLE-QSA-Decoder
und eigener Mixer. Der LM-Head und das Embedding bleiben mit dem Trunk geteilt.
Rekursive Drafts verwenden den Pre-Mixer-Output des vorherigen Drafts;
Cache-only Updates erzeugen weder Mixer noch LM-Head. Übergebene Embeddings
ersetzen den Lookup, Positionen kommen aus dem eigenen QSA-Cache.
Der verbundene synthetische Test prüft drei rekursive Drafts und danach
mehrzeilige Cache-Updates (2 Lookup-Zeilen und 3 explizite Embedding-Zeilen),
bekannte BF16-Ergebnisse mit unterschiedlichen Hidden-Streams, Offset-Fortschritt,
optionale Hidden-Ausgabe und unveränderte Trunk-Caches/last_widened.
Der erste Lauf (head.*.log) scheiterte beim mehrzeiligen Update am zuvor
fehlenden batched QuantizedMatmul-Zweig. Dieser wird nun direkt nach
quantized.cpp ausgeführt: originale Batch-Strides, _batch_1-Kernel aus der
unveränderten gepinnten Metallib und kein Split-K bei B > 1. Kein Zerlegen in
Einzelzeilen oder zusätzliches Contiguous-Materialisieren als Ersatz.
Nach Ergänzung bestehen beide Decoder-Tests (fixed.*.log, 0,33 s,
gesampelter Peak-Footprint 314.868.528 Bytes). Der bestehende affine
Referenztest besteht unverändert 78 Fälle in je drei physischen Varianten,
also 234 exakte Vergleiche (affine.*.log, 1,00 s).
Der zusätzliche Batch-Test besteht 24 Identitätsprojektionen mit K=64/128/2560,
M=1/3/33/64 und Broadcast- beziehungsweise permutierten Batch-Strides. Er
prüft bitgenaue Ausgabe und die tatsächlich ausgeführten Kernel samt Geometrie.
21 Fälle dispatchen ohne Inputkopie direkt batched; bei drei Broadcast-Fällen
mit M=1 verlangt bereits die Referenz wegen des Null-Strides der Singleton-
Matrixachse eine Kopie und anschließend non-batched Dispatch. Die anfangs
pauschale Ein-Dispatch-Erwartung wurde entsprechend korrigiert, nicht der
Referenzpfad verändert (batched-fixed.*.log, 0,25 s, gesampelter Peak
163.578.600 Bytes).
Release-Testbuild, warnings-denied Clippy für App/Tests, beide CPU-Policy-Tests,
Quell-Identität sowie Format-/Diffprüfung bestanden.
Rohdaten: local-eval-results/mtp-head-20260909.gXSh00/.
Alle GPU-Läufe einzeln unter test-supervisor 2048 15 15, keine Modelle
geladen oder heruntergeladen. Dies ist ein Funktionsnachweis mit künstlichen
Gewichten, kein Nachweis der realen MTP-Akzeptanz, Compile-Fusion oder
Performance-Parität; der gesamte kanonische Pfad bleibt cfg(test).
Arraygraph-Nachweis 2026-09-09: qwen_mtplx/moe.rs bildet die tatsächliche
Aufruffolge von MTPLX SparseMoeBlock, _FusedGateUpSwitchGLU und dem
gepinnten SwitchGLU/Qwen3NextMLP ab:
- Präziser Softmax über alle Experten, ArgPartition, strided Top-k-Slice, GatherAxis und optionale Score-Normalisierung bleiben einzelne Array-Knoten.
- Gather-Sort ab 64 Routen, Argsort/inverse Argsort, U32-Floor-Divide, Gather/Unsort und die ursprünglichen Expand-/Squeeze-/Reshape-Views. Expert- und Shared-Gewichte bleiben graph-eigene Arrays.
- Gemeinsame Gate/Up-Projektion verwendet Split, den vorhandenen kompilierten SiLU und gewöhnliche Multiplikation. Getrennte Projektionen verwenden den unveränderten kompilierten SwiGLU-Kernel als einen Knoten. Experten: Up vor Gate; Shared Expert: Gate vor Up, wie in den beiden Referenzklassen.
- Fusioniertes AR (S=1) und Verify (S=2–4) haben zwei CustomKernel-Knoten mit Original-Inputreihenfolge, Output-Layouts, Gruppen32/64 und Dispatch-Geometrie. Sie werden nur bei den ursprünglichen Flag-/Batch-/Quantisierungsbedingungen selektiert. Der Shared-Gate-Aufruf liegt im fusionierten Zweig vor dem Shared MLP, im Standardzweig danach. Keine zusätzliche Eval-/Wait-Grenze im Modellblock.
mtplx_graph_sparse_moe_matches_reference vergleicht die unveränderten 220
vollständigen MTPLX-MoE-Belege zweimal: zunächst mit lazy Parameter-Views,
danach mit zuvor ausgewerteten Parametern. Eingabe und Modellbesitzer werden
vor der Auswertung freigegeben; der Graph muss ihre Lebensdauer selbst halten.
440/440 Ausgaben exakt. Rohdaten:
local-eval-results/moe-graph-20260909.xLwfFW/graph.*.log.
Diagnostischer Gesamtlauf 17,988 s, OS-Lifetime-Peak 5.194.256.488 Bytes
(4,84 GiB), unter dem unveränderten 8-GiB-/15-s-Wächter. Dies ist kein
Modell-Durchsatzbenchmark und kein Vergleich gegen die frühere Buffer-Testzeit.
Der zusätzliche vorhandene GatherQMM-Test einschließlich Streamwechsel,
physischer Views und lazy/vorbereiteter Ausführung ist ebenfalls bestanden
(gather.*.log).
Der anschließende vollständige Lauf mit Dispatch-Erfassung
(dispatch.*.log) besteht ebenfalls alle 440 Vergleiche. Zusätzlich wird an
der tatsächlichen nativen Dispatch-Grenze geprüft: exakt die beiden passenden
fusionierten Kernel in H-/Down-Reihenfolge, Gruppen-/M-Spezialisierungen,
Grid und Threadgroup sowie dispatchThreads; in allen nicht geeigneten
Fällen keine dieser beiden Fusionen. Quell-Identitätsprüfung, Release-Testbuild,
warnings-denied Clippy und Format-/Diffprüfung sind bestanden.
Der gemeinsame synthetische Pack-Generator berechnet nun n*k/32*bits,
damit die gültigen 512-Experten-Packs nicht bereits im Zwischenprodukt
n*k*bits einen u32-Überlauf erzeugen; die Pack-Werte bleiben identisch.
- MTPLX
_FusedGateUpSwitchGLU.__call__sortiert ab 64 Routen und benutzt den gemeinsamen gate/up-Gather auch im sortierten Fall. Der vorangestellte Kommentar zur Large-M-Fallback-Absicht ist nicht der ausgeführte Code. Shared Expert ist ebenfalls gemeinsam gepackt. Der noch nicht migrierte Rust-Produktpfad führt beide Prefill-Projektionen getrennt aus; der neue Arraygraph ist oben belegt. - Aktivierte gepackte Gewichte, Top-10-Routenauswahl/Ties, Sortiergrenze S=5/6/7,
inverse Permutation, Gewichtung, Tile-Reste und stark ungleich verteilte Experten
vergleichen. Auch der standardmäßig deaktivierte
FUSED_MOE_VERIFYgehört gemäß Auftragspräzisierung zum Port, ohne ihn abweichend zur Referenz zu aktivieren. - Abnahme: Referenz-Outputs und Routenzuordnung für identische Matrizen; bestehender
qwen_sorted_routed_prefill_matches_grouped_outputbleibt unverändert gültig. Performance-Abnahme erst am vollständig integrierten Referenzport, keine erneute Auswahl einzelner Bestandteile anhand von Teilbenchmarks.
BK-Teilversuch 2026-09-05: Die online geprüfte, tatsächlich benötigte
MLX-0.32.2-Implementierung
nutzt im NAX-Pfad BK=64 und für sortierte Experten BM=32 bei weniger als 64
Durchschnittszeilen je Experte. Rust Sorted-QMM nutzt BM=64/BK=32 mit M5-MPP.
Der lokale allgemeine MLX-Checkout steht hingegen auf 0.32.3 (b636898);
er ist nicht ungeprüft als Code der installierten MLX-0.32.2-Referenz zu behandeln.
Nur BK von 32 auf 64 geändert und geprüft: vorhandener
qwen_sorted_routed_prefill_matches_grouped_output mit 137 Zeilen/ungleichen
Expertenbelegungen exakt bestanden. Vollständiger AR-Chat ebenfalls identische
Antworten/Tokenzahlen, alle Stop/Exit0. Summary-Prefill 5,578 s, großer GPU-Buffer
3,812 s, gegenüber normal zuvor 5,291 s / 3,861 s und erneut 5,289 s / 3,848 s.
PLE-pread im Summary beträgt im BK64-Lauf 552 ms statt 227 ms im ersten Kontrolllauf;
die höhere Gesamt-Prefillzeit ist deshalb kein isolierter BK-Nachteil. Umgekehrt
beweist die kleine GPU-Differenz ohne Wiederholungen keinen belastbaren Vorteil.
BK64 zurückgenommen, keine unbewiesene Optimierung verbleibt im Produkt.
Rohbelege: sorted-bk64-check.log, qwen-bk64-ar.* im gleichen Messverzeichnis.
BM-/Experten-Worklist und BF16- statt FP32-Aktivierungsspeicher bleiben getrennte
P07/P09-Kandidaten; die BK-Geometrie allein erklärt den Rückstand nicht.
BF16-Speicher-Teiländerung danach umgesetzt (2026-09-05, siehe P09): Der sortierte Gather und dessen SwiGLU-Zwischenergebnis speichern jetzt BF16 direkt für den Sorted-QMM-Eingang. BM64/BK32 und die getrennten gate/up-Dispatches bleiben bestehen. Das ist kein Abschluss der ausstehenden Routing-/Fusions-/Tile-Vergleiche.
BM32 isoliert geprüft und zurückgenommen (2026-09-05): Route-Map, Worklist- Kapazität und Sorted-Dispatch konsistent auf 32er-M-Blöcke umgestellt; der Grouped-Referenzpfad blieb bei 64. Alle acht exakten Formen bis S2048 bestanden. Vollständiger AR-Chat mit identischen Antworten: Summary-Prefill 5629 ms und großer GPU-Buffer 3977 ms gegenüber BF16/BM64 zuvor 5289–5368 ms / 3604–3662 ms bei ähnlicher PLE-Lesezeit. Kein globaler BM32-Produktpfad bleibt zurück. Der kleine Canary-Maximalwert von 1,26 ms in diesem langsameren Lauf ist erneut kein Ersatz für Performance-Messung. Kein MTP-Leistungsnachweis aus diesem Versuch.
Der genauer geprüfte MLX-0.32.2-NAX-Kernel verteilt das Grid über zusammenhängende sortierte Routen und durchläuft innerhalb eines Tiles dessen Expertengrenzen; nur beteiligte SIMD-Gruppen rechnen. Rust erzeugt dagegen getrennte, je Experte aufgerundete Workitems. Bloß BM32 zu kopieren stellt diese Ausführung nicht her. Worklist-Verteilung und aktive SIMD-Gruppen bleiben innerhalb P07 zu untersuchen; der negative Versuch widerlegt keine formabhängige kleinere Tile-Strategie.
Sortierte Gate/Up-Fusion geprüft und zurückgenommen (2026-09-06): Gemeinsames
Dispatch-Grid bei unveränderten Gewichtsansichten/Tile-Mathematik besteht alle
acht exakten Vergleichsformen. 16 abwechselnde Komponentenpaare: GPU-Zeit bei
S2048 9,405→9,376 ms, bei S137 0,794→0,850 ms. Vollständiger AR-Chat textidentisch,
Prefill4880 statt4907 ms bei gleicher PLE-Lesezeit784 ms; kein belastbarer
allgemeiner Gewinn und keine Erklärung des großen Rückstands. Kein experimenteller
Fusionspfad verbleibt. Belege: local-eval-results/20260906-sorted-gate-up/manifest.md.
P08 — Attention/QSA-Kernel und KV-Datentransfers
Kanonischer Graphstand 2026-09-07: Batch-Matmul/Softmax, Dense-SDPA-Fallback, Rows-Gather und gekachelter portabler Prefill-Gather sind verbunden; siehe „Verbundene Attention-Matrixpfade und Softmax“ und „Gekachelter portabler Prefill-Gather“, „Fused-Vector-SDPA und typisierte Metal-Konstanten“ sowie „Originale RoPE-Graphen und KV-Cache-Objektsemantik“ sowie „Direkte Sparse- Attention-Consumer im Arraygraph“. Originaler Flash-Skip-Decode und TensorOps- Prefill sind als eigene CustomKernel-Primitive geprüft. Auch die vollständige originale Blockmaskenrekonstruktion samt ScatterAxis ist verbunden und geprüft (siehe „Vollständige QSA-Blockmaskenrekonstruktion“). RoPE und gewöhnlicher KVCache sind jetzt im kanonischen Arraygraph geprüft, einschließlich Python-Objektalias/Graphdescriptor-Unterscheidung. Auch der positionale QSACache einschließlich FP32-Spiegel und Replay-Reservierungen verwendet diese Semantik (siehe „Positionaler QSACache im kanonischen Arraygraph“). Die originalen Query-/Pooling-CustomKernel sind inzwischen vollständig parametrisiert als Array-Primitiven geprüft (siehe „Parametrisierte QSA-Query-/Pooling-Primitiven“). Die gemeinsamen Float-Summen samt QSA-F32-Mittelwert sind ebenfalls portiert; GDN/PLE/HC nutzen jetzt dieselbe Reduktionsauswahl (siehe „Gemeinsame Float- Summen und QSA-Mittelwert“). Auch F32-/F16-Matmul inklusive TF32 on/off und der verbundene Eager-QSA- Score-Ausdruck sind nun im kanonischen Graph geprüft (siehe „Kanonischer Float-Matmul und verbundener QSA-Score-Pfad“). Sort/Argsort/Partition/Argpartition sind jetzt ebenfalls als kanonische Operationen geprüft; der bisherige Buffer-Argsort teilt deren Backend (siehe „Gemeinsames kanonisches Sort/Argpartition“). Die Eager-Auswahl verbindet jetzt Scores, Maskierung, Argpartition, QSACache- Spiegel und alle fünf Rückgabeformen einschließlich Kachel-Eval und Lane- Zählern (siehe „Verbundene kanonische Eager-QSA-Auswahl“). Die Verbindung zur kanonischen Indexer-Ausführung ist nun geprüft (siehe „Durchgehender kanonischer Indexer und Cache-Commit“). Der vollständige BF16/D256-Attention-Aufruf ist inzwischen ebenfalls verbunden (siehe „Verbundener Qwen-Attention-Modulaufruf“). Der gemeinsame Projektions-/Vorbereitungs-/Update-Vorlauf ist inzwischen mit fortlaufendem Cache und Eager-Auswahl geprüft (siehe „Gemeinsamer QSA-Indexer-Vorlauf und fortlaufender Cache“). Der kanonische Fused-Selektor einschließlich aller drei Ausgabeformen, Graph-Scratch-Siblings und ursprünglicher Query-Chunking-Regel ist ebenfalls geprüft; alter und neuer Aufrufer teilen dessen Backend (siehe „Fused-QSA- Selektor im kanonischen Arraygraph“). Der vektorisierte Prefill-Selektor ist nun ebenfalls als zusammenhängender Zweistufen-Graph geprüft, mit TensorOps BF16/F16 und dem allgemeinen F32-Ausdruck (siehe „Zweistufiger Prefill-Selektor im kanonischen Arraygraph“). Compiled-Indexer und Routing sind nun ebenfalls verbunden. Die dafür benötigten dynamischen Slice-/Update-Primitiven sind jetzt mit gemeinsamem Copy-/Offset-Encoder geprüft (siehe „Dynamische Cache-Fenster im kanonischen Arraygraph“); die Graphbank ist inzwischen angeschlossen. Der reine Compiled-Body samt tatsächlichem Arraygraph-Replay ist inzwischen für die erfassten Q/K-/Hidden-Fälle geprüft (siehe „Reiner Compiled-Indexer und kanonisches Graph-Replay“). Der Host-Core mit vollständigen Compile- Schlüsseln, Validierung und Statistik ist nun ebenfalls geprüft (siehe „Kanonischer Compiled-Host-Core und Engagement“). Parameter-Lebenszyklus, Cache-Commit und Routing sind nun mit 200 vorhandenen vollständigen Aufrufen, 720 Zulässigkeitsfällen und 26 zusätzlichen Lifecycle-Receipts geprüft. Weitere Compiled-Geometrien/Dtypes und die allgemeine Nicht-MPP-Score-Fusion bleiben offen. Andere SDPA-Dtypes/Geometrien einschließlich Full-SDPA sowie die vollständige Modell-/Produktintegration bleiben offen. Die folgenden Befunde zum alten Produktpfad sind dadurch noch nicht behoben.
Priorität P1; nach P02, P04; Quellcodedifferenzen und Nachweislücken.
- Dense Decode, Verify unter/über 16k, Prefill unter/über 32k, Sparse-Selection,
Pooling, Tail und Positionierung mit MTPLX
QSACache,QSAIndexerund Attention vergleichen. Rust poolt in einer CPU-Dispatchschleife und staged Dense-KV erneut. - BF16-KV, F16-Staging für FlashAttention und F32-Zwischenpuffer getrennt prüfen; kopierte Bytes, Layout/Strides und tatsächliche M5-Kernel protokollieren.
- Abnahme: Masken/Indices/States und numerischer Referenzvergleich an 2048,8192, 16384,32768 und ihren Nachbarpositionen sowie partiellen Pool-Blöcken. Der entfernte 8192-Flash-Guard benötigt einen direkten numerischen Test oberhalb der alten Grenze. Ein Allokationstest für langen Kontext ersetzt keinen Attention-Test.
P09 — Affine Matmuls, HC und Speicherformate
Kanonischer Graphstand 2026-09-07: Originale affine Quantisierung sowie der installierte GatedResidual-Read einschließlich eager Norm/Matmul/Mean, Fused/V3-Auswahl und Modul-Pack-Cache sind verbunden und mit128 tatsächlichen MTPLX-Fällen exakt geprüft; siehe „Verbundener GatedResidual einschließlich eager Prefill“. Decoder-/Modell- und Produktintegration sowie Gesamtperformance sind weiterhin offen. Historische Befunde unten bleiben vom aktuellen kanonischen Port zu unterscheiden.
Priorität P1; nach P01, P02, P04; Teiltests bestanden, Gesamtnachweis offen.
K-Tile/Padding/BF16-Versuch verworfen (2026-09-06): Ein kombinierter Versuch mit gruppengroßem K-Schritt, gepaddetem Gewichtstile und BF16-Geräteingang senkte die isolierte QKV2048-Zeit auf2,654 ms, beschleunigte die vollständigen Chats aber nicht erkennbar: AR/MTP-Summary-Prefill4233/4387 ms gegenüber4214/4351 ms der vorherigen Kontrolle; GPU-Buffer2140/2151 gegenüber2160/2159 ms. Kleine Projektionsausgänge bezahlen zusätzliche Konvertierungskosten. Canary-Maxima 49/83 ms, kein allgemeiner Responsivitätsgewinn. Alle drei Antworten pro Modus Stop/Exit0 und exakt gleiche Texte, Tokens und MTP-Akzeptanz wie die gültige Rust-Kontrolle; kein erneuter MTPLX-Paritätsnachweis aus diesen Zahlen.
Der erste Versuch war wegen eines übersehenen direkten GDN-QMM-Aufrufers
(FP32 an BF16-Kernel) ungültig und wurde abgebrochen. Neuer Integrationstest
reproduziert den Fehler bei5 Zeilen und prüft nach Korrektur4/5/32/65/2048 Zeilen
inklusive Unpack exakt. Anschließend wurde die gesamte unvorteilhafte Variante
zurückgenommen, nicht nur der falsche Aufrufer repariert. Test und gewöhnliche
GPU-Timestamps im Operator-Test bleiben erhalten; Produkt-Binary und Metal
sind SHA256-identisch zur vorherigen gültigen Wortloader-Kontrolle. Die Tests
bestehen auch nach Rücknahme. Belege und Rückmessungen:
local-eval-results/20260906-qmm-k-tile/manifest.md.
Wortweise QMM-Entpackung (2026-09-06): Der gemeinsame Affine-QMM-Loader liest
gepackte Wörter/Skalen/Bias jetzt einmal je4/8 Werte, wie der vorhandene sortierte
Loader und MTPLXs QuantizedBlockLoader, statt pro Einzelwert. FMA/BF16-Rundung,
Tile-Geometrie, Split-K und Aktivierungsformat unverändert. Alle bestehenden
Projektionsgoldens einschließlich partieller Tiles bestehen. Die erweiterten
Operator-Timings grenzen QKV2048 ein: MTPLX2,060 ms, Rust vorher7,272 ms,
wortweise3,150 ms (Host-Aufruf und Completion, keine reine GPU-Zeit).
Separat geprüfte BF16-Aktivierungsvarianten brachten keinen generellen Gewinn
und sind zurückgenommen; FP32 ist damit nicht als alleinige Ursache bewiesen.
Vollständiger AR-Chat text-/tokenidentisch: erster Prefill4214 statt4907 ms,
größter GPU-Buffer2160 statt2656 ms, ähnliche PLE-Lesezeit792/784 ms. Canary-Max
3,962 ms; Einzelvergleich, kein GUI- oder2%-Nachweis. Weitere Form-/Layout-/
Referenzwiederholungen bleiben offen. Belege:
local-eval-results/20260906-sorted-gate-up/manifest.md.
Vollständige MTP-Kontrolle ebenfalls text-/token-/acceptance-identisch mit Stop beendet: erster Prefill4351 statt5079 ms; Decode70,622/47,038/66,224 tok/s. AR/MTP-Canary-Max3,962/3,006 ms, keine Fehler. Diese Einzelkontrollen ersetzen keine saubere zeitnahe Referenzmatrix; DeepSeek/GLM wurden dabei nicht neu gemessen.
Verifier-Zeilenspezialisierung (2026-09-06): Der gemeinsame Wide-QMV-Metal-
Helper spezialisiert nun 2/3/4 Zeilen mit konstanten Akkumulator-Indizes und
unrollten inneren Schleifen wie die installierten MTPLX-Kernel. Zwölf zusätzliche
echte MTPLX-Projektionshashes (QKV/Router/GDN-Control/Shared-Gate) bestehen vor und
nach der Änderung; vorhandene Prefill-Goldens bleiben gültig. Vollständiger
MTP-Chat bei 100%/2048/Low, ohne Profiler, mit Canary: unveränderte Texte, Tokens
und Akzeptanz, Decode 70,732/47,279/68,033 statt 57,166/37,921/52,799 tok/s.
Canary-Max31,552 ms, Decode-Max0,874 ms. Erster Prefill5079 statt zuvor4609 ms:
keine belegte Prefill-Verbesserung. Einzelvergleich, keine gepaarten sauberen
Referenzwiederholungen und keine 2%-Abnahme. Belege und Grenzbedingungen:
local-eval-results/20260905-verifier-stage-counters/manifest.md.
AR-Kontrolle ebenfalls vollständig/textidentisch beendet, Decode
48,919/48,795/48,857 tok/s, keine beobachtete Regression. Deren Canary-Max3,141 ms
ist ebenfalls viel kleiner als im historischen Lauf, obwohl AR den geänderten
Wide-QMV-Pfad nicht nutzt. Deshalb die verbesserten Canary-Maxima nicht kausal
der Kerneländerung zuschreiben; zeitnahe gepaarte Messungen bleiben erforderlich.
Vor weiterer QMM-Optimierung belegte Abweichung (2026-09-05): Der erweiterte
Projektions-Komponententest besteht bei QKV 4-bit/g64 mit 32/64/2048 Zeilen und
Router 8-bit/g64 mit 2048 Zeilen. Router 32 und 64 weichen ab. Die Referenzwerte
wurden danach durch die quantisierten Projektionsmodule von MTPLXs
GatedDeltaNet und SparseMoeBlock bestätigt; alle zwölf generierten Hashes
entsprechen dem vorherigen direkten Bibliotheks-Diagnosetest. MTPLX bleibt das
Qwen-Orakel; diese Operatorchecks ersetzen keinen Modell-/Serving-Vergleich.
Belege: tools/qwen-qmm-reference.py, local-eval-results/20260905-qmm-loader/
mit mtplx-components.jsonl und affine-all-shapes-before.log. Der Test sammelt
alle Formfehler und schlägt weiterhin fehl; keine Golden-Hashes wurden angepasst.
Ursache inzwischen bestätigt (2026-09-05): Im begrenzten Komponententest
wurden über LLDB die vom unveränderten, installierten MTPLX angeforderten
Pipeline-Namen und Dispatch-Geometrien gelesen. Router 31/32 Zeilen verwendet
affine_qmm_t_splitk_bfloat16_t_gs_64_b_8_alN_true, Grid 16×1×20; Router 63/64
Grid 16×2×10. Danach folgt jeweils col_reduce_small_1_reduce_sumbfloat16
mit 32×8 Threads. Router 2048 und die geprüften QKV-Matrizen verwenden dagegen
NAX-QMM, ohne K-Split. Das ist nun ein Nachweis der installierten Ausführung,
nicht eine Annahme anhand eines anderen Bibliotheks-Checkouts.
tools/qwen-qmm-reference.py --check-split-k reproduziert beide Router-Goldens
bitgenau mit 20 beziehungsweise 10 expliziten QMM-K-Partitionen und anschließender
BF16-Reduktion. Ein ungeteilter gebatchter Kontrollfall liefert dagegen genau die
bisherigen abweichenden Rust-Hashes. Die 32-Zeilen-Kontrolle muss beim kleineren K
im QMM-Pfad bleiben: 64 gepaddete Eingabezeilen, anschließend Auswahl der ersten
32. Ohne diese Kontrolle wechselte der erste Diagnoseversuch die Operatorform
und reproduzierte das Golden nicht. Golden-Hashes unverändert; Assertions für
beide Split- und Unsplit-Kontrollfälle bestanden. Keine Timing-Abnahme unter LLDB.
Diagnosebeleg: local-eval-results/20260905-router-splitk/manifest.md.
Split-K-Teilkorrektur umgesetzt und nachgemessen (2026-09-05): Gemeinsamer Affine-QMM-Pfad mit formabhängiger K-Aufteilung, BF16-Zwischen-/Reduktionsrundung und wiederverwendbarem 2-MiB-Puffer. Der erste Versuch scheiterte an nativen BF16-SIMD-Overloads; nach Abgleich mit der installierten MTPLX-Abhängigkeit ist die Float-SIMD-Zwischenoperation mit BF16-Ergebnisrundung korrigiert. Unveränderte QKV-/Router-Goldens bestehen jetzt, einschließlich zuvor fehlerhafter Router 32/64. Zusätzliche tatsächliche MTPLX-Projektionsgoldens für GDN-Steuerung (N=48) und Shared-Expert-Gate (N=1) bei 32/64/2048 bestehen ebenfalls, jeweils mit Tail-/Sentinel-Prüfung; beide Reduktionspfade einschließlich 40 Partitionen sind abgedeckt. CPU-Test für Split-Policy, Alignment und Puffergrenzen bestanden.
Vollständige AR-/MTP-Produktchats bei 100%, Chunk2048, Low, identischen eingefrorenen
Prompts und Canary an enden natürlich. Beide Python-Ausgaben bestehen neun Fälle.
Erster Prefill4,436/4,609s; Decode AR48,740/48,486/48,332 und
MTP57,166/37,921/52,799tok/s. Canary max110,710/96,768ms, keine Fehler.
Das beseitigt die nachgewiesene numerische Teilabweichung, nicht den verbleibenden
Durchsatz-/Latenzrückstand. Gesampelte Historien ändern sich; kein isolierter
Kernel-Speedup und keine 2%-Abnahme daraus ableiten. Alle Produktionsformen,
QMV/QMM-Dispatch-Grenzen, HC und Kernel-Performance bleiben innerhalb P09 offen.
Belege, Hashes und reproduzierbare Prüfung:
local-eval-results/20260905-splitk-implementation/manifest.md.
- Pro Operator Form, Quant-Bits/Group-Size, Packung, Akkumulator, gespeicherten Datentyp und BF16-Rundungsstelle erfassen. Rust speichert viele BF16-gerundete Aktivierungen als F32; Werteparität beweist nicht Bandbreiten-/Speicherparität.
- QMV/QMM/Gather/Sorted-QMM, HC-read/mix/write, Norm/Gates, Embedding und LM-Head abdecken; aktive MTPLX-Fusionen von nicht aktivierten Experimenten trennen.
- Abnahme: vorhandenen
qwen_affine_qmv_and_qmm_match_mlx_referenceund Stage-Trace- Tests wiederverwenden, keine Golden-Hashes still ändern. Produktionsformen plus Tail-/Kapazitätsfälle. Vor Änderungen Kernel-Zeit, Dispatchzahl, Kopierbytes und Peak-Transients ermitteln; Dtype-Änderungen nur mit Referenzbeweis.
Sorted-MoE-Eingangsspeicher umgesetzt, Rest offen (2026-09-05):
kernel_qwen_route_gather_rows und die nur dort verwendete BF16-SwiGLU-Variante
schreiben gepacktes BF16; kernel_qwen_affine_sorted_qmm_mpp liest es als
tensor<device bfloat>. Bisher wurden BF16-gerundete Werte als FP32 gespeichert.
Die bestehende SwiGLU-Formel/Rundungsfolge bleibt gemeinsam templatisiert; der
Grouped-/Decode- und Shared-Expert-Pfad bleibt FP32. Outputs und Akkumulatoren
des Sorted-QMM bleiben FP32. Vorhandene Scratch-Puffer werden wiederverwendet,
ihre Kapazität wurde nicht verkleinert: kein behaupteter Peak-Allokationsgewinn.
Der bestehende exakte Grouped-vs-Sorted-Test wurde auf S=5,6,7,32,64,65,137,2048 erweitert; alle Fälle bestehen mit MAE0/max0/assert_eq. Danach sechs vollständige überwachte Chats: BF16 AR/MTP, Rückkehr zu hash-identischem FP32-Metal AR/MTP, erneut BF16 AR/MTP. Alle Stop/Exit0; Antworten, Reasoning, Tokenzahlen und Draft-/Accept-/Cycle-Zahlen exakt identisch zu den vorherigen jeweiligen Kontrollen.
| Modus / Pfad | Summary Prefill ms | größter GPU-Buffer ms | PLE pread ms | Prefill-Canary max ms | Prozess ms |
|---|---|---|---|---|---|
| AR FP32 Rückmessung | 5606 | 3863.26 | 607 | 125.06 | 60572 |
| AR BF16 Lauf 1 | 5289 | 3603.53 | 618 | 1.32 | 59791 |
| AR BF16 Lauf 2 | 5368 | 3662.29 | 613 | 156.50 | 59900 |
| MTP FP32 Rückmessung | 5770 | 3821.95 | 611 | 122.33 | 57956 |
| MTP BF16 Lauf 1 | 5677 | 3741.14 | 853 | 115.85 | 59514 |
| MTP BF16 Lauf 2 | 5494 | 3606.83 | 610 | 16.93 | 55938 |
100%, Chunk2048, Low, gleiche drei Prompts und fortlaufender Chat, Canary an,
keine Layer-Profilierung. Der größte Prefill-GPU-Buffer ist wiederholt kürzer
(AR 5,2–6,7%, MTP 2,1–5,6%). Das ist keine 2%-Referenzabnahme und kein Beleg,
dass Decode allgemein schneller wurde. Die hohe PLE-Streuung beeinflusst auch
die Gesamtlaufzeit. Insbesondere widerlegt der zweite AR-Lauf eine aus dem ersten
niedrigen Canary-Wert abgeleitete allgemeine Responsivitätsverbesserung.
Kein GUI-Eventloop-Nachweis; die Spitzen bleiben P04/P05/P07/P08 zugeordnet.
Details/Hashes und normierte End-to-End-Decodewerte:
local-eval-results/20260905-gdn-delta/bf16-comparison.json, bf16-storage.md.
Zusätzliche M5-Primärquelle für die verbleibenden P07/P09-Arbeiten: Apples MPP Programming Guide, §§2.3.1–2.3.5 behandelt Tile-Reste/Occupancy, cachefreundliche Work-Reihenfolge und statische Tensor-Extents zur Vermeidung unnötiger Bounds-Checks. Das stützt die genannten Messkandidaten, beweist aber weder eine konkrete Beschleunigung unseres Kernels noch einen behaupteten FP32-Fallback auf Nicht-Tensor-Hardware. Keine weitere Geometrie-/Synchronisationsänderung mit der BF16-Änderung vermischt.
Sorted-QMM-Gewichtsloader optimiert (2026-09-05): Der skalare Aufruf von
qwen_quant_weight im Staging las Packed-Word, Scale und Bias für jeden einzelnen
Wert erneut. Der Loader lädt diese nun einmal je Wort und entpackt daraus die
4 beziehungsweise 8 Werte mit derselben FMA und BF16-Rundung. Die installierte
Konfiguration verwendet bei allen 144 Switch-MLP-Projektionen 4 Bit / Gruppe64.
Der unveränderte Grouped-Kernel dient weiter als exakte Kontrolle. Alle acht
Formen bestehen erneut, auch nach der Rückmessung. Nur diese Loader-Änderung
bleibt zusätzlich zur zuvor geprüften BF16-Speicherung bestehen; BM64/BK32,
Barrieren, Command-Buffer-Grenzen und Scratch-Kapazität bleiben unverändert.
Die Wiederverwendung der Scale-/Bias-Werte ist auch im tatsächlichen
MLX-0.32.2-QuantizedBlockLoader
belegt; dessen Implementierung wurde nicht als Engine-Code übernommen.
Gepaarte vollständige Chats ohne aktiven Canary (weiterhin Supervisor, 100%, 2048, Low, bestehende drei Prompts und derselbe fortlaufende Chat):
| Modus / Loader | Prefill Summary / Story / Python ms | Runtime-Decode Summary / Story / Python tok/s | größter Summary-GPU-Buffer ms | Summe Chat-Turns ms | Prozess inkl. Laden/Warmup ms |
|---|---|---|---|---|---|
| AR skalar | 5297 / 794 / 840 | 48,34 / 47,83 / 48,11 | 3611,37 | 37807 | 58959 |
| AR wortweise | 4310 / 620 / 622 | 48,25 / 47,83 / 47,86 | 2942,65 | 36385 | 56029 |
| MTP skalar | 5508 / 828 / 868 | 52,55 / 40,00 / 69,63 | 3612,77 | 35039 | 56833 |
| MTP wortweise | 4487 / 647 / 648 | 54,22 / 41,61 / 72,89 | 2943,32 | 32616 | 56390 |
Mit Canary wurde der wortweise Loader separat gemessen: Summary-Prefill AR4309 ms / MTP4465 ms, großer GPU-Buffer 2940/2937 ms; Prefill-Probe max108,29/28,95 ms, keine Fehler. Der AR-Canary-an/aus-Vergleich zeigt in diesen Läufen praktisch gleiche Prefillzeit, ist aber keine allgemeine Garantie kostenfreier Messung. Die Probe bleibt optional. Alle sieben aktuellen Chats (inklusive BM32-Trial) enden dreimal natürlich mit Stop/Exit0; Startvertrag und vollständige Antworten, Reasoning, Tokenzahlen sowie Draft-/Accept-/Cycle-Zahlen stimmen mit den jeweiligen vorherigen Rust-Kontrollen exakt überein.
Der große Prefill-Buffer wird auch ohne Canary rund18,5% kürzer. Die AR-Decode-
Rate bleibt praktisch gleich. MTP-Decode und Prozesszeit sind stärker durch
PLE-Lesezeit/Warmup beeinflusst (z.B. Summary PLE905 ms skalar vs607 ms neu);
keinen allgemeinen Decode-Gewinn ausschließlich dem Prefill-Loader zuschreiben.
Das sind gepaarte Diagnosemessungen, keine 2%-Abnahme gegen MTPLX und kein
UI-Eventloop-Beweis. Versionen, Einzelwerte, End-to-End-Decodewerte und beide
isolierten Patches: local-eval-results/20260905-moe-tiles/manifest.md,
comparison.json. Reiner Matrix-/Staging-Restvergleich und P07/P08 bleiben offen.
P10 — PLE-Streaming und Hot-Cache mit Referenzkosten vergleichen
Kanonischer Graphstand 2026-09-07: PLE-Projektion/Gate und dilatierte
Faltung einschließlich lazy Cache-Fortsetzung sind mit84 echten MTPLX-Fällen
unmittelbar und verzögert exakt geprüft; siehe „PLE-Projektion und dilatierte
Cache-Fortsetzung“. Zusätzlich ist der CPU-Staging-Hash samt roher History mit
64 Original-Receipts geprüft; siehe „N-Gram-CPU-Staging-Hash und rohe History“.
Der lazy GPU-Hash bis zu den Tabellen-IDs ist mit60 tatsächlichen GPU-Receipts
unmittelbar und verzögert geprüft; siehe „Lazy N-Gram-GPU-Hash bis zu den
Tabellen-IDs“. Der vollständige residente _graph_path ist einschließlich
Lookup/Dequantisierung mit24 Original-Ausgaben sofort und verzögert geprüft;
siehe „Verbundener residenter N-Gram-Graph“. Der Sidecar-Gather samt Prefetch,
Hot-Cache/Bypass und gemeinsamer Tabellenauswahl ist mit192 Original-Receipts
in drei Auswertungsarten geprüft; siehe „Verbundener Sidecar-Gather und
Tabellenauswahl“. Der verbundene Stage-Lifecycle einschließlich QA und Fehler-
History ist mit136 Original-Receipts in zwei Auswertungsarten geprüft; siehe
„Verbundener N-Gram-Stage-Lifecycle“. Der vollständige PLE-Aufruf einschließlich
Sidecar-/Resident-Safetensors-Attach und CPU-Load ist mit144 Original-Receipts
in zwei Auswertungsarten geprüft; siehe „Vollständiger PLE-Aufruf mit
Safetensors-Ladeanbindung“. Modellweite Residency-/Memory-Plan-Auswahl,
übrige Gewichte und Gesamtmodell-/Produkt-Integration bleiben offen.
Keine P10-Performanceabnahme.
Priorität P1; nach P02, P04; Unterschiede belegt, Anteil an Laufzeit offen.
- Referenz
NGramEmbedding.stage,_SidecarGather._rows_matricesgegen RustPleReader::rows/ple_batch_with_state: Staging-Zeitpunkt, deduplizierte IDs, pread-Queueing, Kopien und cachefreie große Prefills prüfen. - Rust
touchhängt jedes Mal einen Eintrag anorder; bereinigt wird nur beim Überschreiten der Nutzdatenkapazität. Wiederholte reine Cache-Hits lassen damit Metadaten unbeschränkt wachsen.cache_byteserfasst nur 100 Nutzbytes pro Row, nicht HashMap/Queue. MTPLX hält seine OrderedDict-Einträge begrenzt. - Abnahme: identische PLE-Rows über EOS/Chunk/Replay-Grenzen; begrenzte tatsächliche Cache-Metadaten bei Wiederholung. Warm-/Cold-Lookups in beiden Implementierungen messen: einzigartige Rows, Bytes, Wall-IO, CPU-Gather, Staging, GPU-Dequant/Projektion. Nur nicht überlappende kritische Zeitanteile von Gesamtzeit abziehen.
- Die in MTPLX
_SidecarGatherdokumentierten M5-NVMe-Mikrosekunden sind historische Autorenmessungen; sie ersetzen keine Referenzmessung auf diesem Gerät.
P11 — Qwen-MTP-Sampler, Depth und unnötige Arbeit
Priorität P1; nach P02, P03, P04, P09; Quellcodedifferenz belegt, direkte Lazy-Übernahme vermessen und nicht beibehalten; Gesamtnachweis offen.
Target-Verteilungen gezielt verglichen (2026-09-05): Direkte zeilenweise Materialisierung wie im aktiven MTPLX-Pfad implementiert, gegen den bisherigen Batch-Sampler geprüft und im vollständigen Produktchat nachgemessen. Alle Texte, Reasoning-Inhalte, Tokens und Draft-/Accept-Zähler bleiben identisch. Der Regressionstest prüft außerdem jeden Ablehnungs-Slot, All-Accept plus Bonus, identische weitere RNG-Ziehungen, konzentrierte/breite Masse und CPU-Fallbacks. Das ist Rust-Eager/Lazy-Äquivalenz, noch kein vollständiges MTPLX-Sampler-Orakel.
Die isolierte Messung mit 32 alternierenden Paaren zeigt aber: vier gebatchte Verteilungen kosten rund 0,80ms; lazy 1/2/3/4 benötigte Zeilen rund 0,53/1,02/1,49/2,04ms. Nur sofortige Ablehnung profitiert. Die Produktänderung wurde deshalb zurückgenommen; Vergleichstest bleibt. Der aktuelle Produktionscode entspricht nachweislich wieder dem vorherigen Stand, CLI neu gebaut. Eine schnellere äquivalente Ausführung ist zulässig; ein anderer Aufrufplan allein ist kein Fehler.
Der vollständige wiederhergestellte Harness-Pfad wurde anschließend mit vorhandener
MTP-Profilierung ausgeführt, erneut mit exakt identischen Antworten/Zählern.
588 Vier-Zeilen-Verifikationen inklusive Warmup: Median Encoding-Wall3,217ms,
anschließendes GPU-Warten42,025ms, Readback0,004ms. Host-Zeitgrenzen, keine
isolierten Kernelzeiten; Profiling und Canary an. Der große Restaufwand liegt
damit im GPU-Verify-/Submission-Pfad, nicht im Auslesen der Verteilungen.
P05–P09 sind dafür weiter zu lokalisieren; keine Performance-Parität behauptet.
Belege und reproduzierbare Prüfungen:
local-eval-results/20260905-lazy-target-distributions/manifest.md.
- Draft-D3 wie Referenzdefault vergleichen. D1..D5-Unterstützung ist eine getrennte Funktionslücke, kein Grund, während des Default-A/B heimlich die Tiefe zu ändern.
- Voller Verify-Block: Rust berechnet/verliest alle Target-Verteilungen; MTPLX
generation.pymaterialisiert lazy bis zur ersten Rejection bzw. Bonusposition. CPU/GPU-Sync, Top-k-Pfad und Full-Vocab-Fallback jeweils zählen. - RNG nicht pauschal als verschieden bezeichnen: Rust enthält bereits NumPy-kompatibles SeedSequence/PCG64. Draw-Reihenfolge, Softmax/top-p/min-p, Rejection und Residual müssen auf gleichen Logits/Drafts geprüft werden.
- Abnahme: deterministische Akzeptanz-/Korrekturfälle, identische Zufallsziehungen, gleiche Verteilungssemantik; pro Zyklus Drafts/Accepted/Bonus/Correction, Forward- Breiten und Zeiten. Hohe Python-Akzeptanz ist eine Messhypothese, keine Garantie.
P12 — Qwen-MTP-Commit, Fallback und vollständiger Abschluss
Priorität P0; nach P03, P04, P06, P11; potenziell schwerer Fallback belegt.
Kanonischer Graphstand 2026-09-07: Validierung und reine GDN-Capture-Rekurrenz sind mit den vorhandenen Array-Primitiven verbunden und gegen 26 tatsächliche MTPLX-Commit-/Decode-Receipts geprüft. Globale Validierung vor Mutation, QSA-/PLE-Zweige, Ablehnungszähler, Rollback-/Repair-Orchestrierung und Produktintegration bleiben offen; siehe „GDN-Capture-Commit mit nachfolgendem Decode“. Die folgenden Befunde betreffen weiterhin den alten Produktpfad.
restore_or_replayfällt bei Capture-Fehler aufreplay_tokenszurück, das nach Reset den gesamten bisherigen Kontext tokenweise ausführt. Der Fehler erscheint nur in stderr, nicht als eindeutig gezähltes Laufzeitereignis.- Gegen MTPLX
commit_verified_window, Conv-Tape-Rekurrenz, Pending-Correction und begrenzte Repair-Pfade abgleichen. Nicht bloß den Fallback schneller machen: Ursache unvollständiger Captures und korrekte Zustandsgrenze bestimmen. - Abnahme: kein unbemerkter Full-Context-Replay; gezielt ausgelöste Rejections an
jeder Draftposition, alles akzeptiert, EOS, Cancel, Kontextende und Save/Restore.
KV/GDN/PLE/MTP-History nach Commit mit Target-Referenz vergleichen; vorhandenen
qwen_mtp_matches_target_and_restores_its_cacheerweitern statt neuen Teststack bauen.
P13 — DSpark-/GLM-Sampling-Vertrag und effektive Einstellungen
Priorität P0; nach P01, P02 für die Messabnahme; Settings-Korrektur und Receipt-Tests bestanden, End-to-end-Messung offen.
- DS4
ds4.c:61906wählt Metal-Confidence 0,6;:66603hebt nur bei stochastischem Exact Sampling den nicht expliziten Wert auf mindestens 0,8. Rust setzte vorher schon normal 0,8 und löste die Exact-Anhebung beim Laden statt pro Turn auf. Jetzt gemeinsame Auflösung inEngineSpeculativeSettings::dspark_confidence_for_temperature, verwendet von beiden Proposal-Aufrufern und dem Harness-Receipt. Explizite Werte bleiben unverändert, einschließlich 0 und 0,7. Kein Eingriff in gespeicherte Konfigurationen. - Harness-Start enthält nun Sampling-Kategorie (
target_only,greedy,opportunistic,exact), Basis-/Turn-Confidence, explizit/automatisch, Strict-/Exact-Flags und integriertes MTP-Timing. UI-Hilfetext korrigiert; Performance-Fixture bezieht ihren Default aus denselben Produkt-Settings. - DSpark opportunistic/strict/exact und GLM opportunistic/exact gesondert erfassen. Rust GLM-Sampled-Dispatch leitet an greedy draft matching weiter; das entspricht der opportunistischen Kategorie, nicht dem optionalen Exact-Modus der Referenz.
- Abnahme: Tabellengetriebener Test für fehlenden Wert, expliziten Wert, Exact und
Quality/Strict. Harness-Receipt enthält effektive Schwelle und Semantik, nicht
nur
acceleration.enabled. Fehlende Exact-Unterstützung ausdrücklich markieren.
Verifikation 2026-09-05, ohne GPU-Modelllauf oder breite Gates:
- Regression vor Korrektur: Default-Test scheitert mit Ist 0,8 / Soll 0,6.
cargo test --release --bin ds4-server settings::tests::: 8 bestanden, einschließlich fehlender/gesetzter Werte und Exact bei Temperatur 0/1.cargo test --release --bin ds4-server model_eval::tests::: 8 bestanden, einschließlich Receipt-Modi, Quality/Strict, GLM/Qwen und abgeschalteter Acceleration.cargo test --release --bin ds4-server engine::metal::tests::dspark_: 2 CPU-Tests bestanden; modellabhängiger Test blieb explizit ignored.git diff --check: bestanden. Keine Durchsatzverbesserung aus diesen Tests abgeleitet. Vor der neuen DSpark-Messung bleiben P02/P03/P04 maßgeblich.
P14 — GLM-MTP tatsächlich batchen wie DS4
Produktpfad umgesetzt, Referenz-Performanceabnahme offen (10.09.):
local-eval-results/glm-two-row-20260910.Y1SbdU/{manifest.md,comparison.json}
enthält echten Zwei-Zeilen-Forward, Row0-Head, KDA-GPU-Backup/Restore,
Rejection-Replay und Rewind auf null/ein behaltenes Token. Vorhandene
Batch-Kernel laufen mit einem wiederverwendeten Zwei-Zeilen-Workspace;
HC-Expansion leitet ihre Zeilenzahl aus Bufferbytes ab, deshalb darf hier
nicht die 2048-Zeilen-Allokation verwendet werden. Speicheradmission ergänzt.
Tests an Frontier12/Context128 und Frontier4095/Context8192 bestehen Annahme,
Ablehnung, Rewind, Cap1 und bereits gesetztes Cancel. Replay-KDA/Logits sind
bitgenau skalar; der Grenzfall schaltet wie DS4 auf indexierten Batch um.
Der normale Vorher-Chat scheiterte an einem schon vorhandenen zu kleinen skalaren Auswahlbuffer im Dense-Compact-KV-Pfad. DS4 reserviert dafür Context- statt nur Top-K-Kapazität; gemeinsame Rust-Allokation korrigiert. Danach vollständige AR/MTP-Chats bis EOS bestanden, beide Python-Ausgaben inklusive 5 Assertions und 5011 unabhängigen Fällen korrekt. Kein Speedup aus dem abgebrochenen Vorher-Lauf. Decode AR 22,278/21,637/22,443 und MTP 22,576/19,350/30,768 tok/s; unterschiedliche Antworten/Historien, keine direkte DS4-Messung oder 2%-Abnahme. Prefill-CB-Maxima 5,983s AR / 4,419s MTP bleiben ein offener Responsivitätsbefund; Canary aus, kein GUI-Stall-Nachweis. Aktueller DS4-Quellstand ec7642c: nichtfinale 2048er-Chunks können ebenfalls ohne Layer-Flush laufen (>2048 oder Logits+>8 ist die Bedingung); daher nicht blind zusätzliche Flushes als Lösung übernehmen. P15 weiter prüfen.
Zusätzlicher P13-Messpunkt (ursprünglicher Befund): GLM-MTP-Zähler werden mit Resident-State getauscht, die Harness behandelt sie aber als Engine-Lifetime-Counter. Warmup→neuer Chat kann deshalb den ersten Turn unterzählen. Vor Akzeptanzraten-Abnahme angleichen; Rohwerte erhalten, keine bereinigten Quoten als Beweis ausgegeben.
P13-Zählerscope korrigiert und geprüft (10.09.):
local-eval-results/glm-counter-scope-20260910.HgghwY/manifest.md enthält den
roten/grünen Sessionwechsel-Test und den vollständigen Produkt-MTP-Chat. Die
fünf kumulativen Zähler bleiben nun auf der aktiven Engine, während Cache und
Draft-Zustand mit dem Chat wechseln. Test prüft Rückkehr in den alten Chat,
monotone Zähler und bitgleichen rekurrenten Zustand. Alle drei Antworten und
Tokenzahlen stimmen per cmp mit dem vorherigen Lauf überein. Summary zählt
nun385 statt377 Zyklen und241 statt236 Accepts: Warmup8/5 wurde zuvor fälschlich
abgezogen. Story/Python unverändert. Keine neue GPU-Arbeit; CB-Zahlen gleich.
Kein Performance-Pass: Decode22,336/18,682/29,075 tok/s, Prefill-CB-Max4,451s;
Canary aus. Wächter Exit0, kein laufender Modellprozess. Direkte DS4-Laufzeit-
Referenz und sechszellige Abnahme bleiben offen; Klärung der AGENTS.md-Regel
gegen Kompilieren/Aufrufen des C-Referenzprogramms erforderlich. Keine
C-Produktintegration vorgesehen oder vorgenommen.
Fokussierte GPU-/CPU-Tests, Release-Clippy, Build, Format-/Diffcheck bestanden. Keine C-Integration, kein Bundle/Commit/Push, Gesamtziel weiterhin offen.
Ursprünglicher Befund und Abnahmekriterien:
Priorität P1; nach P04, P13; Quellcodedifferenz belegt.
- Rust
eval_speculative_greedyführt beim kompatiblen Draft ersteval_glm53_capture(token)und bei Acceptance nochmalseval_glm53_capture(draft)aus. DS4ds4_session_glm_spec_cycle_impl(ds4.c:64176) verifiziert das Paar in einem Zwei-Zeilen-Batch mit KDA-Backup/Restore. - Target-Forward, Draft-Head, Rollback und History separat vergleichen. Acceptance allein beweist keinen Geschwindigkeitsgewinn, wenn Target-Arbeit nicht amortisiert wird.
- Abnahme: echter 2-Row-Verify-Aufruf im Receipt, korrekter KDA/DSA/KV-Zustand bei Match/Mismatch/Cancel, gleiche Sampling-Kategorie und keine Output-Korruption. Danach vollständige GLM-AR/MTP-Chats neu messen; alte überlappte Daten nicht verwenden.
P15 — DS/GLM-Scheduling, Kaltstart und gemeinsame Runtime abgleichen
Aktiver GLM-Pfad und durchgehender Canary geprüft (10.09.):
local-eval-results/glm-scheduling-canary-20260910.T1ABR1/{manifest.md,comparison.json}
enthält zwei vollständige AR/MTP-Chats bis EOS bei Power100/Low und Canary an.
Ausgabe einschließlich Tokens/Thinking/Abschluss ist jeweils exakt zum letzten
Canary-off-Lauf. MTP854/AR935 Proben, keine Fehler, Maxima302,140/251,040ms im
Prefill; Decode-Maxima27,847/0,929ms. Keine Probe über2s. Ein mehrsekündiger
Modell-Command-Buffer blockiert diese unabhängige GPU-Probe nicht automatisch
gleich lange. Keine echte GUI-Eventloop- oder Referenz-Latenzabnahme daraus.
Wichtige Quellzuordnung: Im aktuellen DS4 ist expanded/full-KV deaktiviert;
GLM5.3 benutzt auch für den dichten Compact-Prefix den indexed-Graph. Dieser
übergibt die Batchtokenzahl als command_rows, nicht pos+rows. Deshalb passt
die vorhandene Prefill-Flush-Bedingung für die aktiven <=2048er-Chunks; die
anderslautende Bedingung des nicht aktiven full-KV-Pfads darf nicht blind in
Rust übernommen werden. Konkrete Restabweichung im residenten skalaren Decode:
DS4 flusht periodisch alle4 Layer (ohne letzten Layer), Rust nur einmal nach4.
SSD-Expert-Streaming hat eigene Command-Ownership-/Sync-Regeln und ist separat
abzugleichen. Außerdem Host-Encoding-Progress von abgeschlossener GPU-Arbeit
trennen. Das Manifest enthält die zusammenhängende Folgearbeit samt Abnahmen.
GLM-Teilprefill: HC-Arbeitsmenge korrigiert (10.09.):
local-eval-results/glm-hc-bounds-20260910.BKGvSr/manifest.md dokumentiert
den roten/grünen Produktpfad-Test. Dense und indexed DS4-Prefill begrenzen
HC-/Collapsed-Ausgaben mit token-genauen Views. Rust übergab bisher die gesamte
Workspace-Kapazität, obwohl sowohl HC-Expansion als auch Split/Sum ihre
Zeilenanzahl aus den Ausgabebytes ableiten. Der Regressionstest weist echte
Schreibzugriffe auf unbenutzte Zeilen nach. Fünf einmalig pro übergroßem Batch
erzeugte, nichtkopierende Views begrenzen jetzt sämtliche vier HC-Aufrufe je Layer;
der gemeinsame Pfad gilt für normalen Prefill und Zwei-Zeilen-Verifikation.
Alle fünf Guard-Ausgaben sowie die vorhandenen Rewind-/Rejection-/Counter-
Prüfungen bestehen. Keine neuen Flushes, keine Chunkverkleinerung, kein anderer
Kernel oder Sampler. Das beweist unnötige Arbeit, nicht deren Anteil an den
mehrsekündigen Command Buffers oder an GUI-Stalls. Eine zuerst vermessene Variante
mit Views auch für bereits exakte Workspaces wurde wegen schlechterer Laufzeiten
nicht beibehalten; Vorher-/Kontrollbinary sind hash-identisch. Die gezieltere
Variante besteht alle Guards mit 2048er-Workspace und den vollen MTP-Chat mit
exakt gleicher Ausgabe. Prefill Summary/Story/Python 6418/269/311ms gegenüber
6648/394/452ms im ersten Vorher-Lauf, Decode22,500/19,173/30,988tok/s.
Gesamt96,901s liegt zwischen den beiden Vorher-Läufen99,559/95,288s, deshalb
kein belastbarer Gesamt-Speedup. Maximaler CB weiterhin4,424s; Canary aus.
AR-Chat ebenfalls natürlich beendet, Tokens/Text/Thinking/Abschluss identisch
zum vorherigen AR-Beleg; Prefill8614/278/333ms, Decode21,648/20,967/21,778tok/s,
Max-CB6,150s. Kein frisches AR-Referenzpaar. Zwischenstände, Messstreuung und
ausstehende Responsivitätsabnahme bleiben sichtbar. P15/P16 offen.
Priorität P1; nach P01, P04, P13; Source-Inventar vorhanden, Detailbeweis offen.
- DS4
ds4.c:35309teilt nichtkleine Prefills auch wegen echter Progress-Callbacks. GLM-Referenz:47379berechnet Stage-Sync, Layer-Flush, Progress-Flush und Drain getrennt. Rust GLM koppelt Flush an Logits-Anforderung; Zwischenchunks können anders laufen. DeepSeek/GLM nicht blind auf eine Qwen-spezifische Policy umstellen. - Prefill/Decode-Power, echte Pausen bei <100%, Keine-Pause bei 100%, SSD-/Resident- Varianten, finale und nichtfinale Chunks sowie Cancel-Keepalive prüfen.
- Kalten UI-
pingseparat reproduzieren: Modell-/Pipeline-Laden, Systembootstrap, Restore und erster Prefill. Kein Warmup darf diesen Fehler unsichtbar machen. OS-Pagecache nicht global leeren; Prozess-kalt und tatsächlich SSD-kalt unterscheiden. - Abnahme: Dispatch-/Wait-/Progress-Trace je Phase gegenüber DS4-Code; kalter Ping und warmer Chat enden ohne unbeobachtete Phase. Release-Bundle- und Harness- Buildidentität dokumentiert. Noch fehlende direkte DS4-Laufzeitreferenz transparent halten; C-Inferenz wegen Projektvorgabe nicht eigenmächtig starten.
P16 — Gezielte Änderungen erneut messen und Gesamtmatrix abnehmen
Priorität P1; nach den relevanten P01–P15; offen.
Aktuelles interaktives Test-Bundle bereitgestellt (10.09.,22:32):
make bundle und strikte Codesign-Prüfung bestanden. Das Bundle enthält den
zuletzt vermessenen Release-Code und identische Metal-Ressourcen; der genaue
signaturbedingte Mach-O-Unterschied ist im Manifest
glm-scheduling-canary-20260910.T1ABR1 nachgewiesen. model-eval --help direkt
aus dem Bundle besteht ohne Modell-/GUI-Start. Der bisherige September6-Build
ist ersetzt. Kein tatsächlicher GUI-Eventloop-/Kaltstart-Test und keine
sechszellige Performance-Abnahme; die Anwendung ist als Teststand verfügbar.
Neue Plain-Chat-Referenzdiagnose (2026-09-05): Unveränderter MTPLX-Server,
exakte eingefrorene Eingabeprompts und Samplerwerte der Rust-Diagnose, keine
zusätzliche leere Systemnachricht; AR und MTP sequenziell, vollständiger
Summary/Story/Python-Chat. Alle Antworten natürlich beendet, Python-Prüfungen
bestanden, beide Supervisor exit 0. Erster Summary-Prompt identisch 2617 Tokens:
MTPLX-Prefill 2,455 s AR / 2,528 s MTP versus Rust 4,483 / 4,697 s mit sogar
30 bereits gecachten Tokens. Referenz-MTP-Decode 71,403/55,527/90,376 tok/s versus
Rust 53,976/38,874/61,596. Kein Pass: Canary an, jeweils Einzelmessung, andere
gesampelte Historien, Cache-Arbeit und Stop-Token-Zählweise. MTPLX zählt das
Stop-Token mit, Rust nicht; dieser Messvertrag gehört zu P04, keine unautorisierte
Änderung der Produktzähler. Referenz-Canary max 4,679/4,540 ms gegenüber
Rust 102,483/84,761 ms. Der Rückstand bleibt sichtbar, auch ohne Mehrsekunden-Stall.
Details, Rohdaten, Hashes und Grenzen:
local-eval-results/20260905-plain-reference/manifest.md.
- Während der zusammenhängenden Qwen-Portierung: Referenz-/Regressionstests für Funktions-, Kernel- und State-Abdeckung; Änderungen und Restabweichungen hier nachtragen. Gesamt-Performancevergleich erst nach vollständiger Integration, nicht als Auswahlverfahren für einzelne Referenzbestandteile.
- Endmatrix: DeepSeek AR/DSpark, GLM AR/MTP, Qwen AR/MTP. Leistung 100%, Chunks 2048 soweit Produkt/Referenzvertrag, kleinster aktiver Thinking-Level; Sampler und MTP-Einstellungen innerhalb jedes Referenzpaares identisch, keine künstliche Gleichsetzung verschiedener Modellverträge.
- Pro Zelle separater Warmup, danach Summary README → Story → Python als ein ongoing Chat bis EOS. Zusätzlicher kalter Ping; keine Gesamtzeitbegrenzung. Startup-/Fortsetzungswatchdog, echte Fortschrittsereignisse, Speichergrenze, Prozessüberwachung und genau ein GPU-Modell gleichzeitig.
- Saubere Performance-Läufe Canary aus, separate vollständige Responsiveness-Läufe Canary an; mindestens drei gepaarte Wiederholungen in wechselnder Reihenfolge. Bei Messstreuung in Größenordnung der 2%-Grenze kein Pass aus einem Einzelwert.
- Tabelle je Turn: neue/cached/Output/Thinking-Tokens, Load/Restore/Prefill/TTFT, Prefill- und Decode-tok/s, Gesamtzeit, MTP-Akzeptanz und Zeitzerlegung, GPU/Host/UI-p50/p95/p99/max, Peak-Footprint, IO und Abschlussursache.
- Inhaltliche Abnahme: Summary deckt README ab; vollständige Story ohne Rückfrage; Python-One-shot anhand vorab festgelegter kleiner funktionaler Assertions prüfen. Generierten Code vor Ausführung prüfen und isolieren, keine Tools/Netzwerkrechte.
- Durchsatzziel: mindestens 98% der matched-work Referenzgeschwindigkeit; schneller erlaubt. Gesamtzeiten der natürlichen Chats zusätzlich zeigen, aber unterschiedliche Antwortlängen nicht als Kernelregression ausgeben. Latenz separat abnehmen; ein schneller Durchschnitt kompensiert keinen Mehrsekunden-Stall. Nutzerentscheidung vom 2026-09-10: Die beobachteten 2,6% Rückstand bei Qwen Summary ohne MTP sind als eng begrenzte Ausnahme akzeptiert, ausschließlich wenn alle übrigen Punkte erledigt sind und die produktive Anwendung ansonsten Funktions- und Performance-Parität erreicht. Keine allgemeine Toleranzerhöhung, keine vorgezogene Abnahme und keine Ausnahme für Stalls, Prefill oder andere Turns.
R01 — MTPLX-Speculation als zusätzliche Optimierungsquelle für DS/GLM
Separater Recherche-Task; nach belastbarer DS4-Baseline P13–P16, kein Wechsel des Golden Masters und keine Voraussetzung für die erste Paritätsabnahme.
- Im gepinnten MTPLX existiert ein eigener DeepSeek-V4-Backendpfad
(
mtplx/models/deepseek_v4.py, Registrierungmtplx/backends/registry.py:299). Native MTP-Köpfe dort nicht ohne Prüfung mit DSpark/DFlash gleichsetzen. - Generische Techniken wie batched verify, lazy distributions, begrenzte Capture-Commits, Deferred Repair und Draft-Tiefensteuerung auf Übertragbarkeit für beide Modelle untersuchen. Eine native GLM-5.3-Flash-Unterstützung wird hier nicht behauptet; allgemeine Techniken können auch ohne diesen Backendpfad relevant sein.
- Ergebnis: kurze Kandidatenliste mit exakter Quellstelle, Artefakt-/Draft-Vertrag, unveränderter oder abweichender Sampling-Semantik, gemessenem Referenzvorteil und kleinstem A/B-Versuch. Nicht passende oder nur beworbene Vorteile aussortieren.
- Abnahme einer späteren Übernahme weiterhin gegen antirez/ds4: gleiche Funktion, keine schlechtere Responsiveness, belegter Performancegewinn. Kein Download anderer Artefakte und keine Umstellung auf MTPLX-Runtime als Abkürzung.
Reihenfolge und Fortschrittsführung
Zuerst P01–P04 als belastbare Vergleichsgrundlage. Danach P05/P06 für den belegten Qwen-Prefill-Fehler und P12 für unbeschränkte Repair-Kosten; P11 liefert dafür den Sampler-/Acceptance-Nachweis. P07–P10 schließen die übrigen Kernel-/IO-Unterschiede. P13 muss vor DSpark-Vergleichen erledigt werden, P14/P15 vor der DS/GLM-Freigabe. P16 misst den vollständig integrierten Qwen-Port und die komplette Modellmatrix; die frühere Mikrobenchmark-Auswahl pro Änderung ist aufgehoben.
Pro Task werden Status, konkreter Patch, Referenz-/Arbeitsstand, Testbefehl, Rohdatenpfad, vorher/nachher und verbleibende Differenz ergänzt. Eine Abweichung verlässt die Liste nur durch Nachweis oder ausdrückliche Nutzerentscheidung, nicht durch Weglassen aus dem nächsten Bericht.