Two pre-existing multi-GPU failures in nanovdb_test_mgpu (nanovdb/nanovdb/unittest/TestMultiGPU.cu), independent of the memory-resource work. Both reproduce on a 2-GPU host and are NanoVDB-side bugs in tools/cuda/DistributedPointsToGrid.cuh, not a CCCL/CUB regression — CUB's DeviceMerge::MergePairs and the CUB_LAUNCH two-phase pattern were verified correct in isolation under the vendored CCCL 3.5.
Environment
- 2× NVIDIA RTX 6000 Ada, driver 595.71.05, CUDA 12.6 (nvcc), CCCL/CUB 3.5.0 (vendored).
- Note: NanoVDB CUDA/mgpu tests are compiled but never executed on a GPU in CI (runners are GPU-less; every CUDA job runs
ctest -E ".*cuda.*|.*mgpu.*"), so these only manifest on dev machines.
Bug 1 — TestNanoVDBMultiGPU.RadixSort (deterministic)
Sortedness checks (EXPECT_LE/EXPECT_GE) fail — the output is not globally sorted. Single-GPU (CUDA_VISIBLE_DEVICES=0) passes, isolating the fault to the 2-GPU merge. The right-device merge under-produces: the right half of the output shows inversions and many never-written slots.
Root cause: a cross-device event-ordering hazard in radixSortAsync (~L217–267). postEvents[deviceId] is reused to signal both "per-device sort done" and "mergePathKernel done", so the right-device DeviceMerge::MergePairs can launch before the peer device's sorted output is actually visible.
Bug 2 — TestNanoVDBMultiGPU.DenseLeaf_DistributedCudaPointsToGrid_UnifiedBuffer (flaky / order-dependent)
Illegal memory access (CUDA error 700). Passes in-suite, fails in isolation — order/state dependent. compute-sanitizer --tool memcheck pinpoints the real fault:
Invalid __global__ read of size 4 bytes
at nanovdb::tools::cuda::VoxelKeyFunctor<...>::operator()(...)+0xe0 in tools/cuda/PointsToGrid.cuh:562
Address 0x... is out of bounds, ~51 GB after the nearest allocation (512 bytes)
Device Frame: offsetLambdaKernel<VoxelKeyFunctor<...>>(...) in util/cuda/Util.h:260
PointsToGrid.cuh:562 is Vec3T p = points[d_indx[tid]];. The index d_indx[tid] (mIndices[tid]) is uninitialized/garbage in this configuration, so points[garbage] reads far out of bounds. The kernel is launched from the distributed serial per-tile loop at DistributedPointsToGrid.cuh:747. The error is asynchronous, so it only surfaces at the next cudaEventSynchronize (~L705) — which is why it superficially looks like a copy/sync bug there. Root cause (why mIndices is uninitialized over the per-tile index range in the dense-single-tile path) is under investigation.
Repro
cmake --build build/nanovdb --target nanovdb_test_mgpu
cd build/nanovdb/unittest
./nanovdb_test_mgpu --gtest_filter='*RadixSort*' # sortedness failures
./nanovdb_test_mgpu --gtest_filter='*DenseLeaf*' # CUDA 700 (async)
/usr/local/cuda/compute-sanitizer/compute-sanitizer --tool memcheck \
./nanovdb_test_mgpu --gtest_filter='*DenseLeaf*' # pinpoints PointsToGrid.cuh:562
Both fixes belong in NanoVDB (not upstream CCCL).
Two pre-existing multi-GPU failures in
nanovdb_test_mgpu(nanovdb/nanovdb/unittest/TestMultiGPU.cu), independent of the memory-resource work. Both reproduce on a 2-GPU host and are NanoVDB-side bugs intools/cuda/DistributedPointsToGrid.cuh, not a CCCL/CUB regression — CUB'sDeviceMerge::MergePairsand theCUB_LAUNCHtwo-phase pattern were verified correct in isolation under the vendored CCCL 3.5.Environment
ctest -E ".*cuda.*|.*mgpu.*"), so these only manifest on dev machines.Bug 1 —
TestNanoVDBMultiGPU.RadixSort(deterministic)Sortedness checks (
EXPECT_LE/EXPECT_GE) fail — the output is not globally sorted. Single-GPU (CUDA_VISIBLE_DEVICES=0) passes, isolating the fault to the 2-GPU merge. The right-device merge under-produces: the right half of the output shows inversions and many never-written slots.Root cause: a cross-device event-ordering hazard in
radixSortAsync(~L217–267).postEvents[deviceId]is reused to signal both "per-device sort done" and "mergePathKernel done", so the right-deviceDeviceMerge::MergePairscan launch before the peer device's sorted output is actually visible.Bug 2 —
TestNanoVDBMultiGPU.DenseLeaf_DistributedCudaPointsToGrid_UnifiedBuffer(flaky / order-dependent)Illegal memory access (CUDA error 700). Passes in-suite, fails in isolation — order/state dependent.
compute-sanitizer --tool memcheckpinpoints the real fault:PointsToGrid.cuh:562isVec3T p = points[d_indx[tid]];. The indexd_indx[tid](mIndices[tid]) is uninitialized/garbage in this configuration, sopoints[garbage]reads far out of bounds. The kernel is launched from the distributed serial per-tile loop atDistributedPointsToGrid.cuh:747. The error is asynchronous, so it only surfaces at the nextcudaEventSynchronize(~L705) — which is why it superficially looks like a copy/sync bug there. Root cause (whymIndicesis uninitialized over the per-tile index range in the dense-single-tile path) is under investigation.Repro
Both fixes belong in NanoVDB (not upstream CCCL).