Skip to content

Commit 09f7a17

Browse files
committed
Ledger (93): m_rhs and m_weno present:allocatable opt-in -- -0.09/-0.11 s per step, bit-identical, all gates; copies fell 435->321 not 165 (dummy-argument descriptors survive, explicit present refuted); pre-existing non-Newtonian failures on the amdflang lane recorded
1 parent 8c81242 commit 09f7a17

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

docs/documentation/amr_action_plan.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,153 @@ possible while AMR aborts on the target machine at 1 rank, and every increment b
226226
on a compiler that does not reproduce it. It also means the ladder should add a CCE arm as soon as one
227227
exists, or the same class of breakage will keep accumulating undetected.
228228

229+
## 2026-09-06 (93) — PRE-REGISTERED: m_rhs and m_weno opted into the ledger-82 per-file present:allocatable -- a WIN at the floor's edge, bit-identical: the marginal step -0.09 / -0.11 s (-5%%) with both ON arms below both OFF, but the copies per level-2 batch fell 435 -> ~321, not to ~165 as predicted: ~60%% of the copies these two files paid survive, most of them attributed to descriptors of DUMMY ARGUMENTS, which defaultmap(present:allocatable) cannot reach and -- tested the same hour -- an explicit map(present,alloc:) on the dummy does not remove either
230+
231+
**Pre-registration (amr-bench/notes/ledger_drafts/l93_prereg.md, written 06:25 before the build finished).** Ledger 92
232+
named the per-batch fixed cost as ~435 sub-kilobyte copies issued before the rhs launches and read them as the
233+
per-launch descriptor maps of the allocatables the never-opted-in files name. The increment: ``#:set
234+
MFC_OMP_PRESENT_ALLOCATABLE = True`` with an audit comment in m_rhs.fpp and m_weno.fpp (the allocation audit of the
235+
five candidate files found every conditionally allocated array these two name launches only under its own
236+
condition; m_riemann_solver_hllc has five arrays -- Re_avg_rsx_vf, flux_gsrc_rsx_vf, Res_gs, Re_idx, mom_sp_rsx_vf --
237+
and m_variables_conversion two -- bubrs_vc, weight -- that a kernel can name while unallocated, so they stay out
238+
until they get placeholder allocations). No arithmetic change. ``task21/present-rhs`` = 8c812427 on up/mega 516399a5,
239+
16 lines. Predictions: (1) copies per level-2 batch 435 -> ~165; (2) fit intercept 11.9 -> ~6 ms, idle 9.3 -> ~5;
240+
(3) bit-identity across the two binaries; (4) marginal step -0.06 to -0.12 s, claimed only if both ON marginals sit
241+
below both OFF. Falsifier: copies staying ~435 would mean the descriptor-map reading is wrong.
242+
243+
**Result.** (3) held: inc.sh ident2 on the 60-step no-pad deck, both restart files IDENTICAL by cmp (3,072,000,000
244+
and 8,942,976,652 bytes), and the A/B's own 60-step pad-0.10 identity pair IDENTICAL as well. (1) held in sign and
245+
failed in size -- level-2 batches 435 -> ~321 (all-batch mean 447 -> 333; rank 3's total copies 487,432 -> 391,672,
246+
-19.6%%) against ~165 predicted; (2) held in sign and failed in size too: a second, batch-logged trace (rank_time_wrt
247+
= T,
248+
logs/batchprof-8c812427/rtwT) gives level-2 batches 321 copies each, the level-2 fit span = 9.4 ms + 10.2 ms per
249+
Mcell against 11.9 + 10.0 (intercept predicted ~6), and the single-member batch 18.3 -> 15.7 ms (idle 8.8 -> 6.9,
250+
copies 2.4 -> 1.7, kernels 7.1 -> 7.1). Rank 3, steady half, rank_time_wrt = F, same instrument as ledger 92
251+
(amr-bench/batchprof.sh, logs/batchprof-8c812427):
252+
253+
| per batch, rank 3 | 74764791 (ledger 92) | 8c812427 |
254+
|---|---|---|
255+
| copies | 447 | 333 |
256+
| copy time, ms | 2.42 | 1.82 |
257+
| idle, ms | 9.33 | 7.91 |
258+
| kernel, ms | 31.27 | 31.62 |
259+
| span, ms | 43.02 | 41.35 |
260+
261+
Per launch (copies before each dispatch): add_directional_advection 26 -> 0; flux divergence 33 -> 21; s_weno 10 ->
262+
10; s_preserve_monotonicity 13 -> 13; s_pack_weno_input_arr 7.8 -> 7.8; HLLC 39 and the conversion 8 untouched (not
263+
opted in). Every target-teams directive in both files carries the clause in the generated source (16 of 16, 60 of
264+
60), so the survivors are not a missed kernel. (4) held: padab.sh with the two pinned binaries interleaved (OFF =
265+
74764791, ON = 8c812427, both amr_bat_pad = 0.10, cap 64, 40/240 from-scratch pairs x 2 reps, hold 406685 on
266+
k004-001, 06:35-07:11):
267+
268+
| per 240-step arm | OFF rep 1 / 2 | ON rep 1 / 2 |
269+
|---|---|---|
270+
| wall, s | 425.2 / 434.8 | 407.5 / 411.3 (-17.7 / -23.5) |
271+
| marginal step, s | 1.967 / 2.001 | 1.876 / 1.895 (-0.091 / -0.106) |
272+
| rhs summed over ranks, s | 1,437 / 1,437 | 1,385 / 1,385 (-3.6%%) |
273+
| rhs per rank, rep 1 | 172 168 167 194 194 188 184 170 | 167 163 162 187 180 182 179 165 |
274+
| rhs max/min | 1.168 / 1.200 | 1.149 / 1.143 |
275+
| [phase] coarse (level-0 rhs), s, rep 1 | 74.3 | 70.6 |
276+
| [mpiwait] reflux mean, s | 34.5 / 38.2 | 30.4 / 31.0 |
277+
| [mpiwait] TOTAL mean, s | 132.5 / 140.8 | 122.0 / 125.8 |
278+
| [phase] regrid, s, rep 1 | 32.9 | 32.8 |
279+
| batches / singles | 28,920 / 3,420 both | 28,920 / 3,420 both |
280+
281+
Both ON marginals (1.876, 1.895) sit below both OFF (1.967, 2.001), so by the pre-registered rule the step is
282+
claimed: -0.09 / -0.11 s per step, -5%%, with the batch composition identical in all four arms. The accounting: the
283+
batch span fell 1.7 ms x 10.5-21 batches per rank per step = 0.02-0.04 s per step of rhs, which is what the rhs
284+
row shows (mean -6.5 s per rank per 240 steps in both reps, range -1.7 to -18.1, larger on average on the batch-heavy
285+
ranks 3-6); the level-0 rhs (``coarse``), whose kernels are the same m_rhs/m_weno launches, fell 3.6 / 3.9 s; and
286+
the waits fell with the slowest rank (reflux -4 / -7 s, TOTAL -10 / -15 s per rank) -- not additive with the rhs
287+
(ledger 88: the fast ranks' wait IS the slow ranks' rhs). The wall follows the critical path, consistent with the
288+
-18 / -24 s: max-rank rhs 194.5 -> 186.6 / 198.4 -> 186.4, max coarse 97.7 -> 89.3 / 102.8 -> 89.5, max reflux
289+
wait 59.8 -> 52.0 / 66.6 -> 53.0.
290+
291+
**Why the prediction missed by 2x, kernel by kernel (read-only classification of the generated .f90 against the
292+
copy sizes, amr-bench/notes/residual_copies_classification_0906.md; the 24 / 80 / 16-byte buckets and the
293+
"two entries per dummy" rule are that note's hypotheses, so are the attributions below).** Of the ~269 pre-launch
294+
copies per level-2 batch these two files paid, ~157 survive (~60%%); ~93 of those are attributed to dummy-argument
295+
descriptors, 9 to idwbuff, and ~45 (a 40 x5 / 48 / 24 tail on every WENO kernel, 16 x2 on the flux divergence) are
296+
unattributed. ``defaultmap(present:allocatable)`` covers allocatable VARIABLES. s_preserve_monotonicity names no
297+
module allocatable at all -- only its three rank-4 assumed-shape dummies, is1-3_weno, v_size -- so the clause
298+
provably could not touch its 13 (120 x6, read as the three dummies at two entries each, plus the tail); s_weno's 10
299+
are its two rank-4 dummies (120 x4) plus the same tail, its six module tables already cost nothing; the flux-
300+
divergence kernels' surviving 21 (24 x8, 80 x11, 16 x2) are attributed to the ``type(scalar_field),
301+
dimension(sys_size)`` dummy rhs_vf (its %%sf is a POINTER, outside the allocatable category), though the counts are
302+
not a clean per-element walk; s_pack_weno_input_arr reads idwbuff(1:3) as loop bounds inside the kernel and pays 3 x
303+
320 bytes -- ``type(int_bounds_info)`` is 320 bytes exactly (verified from the type), the one size in the trace that
304+
matches a type to the byte. In the un-opted files: 16 of HLLC's 39 are attributed (six rank-4 descriptors: two
305+
dummies and four module allocatables the opt-in would remove; six 320-byte int_bounds_info objects from the
306+
GPU_UPDATE of is1-3 and isx-z at m_riemann_state.fpp:314/334 and the directive's own ``copyin='[is1, is2, is3]'``,
307+
which by reading duplicates the :314 update; dir_idx/dir_flg/dir_idx_tau/stress_perm) and 23 are not; the
308+
conversion kernel's 8 include two rank-1 module allocatables the opt-in would remove. And add_directional_advection's
309+
26 -> 0 with only two named module allocatables says amdflang also treats a ``type(vector_field)`` dummy (allocatable
310+
%%vf) as allocatable-category -- direction firm, split unsure.
311+
312+
**The next lever, tested and refuted.** An experiment binary (429188f6 = 8c812427 + ``present='[...]'`` on the
313+
rank-4 dummies of s_weno and s_preserve_monotonicity, emitted as ``map(present,alloc: ...)`` in all six generated
314+
kernels, not merged) traced on the same hold 07:12-07:14: s_weno 10 -> 10, s_preserve_monotonicity 13 -> 13, the
315+
120-byte entries unchanged, batch span 41.35 -> 40.52 ms (noise). An explicit present map on an assumed-shape dummy
316+
does not remove its per-launch descriptor copies under amdflang.
317+
318+
**What this closes and opens.** Closed: the descriptor-map reading (ledger 92) is right in kind -- 114 copies and
319+
1.4 ms of idle per batch went away exactly where module allocatables were named -- and wrong in coverage. Closed too:
320+
the explicit
321+
present map on dummies (above). Open, ranked by copies per launch: (i) the dummies themselves -- a kernel that
322+
reads a module array through a dummy pays two descriptor entries per launch that the same array named directly
323+
does not; the WENO and monotonicity kernels could take v_rs_weno / the rs arrays by host association instead of as
324+
arguments, a structural change to be designed; (ii) opt in m_riemann_solver_hllc after placeholder allocations for its
325+
five hazard arrays, drop
326+
the duplicate copyin, hoist the isx/isy/isz update (4 x 120 + 6 x 320 bytes per launch); (iii) copy idwbuff's six
327+
bounds into integer scalars before the pack kernel (scalars are kernel arguments, not copies); (iv) the scalar_field
328+
dummy walk of the flux-divergence kernels needs the rhs to take the flat store array, a larger change.
329+
330+
**Gates (8c812427).** Bit-identity as above; goldens 70/70, none touched; np=2 oracle with ``amr_batched_advance = T,
331+
amr_bat_pad = 0.10``: 6 families balanced, 0 mismatches, both seed controls pass on both decks; CPU build; NVHPC
332+
compile gate clean (the clause is emitted only on the AMD
333+
branch of OMP_DEFAULT_STR); precheck; and, because m_rhs and m_weno serve every case and a present abort is a hard
334+
failure only amdflang can raise (CI does not run this lane), the FULL local GPU test suite
335+
(inc/8c812427/fullsuite.log): 764 passed, 11 failed, 34 skipped (809, every test accounted for; the
336+
run's TOUCHED=1 is the harness's untracked failed_uuids.txt, no golden changed). The 11 are the ten non-Newtonian
337+
cases (seven unit tests, three examples) and the viscous IBM example, which the harness recorded as exceeding its
338+
1-hour timeout (normally 137-223 s) and which was killed by hand after ~2.5 h. Rerun on the BASELINE
339+
516399a5 binary (up/mega without the opt-in, built and run the same hour in another tree) the same ten non-Newtonian
340+
cases fail and the IBM example passes (223 s); rerun on 8c812427 the IBM example passes too (195 s; the hang did not
341+
reproduce on either binary) and one unit test (1D nn = 1.5, 78EB6879) flips between passing in the full suite and
342+
failing in the rerun on the SAME byte-identical binary (an ordinary tolerance failure at rel 1.1e-3, not a zero-band
343+
trip). So there is no stable delta from the opt-in: the only test that differs also flips run-to-run on 8c812427
344+
alone, and the baseline ran once; the non-Newtonian failures are PRE-EXISTING on up/mega under
345+
amdflang and are the next paragraph's finding.
346+
347+
**Pre-existing, found by this gate (not caused by this change): the non-Newtonian cases fail on the amdflang lane.**
348+
The shape from the harness's diagnostics: seven unit tests with maximum absolute errors 4e-12 to 1e-8 -- five trip the
349+
packer's zero-band check (the golden exactly zero, the candidate 1e-10 to 1e-9), two are plain tolerance failures --
350+
with relative errors up to 0.1 on near-zero fields (per the audit, in x-momentum; these cases carry an effective
351+
viscosity 1e3-1e4x the rest of the suite's, so the same perturbation is invisible elsewhere; 1D nn = 1.5 sits at the
352+
band, rel 1.1e-3), and three examples: poiseuille_thickening_nn and herschel_bulkley_poiseuille_nn wrong from step 1
353+
(abs 1e-3 to 3e-2, relative O(1)-O(10) on the first failing variables), lid_driven_cavity_nn a 1.4e-3 excursion on a
354+
near-zero field at step 50 -- all three with weno_Re_flux = T. The last full-suite log on this lane (2026-08-23, 708
355+
passed / 0 failed / 32 skipped, before the master merge) had all twelve passing. A read-only audit for the mechanism
356+
found no module allocatable that an
357+
m_rhs/m_weno kernel names being host-written or reallocated in the time loop without a device update, and two
358+
structural gaps in the OpenMP lane worth their own increment: ACC_SETUP_VFs/SFs are Cray-only no-ops
359+
(macros.fpp:82-119), so the device %%sf pointers of the flux_n(i)%%vf(l)%%sf-style arrays are established only by the
360+
allocation-time map, and -- the audit's unverified inference -- GPU_ENTER_DATA(attach=) lowers to map(always,to:)
361+
(OMP_ATTACH_STR is commented out, omp_macros.fpp:106-109). Whether the example failures are a merge regression or a
362+
golden/tolerance question is open (notes/nn_failures_0906.md); the IBM hang is unreproduced and recorded as such. This
363+
does not gate the opt-in
364+
(no stable delta against the baseline) and is not resolved here.
365+
Independent review before this was written: no blocker; its corrections (one copy base, level-2 435 -> ~321
366+
against ~165; the intercept then measured on a batch-logged trace; ~60%% survive with ~60%% of those attributed to
367+
dummies and ~30%% unattributed; the per-rank rhs range -1.7 to -18.1; rhs and wait not additive, critical-path
368+
reading instead; the classification's confidence carried into the kernel paragraph; the identity pair on the pad
369+
deck; "two #:set lines and 14 lines of comment") are applied; the full-suite and pre-existing-failure paragraphs
370+
were reviewed separately after the reruns finished.
371+
372+
**Verdict.** SHIPPED: -0.09 / -0.11 s per step (-5%%) from two ``#:set`` lines and 14 lines of audit comment,
373+
bit-identical, every gate green including the full suite; ~60%% of the copies these files paid survive, mostly
374+
attributed to dummy-argument descriptors, and the obvious fix for those (an explicit present map) is refuted.
375+
229376
## 2026-09-06 (92) — THE PER-BATCH FIXED COST NAMED FROM A KERNEL+COPY TRACE: a batch pays ~12 ms independent of its size, and that is 435 sub-kilobyte device copies inside the batch (395 issued synchronously before its rhs launches -- 39 before every Riemann launch, 33 + 26 before every flux-divergence and advection-source launch, 10 + 13 before every WENO launch -- and 40 in the restore-side grid sync) plus 46 in the swap-side sync between batches -- mostly the ledger-82 per-launch mapping class again, now on the rhs files that were never opted in; the phase-timer syncs are 0.3 ms of it
230377

231378
**Why this measurement.** Ledger 91 left the batched advance with a per-batch fixed cost the offline pricing put at

0 commit comments

Comments
 (0)