Files
ANE/gen_mil_m1.py
zeekay d861b8959b Add universal ANE runtime (M1→M4+), benchmarks, and MLX training demo
- ane_universal.h: Auto-detecting runtime that selects InMem (M4+) or
  CoreML fallback (M1-M3) based on hardware capability probing
- ane_probe_m1.m: Deep diagnostic found all 74 ANE classes present on M1
  but _ANECompiler binary rejects all MIL programs (40+ format combos)
- ane_m1_fix.m: Systematic MIL format fuzzer (program versions 1.0-1.3,
  opsets ios15-ios18, weight offsets, old/new syntax) — all fail on M1
- ane_coreml_bridge.m: CoreML ANE bridge showing 2.44x speedup at 256x256
- benchmark_apple_silicon.py: MLX vs MPS vs CoreML comparison on M1 Max
  - MLX: 6.72 TFLOPS peak (fp16), 62ms/step training
  - MPS: 4.12 TFLOPS peak, 84ms/step training
  - ANE via CoreML: ~1x (dispatch overhead negates hardware advantage)
- demo_mlx_training.py: Working 4-layer transformer training, 4688 tok/s
- Updated README with M1-M4 compatibility matrix and integration points
- Added .gitignore for compiled binaries and .venv
2026-03-03 06:23:44 -08:00

60 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""Generate a minimal CoreML model and extract the MIL text that M1 ANE accepts."""
import os
import coremltools as ct
import numpy as np
from coremltools.converters.mil import Builder as mb
print(f"coremltools: {ct.__version__}")
configs = [
(64, 64, 16, "small"),
(256, 256, 64, "medium"),
]
for CH_IN, CH_OUT, SEQ, label in configs:
print(f"\n{'='*60}")
print(f"Config: {label} — conv {CH_IN}→{CH_OUT}, seq={SEQ}")
@mb.program(input_specs=[mb.TensorSpec(shape=(1, CH_IN, 1, SEQ))])
def prog(x):
W = mb.const(val=np.random.randn(CH_OUT, CH_IN, 1, 1).astype(np.float16), name="W")
x_fp16 = mb.cast(x=x, dtype="fp16", name="x_fp16")
y = mb.conv(x=x_fp16, weight=W, strides=[1, 1], pad_type="valid", name="out")
return y
model = ct.convert(
prog,
compute_units=ct.ComputeUnit.CPU_AND_NE,
minimum_deployment_target=ct.target.macOS15,
convert_to="mlprogram",
)
pkg_path = f"/tmp/ane_m1_{label}.mlpackage"
model.save(pkg_path)
print(f"Saved: {pkg_path}")
# Walk the package and dump text files
for root, dirs, files in os.walk(pkg_path):
for f in sorted(files):
fp = os.path.join(root, f)
sz = os.path.getsize(fp)
rel = os.path.relpath(fp, pkg_path)
if f.endswith(('.mil', '.json', '.txt')):
print(f"\n--- {rel} ({sz} bytes) ---")
with open(fp) as fh:
print(fh.read()[:3000])
elif f.endswith('.bin'):
print(f"Binary: {rel} ({sz} bytes)")
elif f.endswith('.mlmodel') or f.endswith('.plist'):
print(f"\n--- {rel} ({sz} bytes) ---")
try:
with open(fp) as fh:
print(fh.read()[:1000])
except:
print(f" (binary plist)")
else:
print(f"File: {rel} ({sz} bytes)")
print("\nDone. Use the extracted MIL text to fix the Objective-C ANE runtime.")