Tool

Run transformer inference 4.76x faster on Apple Silicon Neural Engine

Espresso compiles transformer inference straight to Apple's Neural Engine via private APIs, running 4.76x faster than CoreML on Apple Silicon.

Works with coremlswift

91
Spark score
out of 100
Updated 18 days ago
Version public-non-echo-exac

Add to Favorites

Why it matters

Accelerate transformer model inference on Apple Silicon by compiling MIL programs directly to the Neural Engine through reverse-engineered private APIs, bypassing CoreML overhead for production-grade speed improvements in on-device AI applications.

Outcomes

What it gets done

01

Compile transformer models directly to ANE silicon with zero-copy IOSurface buffers

02

Fuse multi-layer transformer kernels into 2 ANE dispatches instead of 6

03

Generate tokens at 1.08 ms/token with verified two-token decode steps

04

Train models on ANE with forward and backward passes plus gradient accumulation

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/christopherkarani-espresso | bash

Overview

Espresso

Espresso compiles MIL programs directly to Apple's Neural Engine via reverse-engineered private APIs, bypassing CoreML for a 4.76x faster decode (1.08ms/token vs 5.09ms/token) using fused multi-layer kernels and zero-copy IOSurface I/O. It also supports full ANE training. Use it on Apple Silicon (M1+, macOS 15+) for high-throughput on-device inference or training in internal tools, research, or enterprise apps; it relies on private APIs so it cannot ship on the App Store.

What it does

Espresso compiles MIL (Model Intermediate Language) programs straight to Apple Neural Engine (ANE) silicon through reverse-engineered private APIs (_ANEClient, _ANEInMemoryModel), bypassing CoreML entirely. There is no per-token recompilation: the decode loop compiles once and reuses the program across all steps, with the KV cache living directly in IOSurface buffers instead of being marshaled through CoreML, and each step producing two exact tokens with verified parity. Fused triplet kernels process 3 transformer layers per ANE dispatch, so a 6-layer model runs in 2 dispatches instead of 6.

On a 6-layer reference model (dim=768, 12 heads, 32k vocab, seqLen=256, M3 Max, macOS 15), Espresso decodes at 1.08 ms/token (926 tok/s) versus CoreML's .cpuAndNeuralEngine path at 5.09 ms/token (196 tok/s) - a 4.76x speedup - and roughly 11x faster than llama.cpp's Metal GPU path, which has no ANE backend at all. Beyond inference, Espresso supports full training on the ANE: forward and backward passes with gradient accumulation and Adam. The whole project is pure Swift 6.2 with ~Copyable move-only tensors, strict concurrency, typed throws, and zero external dependencies - only Apple system frameworks.

Espresso also ships an ESP model platform around portable .esp bundles: .esp is the canonical portable model bundle, .espc is a derived compiled-cache layer, espc packs native model directories into .esp, and esprun inspects, resolves, and runs bundle artifacts.

When to use - and when NOT to

Use Espresso when you're building on Apple Silicon (M1 or later, macOS 15+) and want transformer inference or training to run directly on the Neural Engine at meaningfully higher throughput than CoreML's standard ANE path, or when you're researching or building internal tools, sideloaded apps, or enterprise-distributed software that can rely on private Apple APIs. It's a fit for anyone who wants zero-copy IOSurface I/O, fused multi-layer kernel dispatch, and a Swift Package Manager-integrable ANE runtime.

Do not use it in anything destined for the App Store: apps using the private _ANEClient and _ANEInMemoryModel APIs will be rejected. It also has no support for Intel Macs (no Neural Engine) and only conditional, entitlement-gated support on iOS/tvOS (not App Store safe there either). The published benchmarks are run on a local artifact family built by this repo, not a pretrained production model, and results are explicitly hardware- and OS-dependent since the whole approach relies on undocumented, reverse-engineered private APIs.

Inputs and outputs

Quick start clones the repo and runs a bootstrap script that builds, downloads demo weights, and launches a TUI:

git clone https://github.com/christopherkarani/Espresso.git
cd Espresso
./espresso

Other CLI entry points include ./espresso "Hello" (generate text), ./espresso doctor (check host readiness), ./espresso compare --no-power "Hello" (side-by-side vs CoreML), ./espresso install (install to ~/.local/bin), swift run espresso-bench --ane-only --inference --layers 6 (benchmarking), and the espc/esprun tools for packing and running .esp model bundles.

For library integration, add the package via Swift Package Manager and compile a kernel directly:

import ANERuntime

let kernel = try ANEKernel(milText: myMIL, weights: blobs, inputSizes: [input], outputSizes: [output])
try kernel.eval()
let result = kernel.outputSurface(at: 0)

Output is a zero-copy IOSurface-backed result read directly off the Neural Engine, plus, for benchmarking, machine-readable results written to artifacts/benchmarks/.

Integrations

