Dokumentation

Neural Engine: Geschwindigkeits- und Energiemessungen

Die FP16-ANE-Neuschreibung verbessert die Geschwindigkeit vollständiger Vorhersagen um 1.39× und die geschätzte Gesamtsystem-Energie pro Entscheidung um 2.78× gegenüber kompiliertem MLX FP16. Der separat validierte W8-K-means-Kandidat erreicht jeweils 1.42× und 3.19×. Keiner von beiden erreicht das geforderte 10×-Ziel. Dies sind lokale M3 Max-Ergebnisse, mit den Präzisions- und Leistungsmessgrenzen unten.

Die Implementierungs- und Konvertierungsexperimente stehen in ANE_ENGINEERING.md; mathematische Schranken und Treueverträge in ANE_MATH.md.

Finaler Vergleich anhaltender kurzer Entscheidungen

M3 Max, 40 GPU-Kerne, 128 GiB, macOS 27.2. Derselbe mehrsprachige Quell-Checkpoint, dieselben acht Varianten des Rechnungszustands, eine Frage mit vier Optionen pro Anfrage, 91 echte Tokens auf 96 aufgefüllt. Kein Ausgabe-Cache und keine generierten Tokens. Alle drei Modelle bleiben resident; Laden, Kompilierung und Warmup liegen außerhalb der gemessenen Intervalle.

Die Baseline aktiviert mx.compile, Prompt-Prefix-Caching und 32-Token-Shape-Buckets. Sie ist schneller als die historische Eager-MLX-Baseline. Der FP16-ANE-Kandidat erhält die ursprünglichen Gewichte, mit einem vollständigen Core ML-Transformer-Body, Host-Embedding-Lookup und FP32-CPU-Action-Tail. W8 verwendet gruppierte K-means-Weight-Only-Palettenkompression, keine W8A8-Arithmetik; seine Aktivierungen verwenden weiterhin FP16, und sein Host-Action-Tail bleibt FP32.

Metrik MLX GPU FP16, kompiliert ANE FP16 ANE W8 K-means
Abgeschlossene Entscheidungen 17,184 23,961 24,453
Gemessene aktive Dauer 120.02 s 120.02 s 120.02 s
End-to-End P50 6.937 ms 4.976 ms 4.879 ms
End-to-End P95 7.393 ms 5.307 ms 5.227 ms
Mittlere verstrichene Zeit pro Entscheidung 6.984 ms 5.009 ms 4.908 ms
Mittlere Gesamtsystem-Leistungsschätzung 61.39 W 30.75 W 27.39 W
Gesamtsystem-Energie pro Entscheidung 0.4288 J 0.1540 J 0.1344 J
Um Leerlauf bereinigte Energie pro Entscheidung 0.3393 J 0.0888 J 0.0715 J
Geschwindigkeitsgewinn ggü. kompiliertem MLX 1× 1.394× 1.423×
Gesamtsystem-Energiegewinn ggü. kompiliertem MLX 1× 2.784× 3.189×
Um Leerlauf bereinigter Energiegewinn ggü. kompiliertem MLX 1× 3.823× 4.749×

Verhältnisse verwenden Intervallmittel, einschließlich aller abgeschlossenen Arbeit:

FP16: speed 1.394 × average system-power ratio 1.997 = energy gain 2.784
W8:   speed 1.423 × average system-power ratio 2.241 = energy gain 3.189

Ein Energieverhältnis erneut mit der Geschwindigkeit zu multiplizieren, zählt die verstrichene Zeit doppelt. Die um Leerlauf bereinigte Zeile verwendet eine andere Messgrenze; sie bedeutet nicht, dass die Leistung des ganzen Laptops um 3.8–4.7× fällt. Dies sind Intervalle gesättigten Durchsatzes. Für eine Leistungsaussage bei festem FPS wäre ein Experiment mit gleicher Anfragerate erforderlich. W8 verbessert die mittlere Geschwindigkeit in dieser Sitzung nur um etwa 2.1% gegenüber FP16, während sein Body-Paket von 251.91 auf 129.29 dezimale MB schrumpft. Die Paketgröße schließt den ursprünglichen Checkpoint und die Host-Embedding-Tabelle aus und ist nicht der gesamte Laufzeitspeicher.

