feat(burn-cubecl): add deterministic feature for reproducible float reductions#5156
Open
guoyucode wants to merge 3 commits into
Open
feat(burn-cubecl): add deterministic feature for reproducible float reductions#5156guoyucode wants to merge 3 commits into
guoyucode wants to merge 3 commits into
Conversation
When enabled, SumStrategy / KernelReduceStrategy default to chained / Unspecified reduce instead of Autotune/OneShot, avoiding cross-cube float atomics that make multi-step training non-reproducible.
Contract tests cover SumStrategy defaults. GPU feedback probes show Chained (default with deterministic) is bit-stable while OneShot (Autotune's common pick without it) diverges across runs.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an opt-in deterministic feature to burn-cubecl to make default float reduction behavior reproducible by avoiding reduction paths that rely on cross-cube floating-point atomics (which can introduce run-to-run drift).
Changes:
- Introduce a
deterministicCargo feature forburn-cubecl. - Change
SumStrategy::default()/KernelReduceStrategy::default()to select deterministic-safe defaults when the feature is enabled. - Add unit tests intended to enforce the feature contract and probe (GPU) divergence vs reproducibility.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| crates/burn-cubecl/src/kernel/reduce/base.rs | Switch default reduction strategies under deterministic and add contract/probe tests. |
| crates/burn-cubecl/Cargo.toml | Add deterministic feature and a new dev-dependency for test support. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+107
to
+110
| // `deterministic`: chained reduce avoids cross-cube float atomics in OneShot | ||
| // shared_sum (non-associative + undefined completion order → multi-step drift). | ||
| #[cfg(feature = "deterministic")] | ||
| return Self::Chained(KernelReduceStrategy::Unspecified); |
Comment on lines
+348
to
+351
| #[test] | ||
| #[cfg(feature = "deterministic")] | ||
| fn multi_step_float_sum_is_reproducible_with_deterministic() { | ||
| assert!( |
Comment on lines
+368
to
+371
| #[test] | ||
| #[cfg(not(feature = "deterministic"))] | ||
| fn multi_step_float_sum_diverges_without_deterministic() { | ||
| // Upstream default is Autotune, which frequently selects OneShot shared_sum |
Comment on lines
+98
to
+101
| [dev-dependencies] | ||
| # WgpuRuntime for GPU sum A/B tests in `kernel/reduce/base` (enables `cubecl/wgpu` via unification). | ||
| burn-wgpu = { workspace = true } | ||
|
|
Contributor
There was a problem hiding this comment.
These tests should probably be in burn-wgpu directly (mod multi_step_float_sum)
Allow enabling burn-cubecl/deterministic via burn/deterministic for bit-reproducible multi-step GPU training.
Charles23R
requested changes
Jul 16, 2026
Comment on lines
+98
to
+101
| [dev-dependencies] | ||
| # WgpuRuntime for GPU sum A/B tests in `kernel/reduce/base` (enables `cubecl/wgpu` via unification). | ||
| burn-wgpu = { workspace = true } | ||
|
|
Comment on lines
+98
to
+101
| [dev-dependencies] | ||
| # WgpuRuntime for GPU sum A/B tests in `kernel/reduce/base` (enables `cubecl/wgpu` via unification). | ||
| burn-wgpu = { workspace = true } | ||
|
|
Contributor
There was a problem hiding this comment.
These tests should probably be in burn-wgpu directly (mod multi_step_float_sum)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Multi-step GPU training can produce different weights across identical runs even when application-level seeds, data order, and initialization are fixed. The root cause is in CubeCL float reduction:
Tensor::mean()/float_sumuseSumStrategy::default(), which with the defaultautotunefeature resolves toSumStrategy::Autotune. Autotune frequently selectsOneShot, whoseshared_sumkernel finishes with a cross-cube floatatomicAdd(fetch_addon the output). Floating-point addition is not associative, and atomic completion order is undefined, so the summed value (and therefore gradients / optimizer updates) can drift from run to run. After many Adam steps the drift is large enough to change early-stopping and final checkpoints.This PR adds an opt-in
deterministicfeature onburn-cubeclthat does not change default behavior:deterministic:SumStrategy::default()→Chained(Unspecified)andKernelReduceStrategy::default()→Unspecified(tree/chained reduce, no cross-cube float atomics).deterministic: keep the existing Autotune / OneShot defaults.Users who need bit-reproducible GPU training can enable the feature through the usual Cargo feature graph (e.g. via
burn-wgpu/burnonce forwarded, or by depending onburn-cubeclwithfeatures = [deterministic]).Tests
Unit tests live next to the change in
crates/burn-cubecl/src/kernel/reduce/base.rs:--features deterministicSumStrategy::default()is bit-stable across two runsdeterministic)OneShot(8)(Autotune’s common pick) diverges across runs(GPU / Wgpu required for the multi-step probes; contract tests for
Defaultare CPU-only.)Test plan
deterministicdeterministic(Δ ≈ 0) and fails/asserts divergence without it on OneShotdeterministic) still builds and behaves as beforedeterministicfromburn-wgpu/burnfor a single user-facing switch