Espresso integrates as a Swift Package Manager dependency, exposing the ANERuntime and ANETypes products for direct use in a Swift project. Internally it's layered as ANEInterop (a dlopen bridge to the private ANE APIs with NEON-vectorized I/O), ANETypes (~Copyable tensors and IOSurface I/O), MILGenerator (28+ kernel variants for forward, backward, decode, and fused kernels), CPUOps (RMSNorm, RoPE, embedding, softmax, and Adam via Accelerate/vDSP), and ANERuntime (MIL-to-ANE-E5-binary compilation and IOSurface buffer management), with Espresso itself providing transformer layers, generation, and the training loop, plus EspressoTrain and EspressoBench CLIs. Testing integrates swift test for unit tests plus opt-in hardware and cross-validation test suites gated by ANE_HARDWARE_TESTS=1 and OBJC_CROSS_VALIDATION=1.

Who it's for

Swift developers and ML engineers building on-device transformer inference or training for Apple Silicon who need throughput beyond CoreML's standard ANE path and are comfortable relying on private, reverse-engineered Apple APIs outside the App Store - internal tools, research, sideloaded apps, or enterprise distribution. It is licensed under MIT.

Source README

Espresso

Direct Neural Engine inference for transformers on Apple Silicon.

CI ANE Matrix Swift 6.2 License: MIT macOS 15+ Latest Release


Espresso compiles MIL programs straight to ANE silicon through reverse-engineered private APIs (_ANEClient, _ANEInMemoryModel). No CoreML in the hot path. No per-token recompilation. IOSurface buffers and fused multi-layer kernels for Apple Silicon.

  • Direct ANE path - private-API compile once, reuse across decode steps
  • Fused multi-layer kernels - fewer ANE dispatches per token
  • Zero-copy I/O - NEON-vectorized surface reads, vDSP/Metal where useful
  • Pure Swift 6.2 core - ~Copyable move-only tensors, strict concurrency, typed throws
  • Zero required third-party packages - clean clone resolves and builds on macOS 15+

Espresso generating tokens on ANE

Product journeys

Pick one path. Everything else is optional or research.

1. Try it (demo)

git clone https://github.com/christopherkarani/Espresso.git
cd Espresso
./espresso          # builds, downloads demo weights, launches TUI
./espresso doctor   # host readiness check

2. Serve a model (.esp bundles)

Portable model bundles are the retained serving path:

# Pack a prepared native model directory into a portable bundle
swift run espc pack-native /path/to/model /tmp/model.esp --overwrite

# Inspect / run
swift run esprun inspect /tmp/model.esp
swift run esprun generate /tmp/model.esp "Hello" 32

# Same bundle boundary via the generate CLI
swift run espresso-generate generate --bundle /tmp/model.esp --max-tokens 32 "Hello"
Artifact Role
.esp Canonical portable model bundle
.espc Derived compiled-cache layer (host-local)
espc Pack native model dirs into .esp
esprun Inspect, resolve, generate from bundles
espresso-generate --bundle Full generate/benchmark CLI on the same boundary

3. Embed the library (ANEKernel)

// Package.swift
.package(url: "https://github.com/christopherkarani/Espresso.git", from: "1.0.0")

import ANERuntime

let kernel = try ANEKernel(
    milText: myMIL,
    weights: blobs,
    inputSizes: [input],
    outputSizes: [output]
)
try kernel.eval()                         // runs on Neural Engine
let result = kernel.outputSurface(at: 0)  // zero-copy read

For end-to-end text generation from prepared weights, use RealModelInference or a .esp bundle rather than hand-writing MIL.

Optional tooling (bench, install, training)
./espresso install                            # shim → ~/.local/bin
./espresso compare --no-power "Hello"         # side-by-side vs CoreML (demo weights)
swift run espresso-bench --ane-only --inference --layers 6
swift run espresso-train                      # experimental ANE training loop

Rejected experiment configs and distillation scripts live under research/ and are not product entry points.

Benchmark

Numbers below match the checked-in machine-readable results in
benchmarks/results/latest.json
(M3 Max, macOS 15.0, Espresso 1.1.0).

Espresso vs CoreML (local 6-layer Stories artifact)

Backend ms/token tok/s Notes
Espresso ANE (recurrent fused, 6-layer) 1.93 519 Fused 3-layer recurrent decode + ANE classifier
Espresso ANE (direct transformer, 6-layer) 6.56 153 Same model without recurrent fusion
CoreML .cpuAndNeuralEngine 6.58 152 Apple's standard ANE path
Espresso speedup vs CoreML 3.41× fused recurrent path

All Espresso / CoreML numbers: 6-layer local artifact · dim=768 · 12 heads · 32k vocab · seqLen=256 · M3 Max · macOS 15.
This is a research / demo artifact family, not a pretrained production model.

What these numbers are not

  • Not a claim about full GPT-2 117M or llama.cpp Metal on the same workload
  • Not every serving path: retained exact hybrid .esp Stories runs can land lower in wall-clock tok/s after compile and full decode accounting
  • Not trunk-only or partial-pipeline peaks from blog posts - only figures backed by latest.json (or a PR artifact from the reproduce script) are project claims
