ANE README

The project's README from github.com/maderix/ANE. As one markdown file: README.md.

ANE Training — Backpropagation on Apple Neural Engine

Training neural networks directly on Apple's Neural Engine (ANE) via reverse-engineered private APIs. No CoreML training APIs, no Metal, no GPU — pure ANE compute.

Project Scope & Intent

I'm genuinely grateful for all the attention this project has received — I never expected a weekend research hack to blow up like this. Thank you to everyone who starred, forked, ran benchmarks on their own hardware, and shared the work. It means a lot.

That said, I want to set clear expectations about what this project is and isn't.

This is a research project, not a production framework.

The goal was to demonstrate that training on the Apple Neural Engine — and potentially other NPUs — is possible, and that the barrier has always been software support, not hardware capability. The ANE is a remarkably capable piece of silicon that Apple restricts to inference-only use through CoreML. This project bypasses that restriction using reverse-engineered private APIs to show what's possible when you give the hardware a chance.

What This Project Is

What This Project Is Not

On The Hype

Some coverage of this project has overstated its implications. To be clear:

The honest results — including all limitations — are documented in the accompanying articles:

On Maintenance

I don't intend to grow this into a large community project. My focus is on original research (compiler infrastructure for edge AI optimization), and maintaining an open-source framework takes time away from that.

That said:

Fork it, build on it

This is MIT licensed for a reason. Everyone now has access to AI-assisted development tools that can adapt and extend code in hours. If this project is useful to you — take it, modify it, build something better. If you do something cool with it, I'd love to hear about it.If in future, community decides to maintain one source of truth repo, I'm in full support of that.


What This Is

A from-scratch implementation of transformer training (forward + backward pass) running on the ANE in Apple Silicon. The ANE is a 15.8 TFLOPS FP16 (M4) inference accelerator that Apple does not expose for training. This project reverse-engineers the _ANEClient / _ANECompiler private APIs and the MIL (Model Intermediate Language) format to run custom compute graphs — including backpropagation — directly on ANE hardware.

Current results:

Model Params ms/step Pipeline
Stories110M (12L, dim=768, MHA 12/12) 109M 91 ms Dynamic (no recompile)
Qwen3-0.6B (28L, dim=1024, GQA 16/8) 596M 412 ms Dynamic (no recompile)

INT8 W8A8 quantization — 1.88x throughput (M4, H16G):

Config FP16 INT8 W8A8 Speedup
128x conv 512ch 64x64 18.6 TOPS, 14.8ms 35.1 TOPS, 7.8ms 1.88x
64x conv 512ch 64x64 18.4 TOPS, 7.5ms 34.1 TOPS, 4.0ms 1.85x

INT8 activations halve L2 SRAM bandwidth between tiles via MIL quantize/dequantize ops. Weights use constexpr_affine_dequantize (int8 stored, fp16 at compile time).

Architecture

The dynamic pipeline uses shared ANE kernels with weights packed into spatial dimensions (no recompilation when weights change):

MHA models (Stories110M) — 6 kernels per layer:

Kernel Function
sdpaFwd QKV projection + SDPA + output projection
ffnFused SwiGLU FFN (W1, W3, SiLU, W2)
ffnBwdW2t / ffnBwdW13t FFN backward (split for memory)
sdpaBwd1 / sdpaBwd2 SDPA backward

GQA models (Qwen3-0.6B) — 10 kernels per layer: Adds separate woFwd, qBwd, kvBwd kernels for grouped-query attention (Q_DIM ≠ DIM).

CPU handles: RMSNorm forward/backward, residual connections (DeepNet α scaling), loss computation, dW gradient accumulation (cblas_sgemm), Adam optimizer updates.

Key optimizations:

File Structure

├── api_exploration.m           # Initial ANE API discovery
├── inmem_basic.m               # In-memory MIL compilation proof-of-concept
├── inmem_bench.m               # ANE dispatch latency benchmarks
├── inmem_peak.m                # Peak TFLOPS measurement (2048x2048 matmul)
├── ane_int8_bench.m            # INT8 W8A8 vs FP16 throughput benchmark
├── sram_bench.m                # ANE SRAM bandwidth probing
├── sram_probe.m                # SRAM size/layout exploration
├── gpu_ane_share.m             # GPU↔ANE zero-copy IOSurface demo
├── gpu_prefill_ane_decode.m    # GPU prefill → ANE decode pipeline
├── bridge/
│   ├── ane_bridge.h            # C-callable ANE API (compile, eval, I/O)
│   ├── ane_bridge.m            # Bridge implementation (int8 + fp16 weight blobs)
│   └── Makefile
└── training/
    ├── ane_runtime.h           # ANE private API wrapper (compile, eval, IOSurface)
    ├── ane_classifier.h        # Classifier fwd (32K conv), softmax, rmsnorm on ANE
    ├── train_large.m           # Static pipeline (weights as constants, recompiles)
    ├── training_dynamic/
    │   ├── train.m             # Dynamic training loop (model-agnostic)
    │   ├── config.h            # Derived sizes, structs, alloc helpers
    │   ├── mil_dynamic.h       # MIL generators for dynamic weight kernels (GQA-aware)
    │   ├── io.h                # IOSurface I/O, weight staging, GQA tile/reduce
    │   ├── models/
    │   │   ├── stories110m.h   # Stories110M config (12L, MHA)
    │   │   └── qwen3_06b.h    # Qwen3-0.6B config (28L, GQA)
    │   └── Makefile
    ├── dashboard.py            # Live training dashboard (blessed TUI)
    └── Makefile

Training Data

Training requires pretokenized TinyStories data. To download:

cd training && bash download_data.sh

See training/README.md for detailed training instructions.

Building

Requires macOS 15+ on Apple Silicon (tested on M4).

