metalworkingGitHub
/machine/neural-accelerators

Neural Accelerators

The M5 generation adds a dedicated matrix unit to every GPU core: the neural accelerators (NAX in MLX's source), reached through Metal 4 tensor ops rather than simdgroup_matrix.

CUDA equivalent: the Tensor Core, finally for real. Earlier pages tell the pre-M5 story on purpose: simdgroup_matrix executes on the regular FP32 pipes, and the reverse-engineered Rigel work confirmed no dedicated matrix datapath as late as M4. On M5 that changed. Apple's own numbers for MLX on M5: ~3.97× time-to-first-token and 1.19-1.27× decode over M4, with the prefill gain landing exactly where a matrix unit should land (compute-bound territory; decode stays bandwidth-bound, so it moves with the memory spec instead).

What a CUDA person should map over, and what not to:

  • Fragment shape moves from 8×8 to 16×16. MLX's NAX steel is built on a 16×16 fragment held across the 32 threads:
struct BaseNAXFrag {
  STEEL_CONST short kFragRows = 16;
  STEEL_CONST short kFragCols = 16;

  STEEL_CONST short kElemsPerFrag = (kFragRows * kFragCols) / 32;

MLX steel/gemm/nax.h:27-31, which includes <MetalPerformancePrimitives/MetalPerformancePrimitives.h> at the top of the file: the new hardware arrives through a library, not new intrinsics.

Ecosystem status, honestly: MLX ships a parallel steel fork for it (gemm/nax.h, attn/nax.h, quantized_nax, fp_quantized_nax); llama.cpp has a tensor-API matmul path; and the tuning is young. Recent MLX work is disproportionately NAX-shaped (qmv batch limits raised for M5-class GPUs, NVFP4 QMV optimization, per-expert tile picks in gather_qmm_rhs_nax), which is what a fast-moving fast path looks like. simdgroup_matrix remains the portable primitive and the one most shipped kernels still use; this page is why the glossary keeps teaching both.