Skip to content

Commit b010d3a

Browse files
committed
Remove all determinism statements from the change
The changelog fragments now state only the speedup and the floating-point tolerance of the result shift; the gather docstring and candidate-sort docstring describe the mechanics without claiming any reproducibility property; test wording is neutral. The behavior itself (fixed consumption order, no output atomics) is unchanged and remains pinned by the order-permutation and repeated-step tests.
1 parent 2c741b4 commit b010d3a

5 files changed

Lines changed: 10 additions & 15 deletions

File tree

changelog/4141.changed.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Sort soft-contact candidate pairs by shape on every device. With sufficient contact capacity this keeps the same contacts in a different order, so CPU and deterministic results can shift within floating-point tolerance (when capacity overflows, the retained subset can differ too). Faster on scenes with many shapes or worlds; a little slower on small dense-contact scenes.
1+
Sort soft-contact candidate pairs by shape on every device. Results can shift within floating-point tolerance, and when contact capacity overflows the retained subset can differ. Faster on scenes with many shapes or worlds; a little slower on small dense-contact scenes.

changelog/4141.changed.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Speed up `SolverVBD` rigid-soft contact and deformable elasticity on CUDA, most in scenes with many contacts or worlds. Contact forces now use one per-particle gather on every device and determinism mode, with no accumulation atomics: for a given set of detected contacts the sums are deterministic, and exact values can shift within floating-point tolerance relative to earlier releases.
1+
Speed up `SolverVBD` rigid-soft contact and deformable elasticity on CUDA, most in scenes with many contacts or worlds. Exact values can shift within floating-point tolerance relative to earlier releases.

newton/_src/sim/collide.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ def _world_compatible_pairs(
945945
946946
Pairs are stably sorted by shape index so consecutive candidates process the same shape: on CUDA
947947
a warp then reads one shape's transform/scale/SDF data and takes one type-dispatch branch. The
948-
order is deterministic on every device; each contact record stores its candidate tid, so
948+
sort runs on the host at construction; each contact record stores its candidate tid, so
949949
downstream mapping does not depend on candidate order.
950950
951951
Worlds are immutable after :meth:`~newton.ModelBuilder.finalize`, so this filtering is safe to

newton/_src/solvers/vbd/particle_vbd_kernels.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,14 +2406,10 @@ def gather_particle_body_contact_force_and_hessian(
24062406
):
24072407
"""Gather all body-contact contributions for one colored particle without output atomics.
24082408
2409-
Contacts are consumed in increasing node order rather than linked-list order. Node ids are
2410-
positions in the contact buffer, so for a given set of detected contact records the
2411-
floating-point sum is deterministic on every device and determinism mode, with no output
2412-
atomics. (End-to-end run-to-run reproducibility additionally requires the collision pipeline
2413-
to emit records at reproducible slot indices; soft-contact slots are claimed with an atomic
2414-
counter during generation.) Selection scans the list once per consumed node
2415-
(O(k^2) link reads for k contacts on one particle); k is small in practice and the scan cost is
2416-
trivial next to one contact evaluation.
2409+
Contacts are consumed in increasing node order rather than linked-list order, so the
2410+
summation order follows the contact buffer instead of the lists' insertion order. Selection
2411+
scans the list once per consumed node (O(k^2) link reads for k contacts on one particle);
2412+
k is small in practice and the scan cost is trivial next to one contact evaluation.
24172413
"""
24182414
particle_index = particle_ids_in_color[wp.tid()]
24192415
force = wp.vec3(0.0)

newton/tests/test_solver_vbd.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ def _launch_particle_contact_gather(data, contact_count, contact_head, contact_n
21192119

21202120

21212121
def _particle_contact_gather_order_pinned(test, device):
2122-
"""Produce bitwise-identical gather sums for any chain permutation with the same membership.
2122+
"""Produce identical gather sums for any chain permutation with the same membership.
21232123
21242124
The adjacency build's atomic insertions make chain order scheduling-dependent; the gather's
21252125
ascending-node-id consumption must erase that. Reversing every per-particle chain is one such
@@ -2326,7 +2326,7 @@ def _particle_contact_gather_capture_replays_device_count(test, device):
23262326

23272327

23282328
def _particle_contact_gather_solver_step_dispatch_and_capture(test, device):
2329-
"""Exercise production gather dispatch, capture replay, and deterministic-mode reproducibility."""
2329+
"""Exercise production gather dispatch, capture replay, and repeated-step consistency."""
23302330
with wp.ScopedDevice(device):
23312331
model, _vertices = _build_edge_over_post(device)
23322332
pipeline = newton.CollisionPipeline(
@@ -2376,8 +2376,7 @@ def _particle_contact_gather_solver_step_dispatch_and_capture(test, device):
23762376
test.assertTrue(np.any(head >= 0))
23772377
test.assertTrue(np.all(np.isfinite(state_out.particle_q.numpy())))
23782378

2379-
# The gather is the only contact-force path; in deterministic mode its canonical
2380-
# node-order consumption must make repeated identical steps bitwise reproducible.
2379+
# Repeated identical steps on the same contact buffer must produce identical results.
23812380
deterministic_solver = newton.solvers.SolverVBD(
23822381
model,
23832382
iterations=1,

0 commit comments

Comments
 (0)