Jede Implementierung lief sechs 20-Sekunden-Blöcke in drei ausgewogenen Zyklen von MLX, ANE FP16, ANE W8, ANE W8, ANE FP16, MLX. Zehn Sekunden Idle-Sampling trennen die Blöcke; die ersten drei Leerlaufsekunden werden verworfen, und benachbarte eingeschwungene Leerlaufleistung wird gemittelt. Die Leistungsbereiche der Backend-Blöcke waren 60.32–62.38 W für MLX, 29.28–35.14 W für FP16 ANE und 26.68–27.95 W für W8 ANE. Andere Desktop-Anwendungen waren geöffnet; die Abwechslung und das benachbarte Idle-Sampling reduzieren, beseitigen aber nicht die Unsicherheit durch Hintergrundlast und Sensor.

Alle 65,598 Vorhersagen stimmen mit der gerundeten Warmup-Ausgabe ihres Backends für den entsprechenden Zustand überein. Alle drei Backends wählen bei diesen acht Zuständen dieselbe Antwort. Die separate Treue-Suite ist breiter: FP16 L96 besteht 59/59 passende Fragen mit maximaler Wahrscheinlichkeitsabweichung 0.002925; W8 besteht dieselben 59 mit Abweichung 0.014393 unter dem unveränderten 0.02-Gate. Das vollständige 63/63-Ergebnis gehört zum separat exportierten FP16-L1024-Modell. Das sind Regressions-Fixtures, keine Behauptung allgemeiner Aufgaben-Genauigkeit oder erhaltener Kalibrierung auf beliebigen Eingaben.

Der Lauf behielt 1,101 Leistungsproben; die maximale Lücke betrug 0.510 Sekunden, und die maximal aufgezeichnete Systemleistung betrug 74.47 W. Keine Probe wurde verworfen. Der RSS pro Block wird für den gemeinsamen Prozess aufgezeichnet, während alle Modelle und Aufzeichnungspuffer resident sind; diese Werte lassen sich nicht dem Modellspeicher eines einzelnen Backends zuordnen. Die aktuellen Laufzeit- und Paket-Fingerabdrücke werden mit dem Bericht gespeichert.

Finale Rohaufrufe und PSTR-Proben · Geprüfte Zusammenfassung und Bootstrap-Intervalle innerhalb der Sitzung

Der frühere FP16-only-Pilot maß 1.410× Geschwindigkeit und 2.939× Brutto-Systemenergiegewinn. Er stammt aus der Zeit vor den letzten Eingabeprüfungen und der Pro-Aufruf-Stabilitätsinstrumentierung; der frische Dreiarm-Lauf oben ist der veröffentlichte Vergleich für die finale Laufzeit. Ein Metadaten-Vorbehalt im finalen Rohbericht beschrieb anfangs den historischen macmon-Komponentensummen-Untergrenzwert bedingungslos; ein additiver metadata_corrections-Eintrag stellt klar, dass dieser Lauf nur PSTR verwendete. Die ursprünglichen Felder und alle Messungen bleiben erhalten.

Snake-Kompatibilität ist eine separate Workload

Derselbe veröffentlichte Snake-Planner, kompakte Prompts und dieselbe Sicherheitsrichtlinie liefen sowohl auf dem FP16-ANE-Adapter als auch auf kompiliertem MLX, wobei die Auswertungsreihenfolge bei identischen Live-Zuständen abwechselte. Die Seeds 101 und 102 absolvierten jeweils 300 Schritte: 600/600 vorgeschlagene und ausgeführte Aktionen stimmen überein, null Tode und null Schildeingriffe. Die Endpunktzahlen waren 9 und 10, mit Snake-Längen 15 und 16. Die maximale Zugwahrscheinlichkeits-Differenz betrug 0.0036. Dies validiert diesen FP16-Trajektorienvergleich, nicht das Snake-Verhalten eines komprimierten Modells oder unbegrenztes Überleben.

Seed ANE vollständige Entscheidung P50 / P95 Kompiliertes MLX vollständige Entscheidung P50 / P95
101 23.45 / 27.10 ms 17.14 / 23.58 ms
102 17.68 / 27.30 ms 19.18 / 33.27 ms

Der ANE-Adapter führt drei Fragen sequenziell bei B1/L96 aus; MLX bündelt die drei Fragen bei bis zu L64. Diese Timings umfassen Planner-Features und vollständige Vorhersagen, schließen die Arbeit des anderen Backends, den Spielschritt und das Terminal-Rendering aus und zeigen erhebliche Variation. Sie belegen keine konsistente Snake-Beschleunigung und keine maximale stabile Renderingrate. Das Einzelfragen-Ergebnis von 4.98 ms darf nicht als vollständige Snake-Frame-Zeit beworben werden. Ein dedizierter B3/L64-ANE-Export wäre eine separate Optimierungs- und Validierungsaufgabe.

