Skip to content

NanoVDB: two multi-GPU DistributedPointsToGrid failures (RadixSort merge sync; DenseLeaf illegal access) #2245

Description

@harrism

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions