perf(cuda): skip the far LOD pass when the far band is empty - #5
Conversation
API_computeSES_lod ran computeSlicedSES for BOTH near and far bands unconditionally. When the molecule lies entirely in the near band the far pass still pays a full pass of setup (grid build + atom thrust::sort) + the slab-enumeration loop + aabbInFrustum tests, only to produce 0 geometry — the per-slab visible-only cull skips the heavy refine/MC kernels but not this setup/enumeration cost. Add a pass-level pre-check: test the model's padded world AABB (getMinMax, expanded by maxAtomRad + 2*probe to match the grid extent so the test is conservative) against farPlanes with the existing aabbInFrustum; skip the far computeSlicedSES when the far band is provably empty. Output-identical (the near pass already covers every visible slab when the far AABB is outside) — verified byte-identical NVert/NTri with vs without the skip on 1CRN and 3EAM, both the empty-far and real-split cases. Measured (dgx RTX A1000, reso 0.5, coarseMul 2): empty-far band 3EAM (12625 atoms) 129->115 ms (~11%); 1CRN small ~noise; real-split case unchanged (skip correctly does not fire). Modest win, larger on big multi-slab systems; the skip never fires when the far band has work. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR optimizes the CUDA LOD SES pipeline by avoiding the far-band computeSlicedSES pass when it can be proven to generate no geometry, reducing unnecessary setup and slab-enumeration overhead for near-only cases.
Changes:
- Added a pass-level frustum pre-check using a conservatively padded model AABB against
farPlanes. - Skips the far
computeSlicedSEScall entirely when the padded AABB is outside the far frustum (i.e., far band is empty).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // this setup+enumeration cost. Test the model AABB (padded by the same maxAtomRad + 2*probe the grid | ||
| // uses, so the test is conservative — never skips a band that could contribute) against farPlanes |
…xact) Per PR review: the comment claimed the AABB is padded by the SAME amount the grid uses, but the grid extent comes from computeMaxDist/originGridNeighbor (per-side maxAtomRad+probeRadius) and doesn't equal maxAtomRad+2*probeRadius exactly. Reword to state the pad is >= the grid's per-side reach — a deliberate over-cover that never under-covers, so the skip never drops a band that could contribute. Comment-only; the pad value and logic are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Good catch — fixed in a7ad2e4. The comment now states the relationship accurately: the per-side pad |
…with Metal) The per-vertex nearest-atom search used fast_distance (sqrt) per candidate while the Metal twin (nearestAtomSorted) already uses dot/squared distance. sqrt is monotonic so the argmin is identical without it. Switch to sqr_distance (the squared helper already present, matching the commented-out intent). Output byte-identical: verified md5-identical OBJ on 1CRN/1UBQ/3EAM (baseline build vs this change, same -v 0.5). Brings the two backends into agreement; correctness-neutral (fast-math already softened the sqrt, so this is a tidy-up, not a perf win). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Added a small related parity tidy-up (8eadb93): |
What
API_computeSES_lodrunscomputeSlicedSESfor both the near and far bands unconditionally. When the molecule lies entirely in the near band, the far pass still pays a full pass of setup (grid build + atomthrust::sort) + the slab-enumeration loop +aabbInFrustumtests, only to produce 0 geometry. The per-slab visible-only cull (mode==0) already skips the heavy refine/MC kernels, but not this setup/enumeration cost.This adds a pass-level pre-check: test the model's padded world AABB (
getMinMax, expanded bymaxAtomRad + 2*probeto match the grid extent, so the test is conservative and never skips a band that could contribute) againstfarPlanesusing the existingaabbInFrustum. The farcomputeSlicedSESis skipped when the far band is provably empty.Correctness — output-identical (verified byte-exact)
The skip only removes a pass that produced nothing (when the far AABB is outside the far frustum, the near pass already covered every visible slab). Verified on 1CRN and 3EAM, both the empty-far and the real-split cases:
NVert/NTriare identical with vs without the skip.Performance (dgx, RTX A1000, reso 0.5, coarseMul 2)
A modest win, larger on big multi-slab systems; the skip never fires when the far band has real work. Tested via a small harness calling
API_computeSES_loddirectly (the CLI doesn't exercise the LOD API); harness not included in the PR.Provenance
This mirrors the same empty-far-pass skip applied in the UnityMol Unity-ComputeShader port (where it was ~2×, since that path re-ran the whole GPU dispatch; CUDA's in-loop cull already makes the empty pass cheaper, hence the smaller win here).
🤖 Generated with Claude Code