Roh-Snake-Zustände, -Ausgaben und -Timings

python -m benchmarks.snake artifacts/ane-repro/body96/model.mlpackage \
  /path/to/original/laya-multilingual --ane --mlx-compiled \
  --steps 300 --seeds 101 102 --output artifacts/ane-snake.json

Messgrenze und Telemetrie-Grenzen

Jeder zeitlich gemessene Aufruf umfasst Prompt-Konstruktion, Tokenisierung, Array-Konstruktion, Host-Embedding-Lookup (falls zutreffend), synchrone Modellausführung, Action-Features, Kalibrierung und Ausgabeformatierung. MLX wertet seine Lazy-Ausgaben aus; Core ML gibt fertige NumPy-Arrays zurück. Dies vergleicht ungecachte Vorhersagen, nicht isolierte Modell-Kernel.

Der finale Vergleich verwendet den kleinen, unprivilegierten PSTR-only-Sampler. Er fixiert die Low-Level-SMC-API aus macmon 0.8.2, öffnet eine schreibgeschützte Verbindung und sampelt den ursprünglichen PSTR-Wert alle 500 ms. Er liest keine IOReport-Komponentenzähler. Das ist eine Ganzsystem-Sensorabschätzung, keine externe Wand- oder Akkuleistungsmessung. Der Executable-Hash und die Quellherkunft werden mit den Rohergebnissen aufgezeichnet.

Dieser separate Sampler war notwendig, weil die offizielle macmon-CLI sys_power = max(PSTR, component_sum) berechnet, wie in ihrer Quelle gezeigt. CPU- und ANE-Zähler lieferten auf diesem OS üblicherweise null, dann sprang eine Probe auf ungefähr 38,021 W CPU und 2,068 W ANE. Die Komponenten-Untergrenze pflanzte diesen Fehler in eine Systemablesung von 40,089 W fort. Die genaue Ursache der IOReport-Anomalie ist ungeklärt; der ursprüngliche PSTR-Wert lässt sich aus dieser Probe nicht rekonstruieren. Der gesamte betroffene Energielauf wurde verworfen, ohne die schlechte Probe zu entfernen oder zu begrenzen. Ihr Rohdatensatz bleibt verfügbar, aber ihre gespeicherten Energieaggregate dürfen nicht als Ergebnisse verwendet werden.

Der frühere FP16-only-Lauf verwendete das offizielle macmon v0.8.2-Release, dessen Archiv-SHA256 als 588d5bde79885ba36f693e5150911c10c3ad208a2e418a3f2aa827ac84a2d973 verifiziert wurde. Er bestand die späteren Plausibilitätsprüfungen und bleibt historischer Beleg. Der finale PSTR-only-Lauf misst jedes Backend erneut mit einem einheitlichen Sampler.

Die Testumgebung integriert Watt über monotone Empfangs-Zeitstempel mit interpolierten Grenzen. Fehlende, nichtpositive, nicht-endliche oder über 500 W liegende Systemablesungen verwerfen den Lauf. Die 500-W-Obergrenze ist eine bewusst lockere Plausibilitätsprüfung für diesen M3 Max, keine kalibrierte Genauigkeitsschranke. Lücken über max(2 seconds, 3 × sample interval) verwerfen den Lauf ebenfalls. Die Zusammenfassung verifiziert vollständige ausgewogene Zyklen, Pro-Aufruf-Stabilität, Aufrufzahlen, aktive Energie, beide benachbarten Leerlaufintervalle und die resultierende um Leerlauf bereinigte Energie gegen die Rohproben. Inkrementelle Energie behält ihr Vorzeichen; sie wird nie begrenzt, um ein großes Verhältnis zu konstruieren.

Der direkte Sampler lässt CPU/GPU/ANE-Leistungsfelder weg, weil er sie nicht misst. Historisch fehlende oder nullwertige Komponentenzähler können keine Null-Energie oder das Fehlen einer ANE-Ausführung belegen. Das Bootstrap zieht erneut Stichproben aus vollständigen ausgewogenen Zyklen; drei Zyklen aus einer Desktop-Sitzung charakterisieren nicht die gesamte Hintergrundlast, zukünftige Läufe oder die Sensorgenauigkeit. Keines der gemessenen Verhältnisse liegt nahe bei 10×.

