Skip to content

M22: compile-time debug flags - #36

Merged
ausimian merged 1 commit into
mainfrom
m22-debug-flags
Apr 18, 2026
Merged

M22: compile-time debug flags#36
ausimian merged 1 commit into
mainfrom
m22-debug-flags

Conversation

@ausimian

Copy link
Copy Markdown
Owner

Summary

  • Adds two opt-in Application.compile_env flags — :debug_bounds_check and :debug_detect_nan_inf — that re-enable runtime assertions on hot paths GPU backends skip by default. Both default false with zero runtime cost; the gated branches are dead-code eliminated and no Emily.Backend.DebugHelpers reference reaches the compiled BEAM.
  • :debug_bounds_check covers gather, take, take_along_axis, indexed_add, indexed_put — closes the silent-NaN-from-OOB-gather class of bug that surfaced in DistilBERT-QA conformance.
  • :debug_detect_nan_inf scans matmul, fast_rms_norm, fast_layer_norm, and both fast_scaled_dot_product_attention variants so training-time numerics failures surface at the producing op.
  • Zero-cost verification test inspects :beam_disasm.file/1 output and asserts no DebugHelpers / check_bounds! / check_nan_inf! reference survives under the default-off build — guards against a future refactor accidentally unconditionalising the gate.
  • Emily's own config/test.exs keeps both prod flags false so mix test doesn't pay GPU-sync cost; fixture-only flags drive the gate→helper composition tests.
  • Closes debug: compile-time debug flags for Emily.Backend (opt-in assertions) #32.

Test plan

  • mix precommit — 421 tests, 0 failures, credo clean.
  • mix test test/emily/debug_flags_test.exs — 15 tests across four groups:
    • DebugHelpers direct-call tests (positive / negative / error-message format)
    • Production flag off — silent OOB negative control
    • Fixture module exercises the gate→helper composition
    • Zero-cost verification via :beam_disasm.file/1
  • Manual toggle: flip config/test.exs's :debug_bounds_check to true, rerun the file — zero-cost tests fail (as designed), negative-control test starts raising. Flip back, confirm green.

Two opt-in Application.compile_env flags re-enable runtime assertions
on hot paths that GPU backends skip by default. Both default false
with zero runtime cost when off — the gated branches are dead-code
eliminated by the Elixir compiler and no Emily.Backend.DebugHelpers
reference reaches the compiled BEAM.

- :debug_bounds_check — raises on OOB / negative indices in gather,
  take, take_along_axis, indexed_add, indexed_put. Closes the silent-
  NaN-from-OOB-gather class of bug that surfaced in DistilBERT-QA
  conformance (vocab-30522 tokenizer vs. tiny-random embedding).
- :debug_detect_nan_inf — scans matmul, fast_rms_norm, fast_layer_norm,
  and both fast_scaled_dot_product_attention variants for NaN/Inf so
  training-time numerics failures surface at the producing op.

The Emily.Backend.DebugHelpers module holds the assertion bodies and
is always compiled; Emily.Backend only references it from inside
`if @flag` gates, so when the flags are off the entire module is
unreachable from Emily.Backend's bytecode. A zero-cost verification
test inspects :beam_disasm.file/1 output and asserts no reference
survives under the default-off build.

Emily's own config/test.exs keeps both prod flags false so mix test
doesn't pay GPU-sync cost on every run; fixture-only flags drive the
gate→helper composition tests in test/support/debug_fixture.ex.

Standalone softmax has no Backend callback in Emily (it's Axon-composed
from exp/sum/divide); the fused SDPA softmax is covered via the two
SDPA callback paths.

Closes #32.
@ausimian
ausimian merged commit c8fc143 into main Apr 18, 2026
1 check passed
@ausimian
ausimian deleted the m22-debug-flags branch April 18, 2026 05:22
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.

debug: compile-time debug flags for Emily.Backend (opt-in assertions)

1 participant