Generate indirect-many vec wrappers for formmp (P2M) - #94
Merged
Conversation
This was referenced Jul 29, 2026
fmmlib's formmp routines (P2M) share their argument patterns exactly
with formta (P2L), but only formta had generated _imany wrappers.
Downstream FMM drivers (e.g. boxtree's pyfmmlib wrangler) therefore
form multipoles in a Python loop over per-box scalar formmp calls,
which is serial and call-overhead-bound.
Generalize the formta wrapper block to also emit
{l,h}{2,3}dformmp[_dp]_imany with the same indirect-many addressing,
sum reduction, and OpenMP annotations.
Verified against per-box scalar formmp calls: bit-exact (0.0 max rel
err) for 3D Laplace, 3D Helmholtz, and 2D Laplace on ragged per-box
source counts; with OpenMP enabled, a 4000-box q=3-layout batch at
nterms=20 runs 0.26s -> 0.11s at 4 threads with identical checksums.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYp74e5ZTE6ZHDNR3ETgM6
inducer
enabled auto-merge (rebase)
July 29, 2026 14:18
Owner
|
The follow-up in boxtree sounds good, please send it. :) |
inducer
pushed a commit
to xywei/boxtree
that referenced
this pull request
Aug 5, 2026
pyfmmlib now generates {l,h}{2,3}dformmp[_dp]_imany (inducer/pyfmmlib#94),
the P2M twins of the formta wrappers that form_locals already uses. Switch
form_multipoles to one indirect-many call per level, with each expansion
center drawing on the single source segment of its own box; boxes without
sources are excluded so their expansion entries stay zero, as before.
When pyfmmlib predates these wrappers, form_multipoles transparently falls
back to the previous one-box-at-a-time loop, which is kept verbatim as
_form_multipoles_one_box_at_a_time.
The batched path reproduces the loop bit for bit (tested across 2D/3D,
charges/dipoles, Laplace/Helmholtz). On a 100k-source 3D Laplace tree with
7216 source boxes at order 15, form_multipoles drops from 516 ms to 236 ms
on a 4C/8T laptop with OpenMP, and from 623 ms to 561 ms single-threaded
(the call-overhead saving alone).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYp74e5ZTE6ZHDNR3ETgM6
inducer
pushed a commit
to inducer/boxtree
that referenced
this pull request
Aug 5, 2026
pyfmmlib now generates {l,h}{2,3}dformmp[_dp]_imany (inducer/pyfmmlib#94),
the P2M twins of the formta wrappers that form_locals already uses. Switch
form_multipoles to one indirect-many call per level, with each expansion
center drawing on the single source segment of its own box; boxes without
sources are excluded so their expansion entries stay zero, as before.
When pyfmmlib predates these wrappers, form_multipoles transparently falls
back to the previous one-box-at-a-time loop, which is kept verbatim as
_form_multipoles_one_box_at_a_time.
The batched path reproduces the loop bit for bit (tested across 2D/3D,
charges/dipoles, Laplace/Helmholtz). On a 100k-source 3D Laplace tree with
7216 source boxes at order 15, form_multipoles drops from 516 ms to 236 ms
on a 4C/8T laptop with OpenMP, and from 623 ms to 561 ms single-threaded
(the call-overhead saving alone).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYp74e5ZTE6ZHDNR3ETgM6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
fmmlib's
formmproutines (P2M) share their argument patterns exactly withformta(P2L) —(ier, [zk,] rscale, sources, charge|dipstr[,dipvec], ns, center, nterms, expn)in all eight variants — but onlyformtahad generated_imanywrappers. Downstream drivers (e.g. boxtree'spyfmmlib_integration.FMMLibExpansionWrangler.form_multipoles) therefore form multipoles in a Python loop over per-box scalarformmpcalls, which is serial and call-overhead-bound.This PR generalizes the
formtawrapper block invec_wrappers.pyto also emit{l,h}{2,3}dformmp[_dp]_imanywith the same indirect-many addressing,sumoutput reduction, and OpenMP annotations. No hand-written Fortran; purely the existing generator applied to the twin routine family.Verification
formmploops (0.0 max relative error) for 3D Laplace, 3D Helmholtz, and 2D Laplace on ragged per-box source counts (3–40 sources/box, 50 boxes).nterms=20runs 0.26 s → 0.11 s at 4 threads (4C/8T i7-8650U), identical checksums.Complementary to #93 (which restores the OpenMP flags these annotations need); independent to merge in either order.
A follow-up in boxtree could switch
form_multipolesto this wrapper; happy to send that separately if there's interest.🤖 Generated with Claude Code
https://claude.ai/code/session_01YYp74e5ZTE6ZHDNR3ETgM6