Skip to content

Bound world-space rasterization channel loop unrolling to improve compile times - #743

Open
matthewdcong wants to merge 1 commit into
openvdb:mainfrom
matthewdcong:bound_loop_unrolling
Open

Bound world-space rasterization channel loop unrolling to improve compile times#743
matthewdcong wants to merge 1 commit into
openvdb:mainfrom
matthewdcong:bound_loop_unrolling

Conversation

@matthewdcong

Copy link
Copy Markdown
Contributor

Limit full channel-loop unrolling to kernels with at most 32 channels and use four-way unrolling for larger specializations. Keep the templated warp reduction for small kernels while using the runtime-sized reduction for larger backward kernels.

For CUDA 13.2 targeting sm_120, this reduces forward compile wall time from 165.50s to 71.02s (57.1%, 2.33x) and backward compile wall time from 301.05s to 82.72s (72.5%, 3.64x).

Limit full channel-loop unrolling to kernels with at most 32 channels and use four-way unrolling for larger specializations. Keep the templated warp reduction for small kernels while using the runtime-sized reduction for larger backward kernels.

For CUDA 13.2 targeting sm_120, this reduces forward compile wall time from 165.50s to 71.02s (57.1%, 2.33x) and backward compile wall time from 301.05s to 82.72s (72.5%, 3.64x).

Add 33- and 513-channel coverage for perspective and orthographic cameras, and record the compilation and kernel-resource measurements.

Signed-off-by: Matthew Cong <mcong@nvidia.com>
@matthewdcong
matthewdcong requested a review from a team as a code owner August 18, 2026 06:13

@swahtz swahtz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's great, I assume there's no real runtime performance impact?

@swahtz swahtz added this to the v0.6 milestone Aug 20, 2026
@swahtz

swahtz commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I measured this on an RTX PRO 6000 Blackwell (sm_120), CUDA 13.0, using a synthetic but reasonably sized world-space scene: 512x512 image, 16,384 Gaussians, 16 candidates/tile, and 512 feature channels. These are median CUDA-event kernel times over 30 runs after 8 warmups.

base (full unroll) this PR change
forward 3.588 ms 12.243 ms 3.41x slower
backward 60.727 ms 54.463 ms 10.4% faster

I repeated the run and obtained essentially identical values. So there is a substantial forward-performance tradeoff at 512 channels, despite the backward improvement; this is not runtime-neutral for this workload.

@swahtz

swahtz commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Follow-up with the larger requested fixture: 2048x1024, 9,994,240 Gaussians (1,220 candidates in each 16x16 tile), and 512 feature channels. This is a single pinhole camera with the Gaussians distributed within their assigned tiles. The feature tensor alone is about 20.5 GB; peak process GPU memory was about 50 GB.

Same RTX PRO 6000 Blackwell / CUDA 13.0 system, using median CUDA-event time from 5 samples after 2 warmups:

base (full unroll) this PR change
forward 882.934 ms 2605.360 ms 2.95x slower
backward 10,270.6 ms 12,652.6 ms 23.2% slower

So this scales the same direction as the earlier forward result, and the larger workload also turns the backward path into a regression. This is synthetic rather than a trained capture, but it exercises the target channel specialization and a genuinely large tiled scene.

@swahtz

swahtz commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I ran a smaller sweep to look for a compile/runtime compromise. Fixture: 2048x1024, 1,998,848 Gaussians (244 per 16x16 tile), 512 channels; median CUDA-event time from 5 samples after 2 warmups.

Variant Forward Backward
Full-unroll base 209.2 ms 4672.6 ms
PR, unroll 4 965.1 ms 4708.8 ms
Forward unroll 8 928.1 ms
Forward unroll 16 944.9 ms
Forward unroll 32 958.2 ms
Forward unroll 64 929.1 ms
Backward unroll 8 4578.6 ms
Backward unroll 16 3943.4 ms
Backward unroll 32 3928.4 ms

For backward, 16 looks like the practical sweet spot: 15.6% faster than the full-unroll base; 32 adds only 0.4% while increasing uncached incremental compile time slightly (81.6 s vs. 83.4 s).

For forward, none of 4/8/16/32/64 is close to full unrolling: all remain about 4.4–4.6x slower. So I do not think a different partial-unroll factor alone solves forward. My recommendation would be to use 16-way unrolling for backward, but either retain full unrolling for forward 512/513 or pursue a structural channel-tiling redesign there.

@swahtz

swahtz commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Compile-time context I should have included:

  • The PR description reports clean full-build measurements on CUDA 13.2 / sm_120: forward 165.50 s -> 71.02 s and backward 301.05 s -> 82.72 s.
  • In my CUDA 13.0 / sm_120 environment, with ccache disabled and a single-job incremental rebuild of only the changed CUDA translation unit (cmake --build ... --target fvdb --parallel 1), the measured times were:
Unroll factor Forward TU Backward TU
8 79.56 s
16 69.80 s 81.55 s
32 71.23 s 83.36 s
64 78.62 s

Those incremental numbers are intentionally not directly compared to the PR’s clean full-build baseline; I did not measure unroll 4 and full unroll with that exact same protocol, so presenting them as a complete compile-time comparison would have been misleading. They do show that backward 16 retains roughly the PR-level compilation cost, while larger caps trend upward. I should have stated this distinction in the sweep comment.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants