Sort module attributes when flattening - #100
Draft
cemde wants to merge 1 commit into
Draft
Conversation
cemde
force-pushed
the
fix/76-treedef-order
branch
from
August 9, 2026 14:41
c5d78d3 to
854e696
Compare
cemde
marked this pull request as draft
August 9, 2026 14:49
BaseModule flattened on __dict__ insertion order, so two instances of the same class whose constructor assigned attributes in a different order got different treedefs: they could not be tree_mapped together and forced a jit recompile. Sort the keys, as jax does for dictionaries. Traversal order is now alphabetical rather than by assignment, so the expected sequence in test_extract_yields_one_entry_per_dynamic_param_in_ traversal_order is updated to match.
cemde
force-pushed
the
fix/76-treedef-order
branch
from
August 9, 2026 18:23
854e696 to
07fe496
Compare
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.
Bug
BaseModuleflattened on__dict__insertion order, which is the order a constructor happened to assign attributes in.Impact
Two instances of the same class built by different code paths get different treedefs:
They cannot be
tree_maped together, and passing one then the other to a jitted function forces a recompile. A module is documented as flattening "as if it were a dictionary", and jax's own dict flattening is deliberately key-order-insensitive for exactly this reason.Fix
Sort the keys in both flatten variants.
unflatten_modulerebuilds__dict__by zipping aux keys with children, so it consumes whatever order flatten emits and stays consistent automatically.Why a test changed
test_extract_yields_one_entry_per_dynamic_param_in_traversal_orderasserted thatextracted[0]wasw, the first-assigned attribute. Its docstring states the contract as "extraction has to be deterministic and skip statics"; which deterministic order is precisely what this PR changes, so the positional literals recorded incidental behaviour rather than the contract. No order normalisation of any kind could preserve them. The two expected values are swapped and the docstring now says why.Verified
A full two-moons run is bit-identical to main across per-batch energies, test accuracy and every weight elementwise.
tree_ref/tree_unrefstill restores object identity for an aliased param, and a jitted function called with awb-ordered and abw-ordered instance now traces once instead of twice. Old checkpoints still load, since keys arejtu.keystrattribute paths rather than positions.Reordering a float32
reducecan move the last bits of a sum. It does not on the tutorial, whose module attributes are already alphabetical and whose Vodes live in a list, but a constructed worst case shifts the total energy by 5e-6 relative. Inherent to any order normalisation.Closes #76