Skip to content

perf(CSGOptiX): rebuild Philox RNG state after trace instead of carry - #448

Merged
plexoos merged 7 commits into
mainfrom
rebuild_RNG
Oct 3, 2026
Merged

plexoos merged 7 commits into
mainfrom
rebuild_RNG

Conversation

@ggalgoczi

@ggalgoczi ggalgoczi commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Reduce the Philox RNG state kept live across optixTrace() calls in the
photon-propagation loop.

Before tracing, the kernel records the current random-stream position as a
32-bit value:

(rng.ctr.x << 2) | (rng.STATE & 3u)

After tracing, it reconstructs the 64-byte Philox state from the seed, event
index, and photon index, then uses skipahead() to resume at the saved draw
position.

Philox is Simphony's sole device RNG, so this behavior is unconditional.

Motivation

Values that remain live across optixTrace() contribute to the OptiX
continuation-state footprint. Carrying the complete 64-byte Philox state can
therefore increase stack spills and L2-memory traffic.

Keeping only a 4-byte stream position across the trace trades inexpensive
Philox reconstruction for a smaller live set in the propagation kernel.

Correctness

The reconstructed state resumes at the same scalar draw position because:

  • photon index selects the Philox subsequence;
  • event index supplies the configured event offset;
  • ctr.x and STATE identify the current position within the generated
    four-value block;
  • optixTrace() does not consume random values; and
  • propagation currently uses scalar uniform draws and does not depend on
    cached normal-distribution state.

The 32-bit position delta assumes fewer than 2^32 random draws per photon,
which is far above the configured propagation limits.

Fixed-seed validation produced byte-identical hit output between the base and
optimized kernels.

Performance

On the reported DUNE-scale benchmark—125 million photons on an RTX 4090—the
kernel wall time improved by approximately 4%.

Additional pfRICH measurements on an RTX 4090 showed approximately 1.4–1.8%
lower propagation-kernel time, indicating that the exact improvement depends
on geometry and workload.

@ggalgoczi
ggalgoczi requested a review from plexoos September 16, 2026 20:01
@ggalgoczi ggalgoczi added the enhancement New feature or request label Sep 16, 2026
@ggalgoczi ggalgoczi self-assigned this Sep 16, 2026
@ggalgoczi

Copy link
Copy Markdown
Contributor Author

Can be tested with:

GPURaytrace -g tests/geom/pfrich_min_FINAL.gdml -m run_pfrich_2k.mac -s 42

where the mac is:

/run/numberOfThreads 1
/process/optical/cerenkov/setStackPhotons false
/process/optical/scintillation/setStackPhotons false
/run/initialize
/run/beamOn 2000

nsys profile --trace=cuda can be used to see kernel time

@plexoos

plexoos commented Sep 18, 2026

Copy link
Copy Markdown
Member

The PR statement that “the XORWOW configuration does not use this” is stale and misleading: there is no longer an XORWOW configuration.

Copilot AI 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.

🔵 Needs a closer look

Philox block-boundary handling can restore four draws early and must be corrected.

Pull request overview

This PR reduces OptiX continuation-state pressure by rebuilding Philox RNG state after photon-propagation traces.

Changes:

  • Saves a compact RNG position before tracing.
  • Reinitializes and skips ahead after tracing.
  • Applies the optimization to photon propagation.
File summaries
File Description
CSGOptiX/CSGOptiX7.cu Rebuilds Philox RNG state around propagation traces.
Review details

Suppressed comments (1)

CSGOptiX/CSGOptiX7.cu:457

  • Philox uses a lazy four-value buffer: after the fourth scalar curand_uniform, STATE can be 4 while ctr.x still names the consumed block; the next RNG call normalizes it and advances the counter. Masking STATE to 3 therefore records the beginning of that block, so a bounce ending on this boundary is restored four draws early and repeats random values. Preserve the boundary value (or normalize it while incrementing ctr.x) in both position calculations.
        unsigned rng_p = ( rng.ctr.x << 2 ) | ( rng.STATE & 3u ) ;
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@plexoos

plexoos commented Sep 18, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-03T00:02:15.416958Z 3c8297f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: bc3cf59016

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@plexoos

