Skip to content

Modest performance improvements + some suggestions for future profiling from Claude - #380

Open
adrianaghiozzi wants to merge 7 commits into
developfrom
profiling
Open

Modest performance improvements + some suggestions for future profiling from Claude#380
adrianaghiozzi wants to merge 7 commits into
developfrom
profiling

Conversation

@adrianaghiozzi

Copy link
Copy Markdown
Collaborator

This PR introduces some modest performance improvements by explicitly typing a function argument that was being inferred in Torque.jl, refactoring the green function in Kernel2D and fixing a type instability in the integrate_pitch_gar_quadgk/integrate_pitch_gar_quadgk_wt functions.

The source of much of the compute time for several of the examples goes back to the quadgk step, and the tpsi! function in Torque.jl. Claude has some suggestions about how this tpsi! function could be improved, but it included some caveats that seem worthy of human-review/discussion before implementing and therefore are not pushed onto this branch. Claude's ideas below:

Profiling results — diiid_n1 full pipeline
Ran Julia's statistical profiler across the entire main() call (equilibrium → stability → PE → KineticForces → ballooning). Headline finding:

tpsi! (KineticForces/Torque.jl) and its call chain account for ~84% of all profiled samples — despite KineticForces looking like a modest post-processing stage in the wall-clock logs (~55s of ~133s), it dominates actual CPU-thread time by a wide margin once you account for the equilibrium/stability stage being comparatively cheap per-thread.

#1 hotspot: Roots.find_zeros in bounce-point finding — ~26% of total pipeline time
src/KineticForces/BounceAveraging.jl:434, inside _find_bounce_points_and_grid:

bpts = sort!(Roots.find_zeros(vpar_fn, 0.0, 1.0); rev=true)
This is a generic adaptive full-interval root scanner, called once per trapped-particle λ point — per ψ, per bounce harmonic, per species — so it fires an enormous number of times. It alone accounts for ~9,400 of the ~36,300 total samples.

The interesting part: tpsi! (the caller's caller) already computes theta_bmin/theta_bmax a few lines earlier using a lighter-weight utility that already exists in the codebase — find_sign_change_roots(f, grid) in src/KineticForces/Utils.jl:19, explicitly documented as "Single source of truth for the scan-then-Brent idiom" and already used elsewhere in the same file. _find_bounce_points_and_grid doesn't use it, reaching for the heavier Roots.find_zeros instead.

Why I didn't just swap it: find_zeros's adaptive scan is more robust against closely-spaced multiple roots (the code already handles nbpts > 2 for multi-well B(θ) profiles in _find_deepest_well), whereas find_sign_change_roots only catches sign changes between adjacent grid nodes — too coarse a grid could silently miss a well. This is a physics-sensitive change (bounce-point location feeds the NTV torque/kinetic-energy integrals directly), so it needs a grid-resolution choice validated against find_zeros' output before trusting it, plus a regression-harness pass afterward.

Smaller, secondary costs (for context, not obviously worth chasing)

  • QuadGK adaptive quadrature (the pitch-angle integral itself) — substantial but that's inherent to the physics, not obviously wasteful.
  • FastInterpolations spline construction/evaluation inside tpsi! — only ~4% of total, much smaller than I initially suspected from reading the code.

That's the report — find_zeros → find_sign_change_roots is the one concrete, high-value, evidence-backed lead. Let me know if you want to move forward on it, want me to first check how many wells B(θ) actually has across this equilibrium's ψ range (to size a safe grid), or want to look at something else.

…h reltol

integrate_ballooning_ode set abstol=reltol^2 (1e-16, at machine epsilon)
against a non-stiff DP5 solver, forcing needlessly tight step control.
Profiling (warmed, no JIT noise) showed ballooning boundary search as the
dominant real cost on gal-resistive-PE-style cases -- ~55% of pipeline
runtime, driven by many repeated ODE shoots per flux surface (linear
pre-scan + bisection to locate the marginal-stability crossing).

Setting abstol=reltol=1e-8 (the standard pairing) gives a measured ~8%
speedup on Force-Free States for DIIID-like_gal_resistive_pe_example,
confirming reltol was already the binding constraint for most of the
integration. Validated bit-for-bit identical locstab/alpha_critical
(the value that actually drives stability classification) before/after;
the raw ballooning_Delta_prime diagnostic drifts ~1e-5 relative, which
flips a few profile checksums in the regression harness but is far below
any threshold that matters physically. Full 11-case regression suite
against merge-base a0cad26 is otherwise clean.
@logan-nc
logan-nc requested a review from ebursch August 15, 2026 03:39
@logan-nc
logan-nc requested a review from jhalpern30 August 15, 2026 03:39
@logan-nc logan-nc added the perf Same answers, less time or memory label Aug 15, 2026
@logan-nc

Copy link
Copy Markdown
Collaborator

@adrianaghiozzi I assume this is ready to review? If not, please convert to draft

Pulls in 171 develop commits, including the ForceFreeStates -> standalone
LocalStability module extraction (Ballooning.jl moved to
src/LocalStability/Ballooning.jl). Clean merge, no conflicts; Git's rename
detection correctly carried this branch's ballooning abstol fix (69ad76e)
over to the new path.

Regression harness (develop @ 9491f89 vs merged local, 13 cases, full suite):
clean across the board. 12/13 cases fully unchanged (energies, ODE step
counts, equilibrium/stability quantities, all profile checksums identical).
The only diff anywhere is the "ballooning Delta' profile" checksum in
diiid_n1 (1 changed / 46 unchanged) -- the expected, already-validated
fingerprint of this branch's own abstol=reltol fix (~1e-5 relative drift
in the raw diagnostic; locstab/alpha_critical, the value that actually
drives stability classification, is bit-for-bit identical). No numeric
regressions introduced by the merge itself.
@adrianaghiozzi

Copy link
Copy Markdown
Collaborator Author

@logan-nc Yes this is now fully ready! I just pulled in develop and ran the regression harness again - the output of the regression harness is shown in the commit message of d266e79

@jhalpern30 jhalpern30 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks great! Only one minor comment is about comments lol, then its ready to merge

Also - I see your notes about benchmarking the quadgk stuff - can you also add some comment about what kind of speedup the vacuum kernel optimizations obtained just for posterity?

Comment thread src/Vacuum/Kernel2D.jl

ρ2 = x_minus2 + ζ2

# Distance parameter ℛ [Chance Phys. Plasmas 1997 2161 eq. 41]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Claude is rather inconsistent with its comments - sometimes, it will add large, multi-line comments that saturate the repo, and other times it will remove helpful ones

Can you add back in some of these comments? For sections that you optimized and made individual terms out of date, you can just ask Claude to go through the pdf and revise whatever is necessary. This is just helpful for linking the math here directly to Chance's derivation

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yep, just added it back in e952629 !

@adrianaghiozzi

Copy link
Copy Markdown
Collaborator Author

@jhalpern30 Adding for posterity this local test of the Vacuum/Kernel2D green function showing the speedup I observed for a test before and after the changes implemented here:
Screenshot 2026-08-17 at 3 54 56 PM

@matt-pharr

Copy link
Copy Markdown
Collaborator

@logan-nc What are your thoughts on the 0-finding? You are the one who knows those physics the best

@logan-nc

Copy link
Copy Markdown
Collaborator

FYI reviewing and thinking about this is on my todo list but it's just a long list, so please be patient

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

Labels

perf Same answers, less time or memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants