Files
mininglamp-ai--cider/experimental/README.md
T
2026-07-13 12:34:46 +08:00

95 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ANE Split — ANE+GPU Tensor Parallelism for Prefill Acceleration
*Status: experimental research prototype. Uses private ANE APIs and is not part of Cider's stable inference path.*
Split each linear layer's GEMM along output channels: **ANE** and **GPU** computes running concurrently. This explores whether the otherwise idle Apple Neural Engine can help accelerate prefill, with minimal degradation observed in our current tests.
> **Platform:** Apple M4 (tested). M5 ANE API changes may cause failures — not yet validated.
## How It Works
```
Input x ──┬── ANE (r output channels, FP32, private API) ──┐
│ ├── concat → output
└── GPU (1 - r output channels, FP16, MLX matmul) ──┘
```
1. **SplitLinear** wraps each `nn.Linear` / `nn.QuantizedLinear`
2. In **prefill mode** (seq ≥ 192): split path with ANE+GPU concurrency
3. In **decode mode**: falls back to original `nn.Linear` on GPU (zero overhead)
4. Same-input projections (Q/K/V, Gate/Up) share input preparation via `_InputGroup`
### Automatic Layer Routing
| Layer Type | Routing | Reason |
|------------|---------|--------|
| Q, K, V, O projections | ANE+GPU split | Expand: IC → OC, ANE efficient |
| Gate, Up projections | ANE+GPU split | Expand: IC → OC, ANE efficient |
| Down projection | GPU only | Narrow: IC > 2×OC, ANE inefficient |
| Short sequences (< 192) | GPU only | Split overhead > benefit |
## Performance (Apple M4, Qwen3-VL-2B)
| seq | W8A16 GPU | SplitLinear | Speedup vs W8A16 |
|-----|----------|-----------|-------------|
| 512 | 639.9 ms | **615.9 ms** | **1.039×** |
| 1024 | 1348.6 ms | **1156.9 ms** | **1.17×** |
- Accuracy: cos ≈ 1.0, top-1 match = 100%
- 168 layers split (28 layers × 6 projections), 28 GPU-only (down_proj)
## Quick Start
```python
from split_linear import patch_model, SplitLinear
# Load any MLX VLM model
from mlx_vlm.utils import load as vlm_load
model, processor = vlm_load("path/to/model")
# Patch all linear layers (one-liner)
bridge = patch_model(model, seq=512)
# Enable split for prefill, disable for decode
SplitLinear.set_prefill(True) # prefill: ANE+GPU parallel
# ... run prefill ...
SplitLinear.set_prefill(False) # decode: original GPU path
```
## Benchmark
```bash
# Default: seq=512
python3 bench.py
# Custom seq length
python3 bench.py 1024
# Custom model path
MODEL_PATH=/path/to/model python3 bench.py 512
```
## Building the ANE Bridge
To build libane_bridge_v6.dylib from the source:
```bash
clang -shared -O2 -framework Foundation -framework CoreML \
-framework Accelerate -o libane_bridge_v6.dylib libane_bridge_v6.m
```
> Requires macOS with ANE private frameworks. Uses undocumented `_ANEClient` API.
## Limitations
- **M4 only** — M5 ANE internal changes may break the private API bridge
- **Fixed sequence length** — ANE models are compiled for a specific seq; re-patch needed for different lengths
- **FP32 on ANE** — ANE operates in FP32 (no INT8/FP16 GEMM); benefit comes from parallelism, not precision
- **Memory overhead** — ANE models consume additional system memory (~200MB for 2B model)
- **No decode benefit** — Decode is single-token, falls back to GPU (no split overhead)
- **No E2E benefit** - MLX natively employs lazy evaluation to reduce synchronization overhead. In end-to-end testing, our hybrid approach currently shows no advantage because we haven't yet implemented it with MLX's lazy evaluation.
## License
MIT