# Dynamic pipeline (recommended) — model selected at build time
cd training/training_dynamic
make MODEL=stories110m    # Stories110M (12L, MHA, 109M params)
make MODEL=qwen3_06b      # Qwen3-0.6B (28L, GQA, 596M params)
./train --scratch          # train from random init
./train --resume           # resume from checkpoint

# Static pipeline (legacy — recompiles weights each step)
cd training && make train_large
./train_large ane_stories110M_ckpt.bin 256 100 1e-4

# INT8 benchmark
xcrun clang -O2 -fobjc-arc -framework Foundation -framework IOSurface -ldl \
  -o ane_int8_bench ane_int8_bench.m
./ane_int8_bench

# Bridge library (C-callable ANE API)
cd bridge && make

No external dependencies. Uses only system frameworks + private ANE APIs resolved at runtime via objc_msgSend.

How It Works

  1. MIL generation — Objective-C code constructs MIL program text at runtime, specifying convolutions (for linear layers), matmul (for attention), softmax, element-wise ops
  2. In-memory compilation — _ANEInMemoryModelDescriptor compiles MIL text + weight blobs directly to ANE programs, no disk mlmodelc needed
  3. IOSurface I/O — Input/output tensors passed via IOSurface shared memory in [1, channels, 1, spatial] format (fp16 or fp32; fp16 direct I/O is ~37% faster)
  4. Dynamic weights — Activations and weights packed into a single spatial input dimension, sliced apart inside the MIL kernel. Weights change without recompilation.
  5. Gradient flow — Forward taps expose intermediates needed for backward; backward kernels compute dx (input gradients) on ANE; dW (weight gradients) computed on CPU via cblas
  6. INT8 quantization — constexpr_affine_dequantize for int8 weights, quantize/dequantize between layers for int8 activation caching in L2 SRAM (1.88x throughput)

Limitations

Performance

Training throughput (M4):

Model Params ms/step Layers Kernels/layer
Stories110M 109M 91 ms 12 6 (MHA)
Qwen3-0.6B 596M 412 ms 28 10 (GQA)

ANE peak throughput (M4, H16G):

Precision Peak TOPS Config
FP16 18.6 128x conv 512ch 64x64
INT8 W8A8 35.1 128x conv 512ch 64x64

GPU↔ANE inference pipeline (M4, seq=256):

Model GPU Prefill ANE Decode Total
Stories110M 6.7ms 1.9ms 8.8ms
Qwen3-0.6B 9.7ms 2.3ms 12.0ms

Disclaimer

This project uses Apple's private, undocumented APIs (_ANEClient, _ANECompiler, _ANEInMemoryModelDescriptor). These APIs are not covered by any public stability guarantee and may change or break with any macOS update. This is independent research into Apple Neural Engine architecture, using APIs discovered through runtime introspection for research and educational purposes under fair use and interoperability provisions (see Sega v. Accolade, 1992; DMCA §1201(f)). No Apple proprietary code or binaries are included in this repository. This project is not affiliated with or endorsed by Apple Inc. Use at your own risk.

License

MIT — see LICENSE


Built by a human + Claude, one weekend at a time.

ANE (maderix/ANE)

Searching Database…

7.3K ·GitHub
这是什么?ANE 是一个研究项目,借助逆向工程得到的私有 API 直接在 Apple 神经网络引擎(Neural Engine)上训练神经网络,而不是走 CoreML 那条只支持推理的路线。
这是持续维护的训练框架,还是研究性质的取巧方案?它明确只是一个周末研究性质的概念验证和基准测试集,不是生产级框架;作者说别指望它取代 CoreML、MLX 或 llama.cpp。
怎么把它跑起来?在搭载 Apple Silicon 的 macOS 15+ 上构建这个 Objective-C 项目(在 M4 上测试过),然后按 training/README.md 获取预分词的 TinyStories 训练数据。
需要 CoreML、Metal 或任何外部库吗?不需要——它只用系统框架,外加运行时通过 objc_msgSend 解析的私有 ANEClient/ANECompiler API,完全不涉及 CoreML 或 Metal。
在 ANE 上训练的实际效果如何?训练能端到端跑通,但硬件利用率很低(约为峰值的 5-9%),许多逐元素运算会回退到 CPU,还有一个约 119 次编译的上限,只能靠重启进程来绕过。
它能在 Intel Mac 或旧版 macOS 上跑吗?不能,它只能在 macOS 15 及以上版本的 Apple Silicon Mac 上运行;而且专门在 M4 芯片上测试过。
这里面有哪个部分用到 GPU 吗?ANE 训练本身不使用 GPU;另有一个独立的零拷贝推理演示,由 GPU 负责 prefill,ANE 负责 decode。
这个项目测试过哪些模型?该仓库训练 Stories110M(109M 参数,MHA)和 Qwen3-0.6B(596M 参数,GQA),在 Apple M4 上分别报告 91ms/step 和 412ms/step。
作者为什么要做这个,而不是直接用 CoreML?CoreML 只把 ANE 开放给推理,所以作者用逆向工程得到的 ANEClient/ANECompiler API 绕过了这道限制,以证明训练是可行的,而且拦住大家的其实是软件而不是硬件。
INT8 量化带来了什么?INT8 W8A8 量化利用 MIL 的量化/反量化操作,把 tile 之间的 L2 SRAM 带宽减半,从而让吞吐量大约翻倍(在 M4 上为 1.88 倍)。
长期依赖它安全吗?不安全——它依赖没有官方文档的 Apple 私有 API,任何 macOS 更新都可能让它失效,而且作者把它当作持续演进的研究代码,而不是稳定的库。
Creator
maderix
Size
0.5 MB
Stars
7.3K
Updated
CommitMar 10
Age
7mo
Commits · 90 Days