Make CUDA floating-point prefix sums deterministic - #211
Conversation
|
Hi @matla91, I do not wish to avoid the decoupled loopback algorithm, which remains the optimal way to do these kinds of reductions on NVIDIA GPUs. Probably the better fix would be something that avoids FP nondeterminism while still keeping the loopback structure. |
3048dcc to
16364ba
Compare
16364ba to
6bf7e8c
Compare
|
Hi @wjakob, Thanks for the feedback. I reworked the patch to keep the decoupled look-back structure. The revised implementation uses fixed 32-chunk anchor intervals for The original DLB path is unchanged for the other operations and types. I also replaced the previous regression with a test that runs both Float32 and Float64 scans 20 times on the original 164,738-element reproducer. The test fails with the original DLB kernel and passes with the revised one. Validation on my side:
I force-pushed the revised commit. |
6bf7e8c to
a5c2594
Compare
Keep the existing decoupled look-back prefix scan while making Float32 and Float64 addition deterministic. Use fixed warp-sized anchor intervals for floating-point additions so that the reduction association order no longer depends on whether predecessors are observed in partial or inclusive states. Other reduction operations and data types retain the existing decoupled look-back path. Add a CUDA regression test exercising repeated Float32 and Float64 prefix sums.
Summary
Float32/Float64addition; other reductions and types keep the existing implementation.Float32andFloat64.Root cause
The CUDA prefix reduction uses decoupled look-back. For floating-point addition, a block can observe predecessors in different
PARTIAL/INCLUSIVEstates depending on GPU scheduling. That changes the association order of the chunk-prefix additions and can therefore change the resulting bit pattern across otherwise identical runs.This propagated to Mitsuba mesh area CDF construction and caused repeated sampling of an identical mesh with identical random samples to return different positions and PDFs. The original investigation is documented in mitsuba-renderer/mitsuba3#1938.
Implementation
The revised patch keeps the single-pass decoupled look-back kernel.
For
Float32andFloat64addition, look-back is divided into fixed warp-sized anchor intervals. Each lane examines a fixed predecessor relative to the current chunk, waits until the interval anchor has reached the inclusive state, and then performs a fixed-order warp reduction through that anchor. Only fixed anchor chunks publish an inclusive prefix for the next interval.This makes the floating-point association order independent of whether intermediate predecessors happen to be observed as partial or inclusive due to scheduling.
The original decoupled look-back path is retained unchanged for other reduction operations and data types.
Validation
Float32andFloat64.Float32andFloat64, forward/reverse, inclusive/exclusive, full-array and segmented scans, including inputs spanning more than one 32-chunk anchor interval.test_reductions -c: 15/15 passed (43 skipped).graphvizhas a pre-existing reference-output mismatch and produces byte-identical failing output with the baseline and patched libraries.ptxasresource usage for the modified kernels:Float32: 19 registers, 0 spills.Float64: 22 registers, 0 spills.Microbenchmark
RTX 2060, CUDA kernel execution + synchronization, median of repeated runs:
The generated CUDA kernel artifacts were rebuilt with CUDA 12.2.140.