Reproduce Espresso benchmarks
RESULTS_DIR=results/$(date +%Y%m%d-%H%M%S) \
REPEATS=5 WARMUP=3 ITERATIONS=20 \
./scripts/reproduce_local_real_artifact_claim.sh

Machine-readable output lands in artifacts/benchmarks/ and is kept out of git.
Update benchmarks/results/latest.json only when you intentionally refresh the public table.
CI fails if the README table drifts from latest.json.

Platform Compatibility

SoC Neural Engine Tested Notes
M1 / M1 Pro / M1 Max / M1 Ultra 16-core ANE Full feature set
M2 / M2 Pro / M2 Max / M2 Ultra 16-core ANE Full feature set
M3 / M3 Pro / M3 Max 18-core ANE Reference hardware (M3 Max)
M4 / M4 Pro / M4 Max 38-core ANE Faster compile cache warm-up
Intel Mac - No Neural Engine
Apple A-series (iOS) ⚠️ Requires entitlement; not App Store safe

macOS 15+ required. iOS / tvOS not supported out of the box (private API entitlements differ per platform).

How It Works

                    ┌─────────────────────┐
                    │   MIL Program Text   │  Generated per-kernel
                    └──────────┬──────────┘
                               ▼
                    ┌─────────────────────┐
                    │  _ANEClient compile  │  Private API (dlopen)
                    └──────────┬──────────┘
                               ▼
                    ┌─────────────────────┐
                    │    ANE E5 Binary     │  Cached by system
                    └──────────┬──────────┘
                               ▼
              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
     ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
     │  IOSurface   │ │  IOSurface   │ │  IOSurface   │
     │   (input)    │ │  (weights)   │ │  (output)    │
     └──────┬───────┘ └──────────────┘ └──────┬───────┘
            │          ANE Hardware            │
            └──────────────eval───────────────┘

The decode loop compiles once and reuses the program across all steps. KV cache lives in IOSurface buffers - not marshaled through CoreML.

Architecture

ANEInterop (ObjC/C — private API bridge)
  └── ANETypes (~Copyable value types, IOSurface I/O)
          ├── MILGenerator (kernel variants)
          │       └── ANERuntime (compile, eval, surface management)
          │               └── Espresso / RealModelInference (serving, decode)
          │                       ├── espresso-generate / esprun (CLI)
          │                       └── ESPBundle (portable .esp)
          └── CPUOps (Accelerate/vDSP kernels)
Module What it does
ANEInterop dlopen bridge to _ANEClient and _ANEInMemoryModel. NEON-vectorized I/O.
ANETypes ~Copyable tensors, SurfaceIO, weight serialization, model config.
MILGenerator Generates MIL text for forward, backward, decode, and fused kernels.
CPUOps RMSNorm, RoPE, embedding, softmax, Adam via Accelerate/vDSP.
ANERuntime Compiles MIL to ANE E5 binaries. Manages IOSurface buffers and compile budget.
Espresso Generation harnesses, decode, training experiments.
RealModelInference Hybrid serving path used by espresso-generate / .esp runtime.
ESPBundle / ESPRuntime Portable .esp bundles and runtime resolution.

SPM Integration

// Package.swift
dependencies: [
    .package(url: "https://github.com/christopherkarani/Espresso.git", from: "1.0.0")
],
targets: [
    .target(name: "MyApp", dependencies: [
        .product(name: "ANERuntime", package: "Espresso"),
        .product(name: "ANETypes",   package: "Espresso"),
    ])
]
import ANERuntime
import ANETypes

let kernel = try ANEKernel(
    milText: milText,
    weights: weightBlobs,
    inputSizes: [inputByteSize],
    outputSizes: [outputByteSize]
)
try kernel.eval()
let output = try kernel.outputSurface(at: 0)

Dependencies

Zero third-party Swift packages. The package graph depends only on Apple system frameworks (Foundation, Accelerate, IOSurface, Metal, CoreML). A clean clone of this repo alone must resolve and build.

Requirements

Minimum
Hardware Apple Silicon (M1+) with Neural Engine
macOS 15.0+
Swift 6.0+ (6.2 recommended)
Dependencies None required - Apple system frameworks only

Testing

swift test                                                    # unit tests (no ANE needed)
ANE_HARDWARE_TESTS=1 swift test --filter "ANERuntimeTests|EspressoTests"  # hardware tests
OBJC_CROSS_VALIDATION=1 ANE_HARDWARE_TESTS=1 swift test --filter CrossValidationTests  # parity

CI runs non-hardware unit tests including ESP bundle/runtime and RealModelInference unit suites, asserts a zero-dependency default graph, and checks README claim numbers against latest.json. Hardware ANE tests run on self-hosted matrix jobs.

Research vs product

Path Location
Retained product surface Sources/, ./espresso, espc / esprun / espresso-generate, public docs
Quarantined experiments research/ - rejected draft/student/future-head configs and tooling

Do not treat research/ numbers or flags as supported product behavior.

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.