plexoos commented Sep 18, 2026

Copy link
Copy Markdown
Member

I reran the DUNE benchmarks after confirming that both RTX 4090s were idle. The uncontended results do not reproduce the previously reported speedup; instead, the PR is consistently about 1% slower.

Setup

  • Base: origin/main at 681f09409
  • Head: bc3cf5901
  • Release builds
  • Fixed seed: 42
  • DUNE geometry: dune_mock_wls_detector_box.gdml
  • Eight runs per revision:
    • Five base → head pairs
    • Three reverse-order head → base pairs to control for warm-up and thermal ordering

Results

Test Base median Head median Head change
simg4ox, 1M photons 40.257 ms 40.719 ms 1.148% slower
GPURaytrace, summed 122 GPU slices 23.8660 s 24.0880 s 0.930% slower
GPURaytrace, complete simulate() 24.2023 s 24.4241 s 0.916% slower

The paired mean changes were:

  • simg4ox: 0.887% slower, with a simple paired 95% CI of 0.396–1.379%.
  • GPURaytrace: 0.886% slower, with a simple paired 95% CI of 0.763–1.008%.
  • Head was slower in all eight GPURaytrace pairs.

Correctness

The results remained deterministic and byte-identical:

  • simg4ox: 1,000,000 photons, 988,940 GPU hits and 988,996 Geant4 hits in every run.

  • Both simg4ox hit arrays had identical SHA-256 hashes across all 16 executions.

  • GPURaytrace: 120,984,484 photons and 3,779,848 GPU hits in every run.

  • Base and head produced the same GPURaytrace hit-stream SHA-256:

    0ec0d6ec41ffbe574a1faed7cc1326bb19400321160c5ae64c99648d1af97b34

GPU telemetry was collected once per second throughout the tests. The control GPU remained at 0% utilization and 8 MiB allocated, while the benchmark GPU returned to 0% and approximately 97 MiB between runs. There were no external compute processes.

Both builds reported Philox, so this measures the PR’s additional RNG-position restoration work, not XORWOW versus Philox.

Based on this uncontended rerun, the earlier apparent ~4% improvement was caused by GPU contention and should not be used as evidence for this PR. The current evidence shows preserved output with a repeatable performance regression of approximately 1%.

@ggalgoczi

Copy link
Copy Markdown
Contributor Author

I reran the DUNE benchmarks after confirming that both RTX 4090s were idle. The uncontended results do not reproduce the previously reported speedup; instead, the PR is consistently about 1% slower.

Setup

* Base: `origin/main` at `681f09409`

* Head: `bc3cf5901`

* Release builds

* Fixed seed: `42`

* DUNE geometry: `dune_mock_wls_detector_box.gdml`

* Eight runs per revision:
  
  * Five `base → head` pairs
  * Three reverse-order `head → base` pairs to control for warm-up and thermal ordering

Results

Test Base median Head median Head change
simg4ox, 1M photons 40.257 ms 40.719 ms 1.148% slower
GPURaytrace, summed 122 GPU slices 23.8660 s 24.0880 s 0.930% slower
GPURaytrace, complete simulate() 24.2023 s 24.4241 s 0.916% slower

The paired mean changes were:

* `simg4ox`: 0.887% slower, with a simple paired 95% CI of 0.396–1.379%.

* `GPURaytrace`: 0.886% slower, with a simple paired 95% CI of 0.763–1.008%.

* Head was slower in all eight `GPURaytrace` pairs.

Correctness

The results remained deterministic and byte-identical:

* `simg4ox`: 1,000,000 photons, 988,940 GPU hits and 988,996 Geant4 hits in every run.

* Both `simg4ox` hit arrays had identical SHA-256 hashes across all 16 executions.

* `GPURaytrace`: 120,984,484 photons and 3,779,848 GPU hits in every run.

* Base and head produced the same GPURaytrace hit-stream SHA-256:
  `0ec0d6ec41ffbe574a1faed7cc1326bb19400321160c5ae64c99648d1af97b34`

