Skip to content

M16: mixed-precision training - #31

Merged
ausimian merged 2 commits into
mainfrom
m16-mixed-precision
Apr 17, 2026
Merged

M16: mixed-precision training#31
ausimian merged 2 commits into
mainfrom
m16-mixed-precision

Conversation

@ausimian

@ausimian ausimian commented Apr 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add Emily.MixedPrecision module with LossScaler struct, cast_params/2, accumulate_grad/2, loss_scale/1, scale_loss/2, unscale/2, update/2, and has_overflow?/1 — the standard bf16 activations + f32 master weights + dynamic loss scaling recipe
  • Fix Emily.Backend.wrap coerce to detect and correct all MLX buffer vs Nx metadata type mismatches (previously only handled pred→u8), unblocking bf16 grad computation
  • Add bf16 grad equivalence, mixed-precision MLP curve-matching, and bf16 MNIST convergence canary tests

Test plan

  • mix precommit — 0 failures (438 tests, 73 properties, 1 doctest)
  • test/emily/mixed_precision_test.exs — 33 unit tests covering all public API functions
  • test/emily/grad/bf16_grad_equivalence_test.exs — 8 zoo functions, Emily.Compiler vs BinaryBackend Evaluator in bf16
  • test/emily/training/bf16_mlp_curve_test.exs — 50-step mixed-precision MLP, Emily vs BinaryBackend within rtol 5e-2
  • mix test --only training_full — bf16 MNIST convergence canary (target ≥ 95.5%)

Add Emily.MixedPrecision with dynamic loss scaling (LossScaler),
cast_params/accumulate_grad for bf16/f32 conversion, and overflow
detection. Fix Backend.wrap coerce to handle all MLX/Nx type
mismatches (not just pred→u8), which surfaces when Nx.Defn.grad
promotes output metadata to f32 while the MLX buffer stays bf16.

Tests: 33 unit tests, bf16 grad equivalence (8 zoo functions),
bf16 MLP curve-matching (50 steps), bf16 MNIST canary (training_full).
- Eliminate deep_cast: express as deep_apply + Nx.as_type closure
- Extract close?/4 and flunk_trajectory/5 to TrainingHelper (was
  copy-pasted across 3 curve tests)
- Extract MNIST load/evaluate helpers to MnistHelper (was duplicated
  between f32 and bf16 test modules)
- Collapse bf16/f16 tensor generators into a single clause that
  delegates to the f32 generator + as_type
- Restore coerce fast path for {:u, 8} (avoids Native.dtype NIF
  call on the most common mismatch type)
- Remove section comments on self-describing private functions
- Single-source LossScaler default scale via @default_scale attribute
@ausimian
ausimian merged commit 1e9b702 into main Apr 17, 2026
1 check passed
@ausimian
ausimian deleted the m16-mixed-precision branch April 17, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant