Skip to content

VBM select-based inverse-map decode - #2258

Open
swahtz wants to merge 3 commits into
AcademySoftwareFoundation:masterfrom
swahtz:nanovdb-vbm-select-decode
Open

VBM select-based inverse-map decode#2258
swahtz wants to merge 3 commits into
AcademySoftwareFoundation:masterfrom
swahtz:nanovdb-vbm-select-decode

Conversation

@swahtz

@swahtz swahtz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR replaces the method in inverse-map decode in the NanoVDB VoxelBlockManager (tools/cuda/VoxelBlockManager.cuh) with an output-centric select. decodeInverseMaps previously had every thread in the block sweep all 512 voxel slots of every leaf overlapping the block — O(nLeaves × 512) work per block. It now runs one thread per output slot: each slot ranks itself into its leaf with a jumpMap popcount, then locates its voxel via the leaf's 9-bit mPrefixSum plus an in-word __fns bit select — O(1) per slot.

The public signature is unchanged and the decoded maps are byte-identical, so every downstream stencil consumer inherits the speedup for free. Benchmarked A/B on an RTX PRO 6000 (sm_120; 50 iters / 15 warmup).

What changed

The decode is, in effect, a rank + select over the VBM's bit-vectors:

  • rank into the block's jumpMap (a popcount of leaf-start bits at or before the slot) selects which leaf owns the slot;
  • select into that leaf's 512-bit value mask — guided by the precomputed 9-bit prefix-sum directory to find the containing 64-bit word, then an in-word __fns — recovers the voxel offset.

This removes the old sweep's data-dependent inner branch (if (index ∈ block)) and its per-leaf full scan, and makes the decode's work independent of leaf sparsity.

A/B — decode (dragon, median; BlockWidth = 2^log2width)

width base (sweep) this PR (select) speedup
64 0.372 ms 0.171 ms 2.17×
128 0.288 ms 0.146 ms 1.97×
256 0.262 ms 0.162 ms 1.62×
512 0.281 ms 0.198 ms 1.42×

Decode is the shared front-end for all stencil consumers, so whole-consumer times improve too (dragon): 7-pt Laplacian −10…−15%, 27-tap box / 19-tap WENO −4…−9%, with no consumer regressing.

Validation

  • Byte-identical decode maps: the VBM decode / box / lap / weno A/B comparisons all passed unchanged at widths 64/128/256/512 across dragon/emu/crawler/wdas_cloud.
  • Final partial blocks and the beyond-last-active-voxel sentinels verified at all four widths.

swahtz added 3 commits July 23, 2026 04:38
Replace the O(nLeaves x 512) cooperative sweep in decodeInverseMaps with an
O(1)-per-slot select: one thread per output slot ranks itself into its leaf via
the jumpMap popcount, then locates its voxel with the leaf's 9-bit mPrefixSum plus
an in-word __fns bit select. Same signature, byte-exact decode maps.

Verified byte-exact on the VBM goldens for all consumers (decode/box/lap/weno) at
widths 64/128/256/512, and faster for every consumer with no regression: decode-only
2.17x/1.97x/1.62x/1.42x (w6/w7/w8/w9), 7-pt Laplacian -8.5..-15.4%, box/weno -4..-9%.

Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant