Orion: Characterizing and Programming Apple's Neural Engine for LLM Training and Inference
Abstract
Over two billion Apple devices ship with a Neural Processing Unit (NPU) - the Apple Neural Engine (ANE) - yet this accelerator remains largely unused for large language model workloads. CoreML, Apple's public ML framework, imposes opaque abstractions that prevent direct ANE programming and do not support on-device training. We present Orion, to our knowledge the first open end-to-end system that combines direct ANE execution, a compiler pipeline, and stable multi-step training with checkpoint resume in a single native runtime, bypassing CoreML entirely via Apple's private _ANEClient and _ANECompiler APIs. Building on prior characterization work by maderix, we extend public knowledge of ANE constraints to a catalog of 20 restrictions on MIL IR programs, memory layout, compilation limits, and numerical behavior, including 14 previously undocumented constraints discovered during Orion development. Orion includes a compiler that lowers a graph IR through five optimization passes to ANE-native MIL and a runtime that manages IOSurface-backed zero-copy tensor I/O, program caching, and delta compilation for weight updates. Because the ANE bakes weights at compile time, naive training normally requires full recompilation per step (~4.2 s). We show that compiled programs can instead be updated by unloading, patching weight files, and reloading, bypassing ANECCompile() and reducing recompilation from 4,200 ms to 494 ms per step (8.5x), yielding a 3.8x training speedup. On an M4 Max, Orion achieves 170+ tokens/s for GPT-2 124M inference and demonstrates stable training of a 110M-parameter transformer on TinyStories for 1,000 steps in 22 minutes with zero NaN occurrences. We also present LoRA adapter-as-input, enabling hot-swap of adapters via IOSurface inputs without recompilation.
Figures & tables
| Property | Value |
|---|---|
| Generation | H16 |
| Neural Engine cores | 16 |
| Peak throughput (INT8, Apple spec) | 38 TOPS |
| Peak throughput (fp16, measured 1 1 footnotemark: 1 ) | 19 TFLOPS |
| On-chip SRAM 2 2 2 Apple specifies 38 TOPS (INT8), but the ANE dequantizes INT8 to fp16 before computation. Actual measured peak is 19 TFLOPS fp16 ( maderix, 2026c ) ; INT8 saves only memory bandwidth, not compute cycles. | 32 MB |
| Evaluation queue depth | 127 |
| Class | Role |
|---|---|
| _ANEClient | Singleton connection to ANE daemon |
| _ANECompiler | MIL E5 microcode compilation |
| _ANEInMemoryModel | In-memory model (no filesystem) |
| _ANEInMemoryModelDescriptor | Accepts MIL + weight blobs |
| _ANEModel | Holds compiled program handle |
| _ANERequest | Evaluation request specification |
| # | Constraint | Symptom | Workaround | Src |
|---|---|---|---|---|
| 1 | concat MIL op rejected by ANE compiler | Compile failure | Split into separate programs | O |
| 2 | Multi-output buffers must have uniform sizes | 0x1d at eval | Pad outputs to max size | O |
| 3 | Multi-output surfaces ordered alphabetically | Silent wrong data | Name outputs in sorted order | O |
| 4 | Minimum 49 KB IOSurface for eval | 0x1d at eval | Pad seq dim 16 | O |
| 5 | 119 compilations per process limit | Silent fail / crash | exec() restart | P |
| 6 | SDPA causal masks silently ignored | Wrong attention | Manual causal masking | P ∗ |
| Category | Operations |
|---|---|
| Data | input , const , identity |
| Linear | conv1x1 , matmul |
| Elementwise | add , sub , mul , neg |
| Activation | relu , tanh , sigmoid |
| Math | exp , pow , sqrt , rsqrt |
| Reduction | reduce_sum , reduce_mean , reduce_max |
| Operation | Device | Reason |
|---|---|---|
| Transformer fwd/bwd (dx) | ANE | Compute-bound convolutions |
| Token sampling | CPU | Sequential, branching logic |
| Adam optimizer | CPU | Weights immutable on ANE |
| accumulation | CPU | cblas_sgemm via GCD |
| NLL loss + gradient | CPU | gather not in MIL |
| Classifier backward | CPU | 32K channels rejected |
| Metric | v1.0 | v2.0 | Speedup |
|---|---|---|---|
| Train time (compute) | 908 ms | 849 ms | 1 |
| Recompile / reload time | 4,200 ms | 494 ms | 8.5 |
| Total step time | 5,108 ms | 1,345 ms | 3.8 |
| Recompile % of step | 83.9% | 36.8% | 47.1 pp |
| 1000-step wall time | 85 min | 22.4 min | 3.8 |
| Process model | 1 step/process | Single process | — |
| Metric | Value |
|---|---|
| Resume chains tested | 5 |
| Steps per chain | 5 (each in a fresh process) |
| Total training steps | 25 |
| NaN / Inf occurrences | 0 / 25 |
| Loss monotonically decreasing | 5 / 5 chains |
| Step 1 loss (mean std across chains) |
| Step | Chain 1 | Chain 2 | Chain 3 | Chain 4 | Chain 5 |
|---|---|---|---|---|---|
| 1 | 13.979 | 13.978 | 13.975 | 13.974 | 13.971 |
| 2 | 13.968 | 13.965 | 13.962 | 13.961 | 13.958 |
| 3 | 13.946 | 13.949 | 13.945 | 13.941 | 13.935 |
| 4 | 13.932 | 13.927 | 13.924 | 13.926 | 13.920 |
| 5 | 13.923 | 13.916 | 13.911 | 13.911 | 13.904 |
| Configuration | Throughput | Latency (p50) |
|---|---|---|
| CPU decode | 283 tok/s | 3.48 ms/tok |
| ANE full forward (decode) | 170 tok/s | 5.76 ms/tok |
| ANE prefill (first call) | 12 tok/s | — |
| ANE prefill (cached) | 165 tok/s | — |
| Metric | v1.0 | v2.0 |
|---|---|---|
| Compute time (mean) | 908 ms/step | 849 ms/step |
| Recompile / reload time | 4,200 ms/step | 494 ms/step |
| Total step time | 5,108 ms/step | 1,345 ms/step |
| Throughput | 0.612 TFLOPS | 0.656 TFLOPS |
| 1000-step wall time | 85 min | 22.4 min |
| NaN occurrences | 0 / 1,000 | 0 / 1,000 |
| Operation | CPU | ANE | Speedup |
|---|---|---|---|
| Classifier fwd (embed ) | 10.77 ms | 1.06 ms | 10.2 |
| Softmax (vocab=32000) | 81.11 ms | 2.40 ms | 33.8 |
| RMSNorm backward | 0.18 ms | 0.21 ms | 1 |
| Framework | Hardware | Training | ANE Direct | Compiler | Weight Update |
|---|---|---|---|---|---|
| MLX ( Apple Machine Learning Research, 2023 ) | GPU | Yes | No | Yes | In-memory |
| llama.cpp ( Gerganov and others, 2023 ) | CPU+GPU | No | No | No | N/A |
| MLC-LLM ( Chen and others, 2023 ) | GPU | No | No | Yes | N/A |
| CoreML ( Apple Inc., 2023 ) | CPU/GPU/ANE | No | No | Yes | Recompile |
| Orion | ANE | Yes | Yes | Yes | Delta reload |