Skip to content

Autocast (scope-based prototype) — mixed precision - #2702

Draft
CarloLucibello wants to merge 1 commit into
masterfrom
cl/autocast
Draft

Autocast (scope-based prototype) — mixed precision#2702
CarloLucibello wants to merge 1 commit into
masterfrom
cl/autocast

Conversation

@CarloLucibello

Copy link
Copy Markdown
Member

Draft — kept for comparison, not intended to merge.

Scope-based prototype of Flux.autocast (PyTorch-torch.autocast-style mixed precision). A companion wrapper-based implementation is being developed on a separate branch; this PR preserves the scope-based approach so the two can be compared (ergonomics, inference, performance).

Approach

Affected layers consult an ambient ScopedValue at forward time via a per-layer dispatch barrier. The whole mechanism is compiled out until the first autocast call: a one-time world-age flip of autocast_active() from false to true. So:

  • Code that never uses autocast keeps exact inferred return types and zero overhead.
  • After the first use, forward passes of the affected layers infer as the small concrete union of the Float32/Float16/BFloat16 paths (union-split by the compiler).

Parameters stay Float32 ("master weights"); gradients come back Float32, so the usual optimiser setup is unchanged. Normalization layers and losses compute in Float32.

Also

  • Splits the precision casts: f16/bf16 are full casts (PyTorch model.half()/.bfloat16()); new f16mix/bf16mix keep BatchNorm/InstanceNorm/GroupNorm statistics + affine parameters in Float32.
  • autocast=T keyword added to gradient/withgradient/train!.

Known limitations

  • After the flip, active-scope forward passes are a small union rather than a single concrete type (the motivation for the wrapper alternative).
  • BFloat16 autocast under AutoEnzyme is blocked upstream: EnzymeAD/Enzyme.jl#3430.

🤖 Generated with Claude Code

…ispatch barrier

Draft/comparison implementation of Flux.autocast. Layers consult an ambient
ScopedValue at forward time through a per-layer dispatch barrier; the machinery
is compiled out until the first `autocast` call (a one-time world-age flip of
`autocast_active()`), so code that never uses autocast keeps exact inference and
zero overhead. Once enabled, forward passes of the affected layers infer as the
small union of the Float32/Float16/BFloat16 paths.

Also splits the precision casts: f16/bf16 are full casts (like PyTorch
model.half()); f16mix/bf16mix keep BatchNorm/InstanceNorm/GroupNorm statistics
and affine parameters in Float32.

Known: after the flip, active-scope forward passes are a small union rather than
a single concrete type; bf16 + AutoEnzyme is blocked upstream (EnzymeAD/Enzyme.jl#3430).
This branch is kept for comparison against a wrapper-based implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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