Lucid Layer Map
ArchitectureEvery layer an op crosses: the Python API, pybind11, ops and kernels, the backend dispatcher, and the two Apple stream backends.
12 components · 4 guided chapters25 source links pinned to 2a49b45
Key facts
Dependency direction
- C++ depends one way: bindings → ops → kernel → autograd → backend → tensor → core (convention, DEVELOPMENT.md §2.2)
- tools/check_layers.py guards Python only: autograd, linalg and diffeq may not import nn or optim
H3 · Stream split
- CPU uses Accelerate only, GPU uses MLX only
- Carve-outs: linalg and FFT run on MLX's CPU stream; nonzero and unique round-trip through the CPU
H4 · No external deps
- No numpy or other third-party import on any compute path
- Only six bridge boundaries may touch the outside world
Guided chapters
- 01
Op call path
One line of user code crosses Python and the pybind11 boundary down to a C++ kernel.
- 02
CPU and GPU streams
Dispatcher routes by Device: CPU to Accelerate, GPU to MLX. The two streams never mix (H3).
- 03
Autograd recording
The forward kernel leaves itself behind as the grad_fn node and re-checks saved input versions in backward.
- 04
compile and Core ML
A Tracer hooked into OpScopeFull gathers ops into TraceGraph IR, then compiles to MPSGraph or exports to Core ML.