Führt die Neural Engine tatsächlich Arbeit aus?

Der Core ML Compute Plan des neu geschriebenen B1/L96-Graphen platziert alle 6,390 nichtkonstanten Operationen auf MLNeuralEngineComputeDevice; die verbleibenden 3,809 unbekannten Einträge sind Konstanten. Das ist antizipiertes Placement, für sich genommen kein ausreichender Hardwarebeleg. Der gewöhnliche SDPA-Export hatte auf diesem System keine NE-bevorzugten Operationen.

Ein separater 15.97-sekündiger Instruments-Core ML-Trace, aufgenommen, während der Kandidat mit CPU_AND_NE lief, erfasste 3,124 aktive „Neural Engine Prediction“-Intervalle und einen unabhängigen Ladevorgang eines gecachten Systemmodells. Die exportierte Hardware-Tabelle liefert daher zusätzlich zum Compute Plan einen positiven Beleg für ANE-Aktivität zur Laufzeit. Die Tabelle ist global und ordnet nicht jeder Vorhersage eine PID oder Modellidentität zu; die Core ML-Modell-Marker-Tabelle war in dieser Aufzeichnung leer. Wir schreiben nicht jedes Hardwareintervall ausschließlich Laya zu und behaupten nicht, dass Host-Arbeit auf ANE läuft.

Die auf die Positivliste gesetzten Hardwareereignisse umfassen nur Zeitstempel, Dauer, Gerät, Label und Zustand. Vollständige Instruments-Archive und Prozessumgebungs-Metadaten bleiben im ignorierten artifacts/-Verzeichnis. Das Tracing war getrennt vom Energietest, und instrumentierte Hardwareintervalle werden nicht als End-to-End-Latenzergebnis verwendet.

Reproduzieren

Erstelle und validiere zuerst die festen L96-FP16- und W8-K-means-Pakete mit den Befehlen im Engineering-Bericht. Diese Befehle schreiben in frische Verzeichnisse unter artifacts/ane-repro/. Baue den direkten Sensor-Sampler lokal; es wird kein System-Daemon und kein privilegierter Dienst installiert.

pip install -e '.[convert,dev,compare,research]'
cargo build --release --locked --manifest-path benchmarks/pstr_sampler/Cargo.toml
python -m benchmarks.energy \
  --source /path/to/original/laya-multilingual \
  --candidate artifacts/ane-repro/body96-w8km/model.mlpackage \
  --fp16-candidate artifacts/ane-repro/body96/model.mlpackage \
  --candidate-factory experiments.ane_engineering.runtime:ANEAgent \
  --sampler benchmarks/pstr_sampler/target/release/pstr-sampler --pstr-only \
  --cycles 3 --seconds 20 --idle-seconds 10 \
  --output artifacts/energy.json

python -m benchmarks.energy_summary artifacts/energy.json \
  --output artifacts/energy-summary.json

Für unabhängige Laufzeitdiagnosen starte benchmarks.trace_ane, warte auf seine Ready-PID-Datei und hänge dann Instruments an, ohne dass eine andere Modell-Workload läuft:

python -m benchmarks.trace_ane \
  --source /path/to/original/laya-multilingual \
  --package artifacts/ane-repro/body96/model.mlpackage \
  --seconds 90 --ready artifacts/trace.pid
# From another terminal; use the PID written to that file.
xcrun xctrace record --template 'Core ML' --attach <PID> \
  --time-limit 15s --output artifacts/ane.trace
xcrun xctrace export --input artifacts/ane.trace --toc \
  --output artifacts/toc.xml
xcrun xctrace export --input artifacts/ane.trace \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="ane-hw-intervals"]' \
  --output artifacts/hardware.xml
python -m benchmarks.trace_summary --hardware-xml artifacts/hardware.xml \
  --toc-xml artifacts/toc.xml --output artifacts/hardware-summary.json

Der ursprüngliche Checkpoint und der kürzere Export haben getrennte Kontextlimits. Die L96-Laufzeit weist Eingaben zurück, die nicht passen; ein Geschwindigkeitsergebnis für eine kurze Workload belegt keine Performance bei 512/1024 Tokens oder über alle drei Laya-Checkpoints hinweg.