GPU telemetry was collected once per second throughout the tests. The control GPU remained at 0% utilization and 8 MiB allocated, while the benchmark GPU returned to 0% and approximately 97 MiB between runs. There were no external compute processes.

Both builds reported Philox, so this measures the PR’s additional RNG-position restoration work, not XORWOW versus Philox.

Based on this uncontended rerun, the earlier apparent ~4% improvement was caused by GPU contention and should not be used as evidence for this PR. The current evidence shows preserved output with a repeatable performance regression of approximately 1%.

The current DUNE config that was used for this test is not a proper one. Most GPU lanes sit idle due to lifetime divergence. This PR is aimed to speed up optimized processes where performance actually matter. I will open a PR with SER that optimizes the DUNE workload. Once that is in, this PR will speed up DUNE case too then.

@ggalgoczi

Copy link
Copy Markdown
Contributor Author

@plexoos what if we make this an option with default turned off, is that sufficient for you?

@plexoos

plexoos commented Sep 23, 2026

Copy link
Copy Markdown
Member

Yes, putting this behind a compile definition would be a good way to introduce this experimental functionality while keeping the default behavior unchanged.

@ggalgoczi

Copy link
Copy Markdown
Contributor Author

Yes, putting this behind a compile definition would be a good way to introduce this experimental functionality while keeping the default behavior unchanged.

Implemented.

Exercise SIMPHONY_RNG_REBUILD in the GPU image matrix by compiling isolated OFF and ON PTX variants and running a deterministic five-event simg4ox workload.

Report and validate per-event photon counts, normalize multi-event hit summaries by event ID for serial and multithreaded logs, and require matching photon counts, per-event and total hit counts, and byte-identical s_hits.npy data. Also assert that the PTX artifacts differ so CI confirms both compile-time paths were built.
Add SIMPHONY_RNG_REBUILD to the CMake build-options guide with its default, PTX scope, configuration command, and fixed-seed behavior expectations.

Link the performance guide to the option and clarify that benchmarking each variant requires reconfiguring and rebuilding the CSGOptiX PTX target.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

RNG state reconstruction has unresolved correctness issues that can alter random-number sequences.

Review effort: Lite
Findings: 1 High severity

Open (1)

Comment thread CSGOptiX/CSGOptiX.cu

#ifdef SIMPHONY_RNG_REBUILD
sim->rng->init( rng, sim->evt->index, photon_idx );
skipahead( (unsigned long long)( rng_p - ( ( rng.ctr.x << 2 ) | ( rng.STATE & 3u ) ) ), &rng ) ;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Philox overload of skipahead(n) counts scalar elements, not four-element blocks. Its implementation applies n & 3 to STATE, advances the counter by n / 4, handles the intra-block carry, and regenerates output. Therefore 4 * ctr.x + STATE is the scalar position, and reinitializing followed by skipahead(delta) restores arbitrary intra-block positions. The fixed-seed ON/OFF CTest also verifies identical per-event counts and byte-identical hit output.

@plexoos

plexoos commented Oct 2, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 3c8297fde8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@plexoos
plexoos requested a balanced review from Copilot October 3, 2026 00:02

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The equivalence tests can pass with missing variant PTX files while both runs use the same fallback kernel.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)

Comment thread tests/CMakeLists.txt
Require each RNG rebuild simg4ox run to use its configured PTX artifact instead of silently falling back to the normal build output.

Replace the inverted compare_files test with an explicit comparison that passes only for two readable, distinct PTX files and preserves missing-file or comparison errors as failures.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

RNG reconstruction affects simulation reproducibility and needs human confirmation of GPU-backed equivalence results.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Align PR description with opt-in RNG rebuild behavior

CSGOptiX/​CMakeLists.txt:9

The PR description says RNG rebuilding is unconditional, but SIMPHONY_RNG_REBUILD defaults to OFF and guards the kernel changes. Default builds therefore retain the original RNG-state handling. Please align the description with the documented experimental, opt-in behavior and specify -DSIMPHONY_RNG_REBUILD=ON to enable it.

@plexoos
plexoos merged commit 6eae599 into main Oct 3, 2026
17 checks passed
@plexoos
plexoos deleted the rebuild_RNG branch October 3, 2026 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants