Skip to content

feat: f16/bf16 precision mode for the OpenXLA emitter (#449)#553

Merged
inureyes merged 1 commit into
mainfrom
feat/514-xla-f16-precision
Jul 1, 2026
Merged

feat: f16/bf16 precision mode for the OpenXLA emitter (#449)#553
inureyes merged 1 commit into
mainfrom
feat/514-xla-f16-precision

Conversation

@inureyes

@inureyes inureyes commented Jul 1, 2026

Copy link
Copy Markdown
Member

Closes #514. Part of #513.

What

A Precision on the OpenXLA StableHLO emitter's Builder that demotes the f32 inputs of every dot_general (matmul) to f16/bf16 while keeping the f32 accumulate and output. Only the matmuls change; the sensitive elementwise ops (norm, softmax, RoPE) stay f32. Authored in the graph, so it is portable to every IREE target (CPU, CUDA, Metal, future NPUs), matching --iree-global-opt-demote-contraction-inputs-type=f16.

Selected by MLXCEL_XLA_PRECISION (f16 | bf16, default f32). The emitted MLIR differs, so compile_one's content-hash vmfb cache keys each precision separately with no extra plumbing.

Changes

  • emitter/builder.rs: Precision enum + precision_from_env(); Builder carries it (default F32, with_precision()); dot_general converts f32 operands to the narrow type (f32 output) when set. Unit tests for the f16/bf16 demotion.
  • emitter/model.rs: the four emit_* entry points read precision_from_env().
  • mlxcel-xla/README.md: a Precision section.

Design notes

  • Targeted, not blanket. A program-wide --iree-input-demote-f32-to-f16 was measured slower (f16 norm/softmax/accumulation backfires), so only the contraction inputs are demoted.
  • Weights stay f32-resident and are demoted in the graph (no FFI change). Keeping the resident weights in the narrow type (a memory-bandwidth win needing the f16 weight FFI) lands with the quantized-weight path (feat: int8 weight quantization with quantized matmul on the OpenXLA path (#449) #516), where it matters more; on Metal the decode is compute-bound here, so resident-f16's marginal benefit is a future-NPU concern.

Validation (M1 Ultra, Llama-3.2-1B-Instruct, greedy)

  • MLXCEL_XLA_PRECISION=f16 on Metal: 2.89 tok/s vs 1.53 (f32) = ~1.9x, output token-exact with f32.
  • The same graph change speeds up the CPU (local-task) path too.
  • The F32 default is byte-identical to before: the emitter byte-exact regression test (from_json_reproduces_bundled_assets_byte_for_byte) still passes. 46/46 mlxcel-xla unit tests green; cargo fmt --check clean; emitter clippy clean.
  • Default / non-macOS builds unaffected (change is in the xla-backend-only crate; the F32 path is a no-op passthrough).

Note on performance

This is a transferable, correctness-first lever, not a path to MLX parity. XLA-on-Metal remains a dev/parity path (the remaining gap is IREE metal-spirv kernel codegen, out of scope). The value is that this one graph change benefits every IREE target, which is the entry ticket for low-precision-native NPUs.

Add a Precision to the StableHLO emitter's Builder that demotes the f32 inputs of every dot_general (matmul) to f16/bf16 while keeping the f32 accumulate and output, so only the matmuls change and norm/softmax/RoPE stay f32. Authored in the graph so it is portable to every IREE target (CPU, CUDA, Metal, future NPUs), matching --iree-global-opt-demote-contraction-inputs-type=f16. Selected by MLXCEL_XLA_PRECISION (f16|bf16, default f32); the emitted MLIR differs, so the vmfb content-hash cache keys each precision separately.

A blanket program-wide f32 to f16 is deliberately not done: it regressed norm/softmax/accumulation and was slower. Weights stay f32-resident and are demoted in the graph (no FFI change); keeping the resident weights in the narrow type (a memory-bandwidth win that needs the f16 weight FFI) lands with the quantized-weight path, where it matters more.

Validated on an M1 Ultra (Llama-3.2-1B-Instruct, greedy): f16 is ~1.9x the f32 tok/s (2.89 vs 1.53) and token-exact with it; the same graph change also speeds up the CPU path. The F32 default is byte-identical to before (the emitter byte-exact regression test still passes). New builder unit tests cover the f16/bf16 demotion.
@inureyes inureyes added type:enhancement New features, capabilities, or significant additions area:inference Generation, sampling, decoding (incl. speculative, DRY) labels Jul 1, 2026
@inureyes
inureyes merged commit 8fe663f into main Jul 1, 2026
5 checks passed
@inureyes
inureyes deleted the feat/514-xla-f16-precision branch July 1, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:inference Generation, sampling, decoding (incl. speculative, DRY) type:enhancement New features, capabilities, or significant additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: f16/bf16 precision mode for the OpenXLA emitter and resident weights (#449)

1 participant