Kernel: make boolean results reproducible across processes - #903
Merged
Merged
Conversation
Three places let HashMap iteration order — seeded per process — leak into geometry, so the same document tessellated differently from run to run (in-process repeats were always bit-identical, which is what made it look like anything but hash order): - sew::merge_nearby_vertices and repair::weld_boundary_vertices removed merged vertices in merge_map.keys() order. A slotmap recycles freed slots LIFO, so removal order decides which keys later vertices receive, and with them every id-based tie-break downstream. Measured on the rana-60 stator: one 378-face union came back with 4067, 4075 or 4083 triangles. - tessellate::snap_boundary_rails kept the FIRST nearest open edge from a HashMap-ordered list; a slit's two rails routinely offer exactly equidistant candidates. - tessellate::heal_t_junctions_pass built its candidates from counts.iter(); ties survived in that order into dedup_by_key. All three now iterate sorted. Verified across processes, not within one: 10/10 stator evaluations identical under env -i with the environment block padded from 37 to 370 bytes (the flip only ever showed with no debug env var set, i.e. it tracked the environment's size); before, triangle counts wandered 99 985..105 998 and the mesh fallback returned 8118.6 or 8150.6 mm3 from "the same" input. Closes #893 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Owner
Author
|
Merged current 🤖 Posted by Claude Code |
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.
Closes #893.
The same document evaluated to a different (equally valid) mesh from run to run — triangle counts wandered 99 985…105 998 on the rana-60 stator, and its mesh-fallback union returned 8118.6 mm³ closed or 8150.6 mm³ with 12 open edges. In-process repeats were always bit-identical, and the flip only ever showed when no debug env var was set, which pointed everywhere except the actual cause:
HashMapiteration order (seeded per process) leaking into geometry in three places.sew::merge_nearby_vertices,repair::weld_boundary_verticesmerge_map.keys()order; a slotmap recycles freed slots LIFO, so removal order decides which keys later vertices get, and with them every id-based tie-break downstream (one 378-face union: 4067 / 4075 / 4083 triangles)tessellate::snap_boundary_rails<) from a hash-ordered list; a slit's two rails routinely offer exactly equidistant candidatestessellate::heal_t_junctions_passcounts.iter(); ties survived in that order intodedup_by_keyAll three now iterate sorted — three small hunks, no behaviour change beyond which of two equally valid tie-break winners is chosen (now always the same one).
Verification — across processes, since in-process repeats never showed it: 10/10 stator evaluations identical (volume, triangle count, defect count) under
env -iwith the environment block padded 37→370 bytes; an instrumented run gave byte-identical FNV hashes at all 7 fallback stages across 5 processes. Whole workspace the way CI runs it (cargo nextest run --workspace --exclude vcad-desktop --profile ci): 4378 passed; the only 2 failures are the local-GPU wavefront tests in #897, which pass on CI. Workspace clippy (1.98.1) and fmt clean.Worth a look in CI: the torture-track baseline is platform-specific and these tie-breaks now resolve one fixed way, so a case could legitimately move.
🤖 Generated with Claude Code