Add new application: petsc-gmres - #87
Conversation
|
Thanks for the detailed validation notes. One current blocker is DCO: the check is failing on this draft PR. Could you please add Signed-off-by lines to the commits that are missing them, or otherwise update the branch so the DCO check passes? |
PETSc KSP (GMRES + GAMG) benchmark: loads the audikw_1 sparse SPD matrix (SuiteSparse GHS_psdef group, 943,695 x 943,695, 77,651,847 nnz) via MatLoad against a pre-converted PETSc binary file, solves Ax=b for a known x, reports relative L2 error and solve wall-time. PETSc is fetched via bk_fetch_source, pinned to v3.25.2. The app's own source is vendored directly in src/ rather than fetched from a separate repo, since its upstream development happens in a private RIKEN-RCCS repository (not fetchable by bk_fetch_source's plain git clone). RIKYU build/run recipe validated end to end on real hardware: PETSc builds and configures cleanly against nvhpc-hpcx, the app compiles and links, and a 4-rank run against the staged matrix produces a correct result (relative L2 0.03154, matching the expected ~0.03-0.04 band). Fugaku and RC_DGXSP cases are included in build.sh/run.sh based on previously-validated recipes on those systems, but their list.csv rows are enable=no pending data staging (see README.md's "Staging the data" section -- Fugaku's group-storage volumes are currently at quota). -pc_gamg_square_graph 0 is required at any rank count above 1 on every system, to avoid a crash in GAMG's aggressive-coarsening graph-squaring step on this matrix's connectivity (a cuSPARSE resource error on GPU, a multi-GB single-allocation OOM on CPU). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
Validated end to end on real ng-dgx-m2 hardware (same GB10 Blackwell hardware as the ng-dgx-m1 this app's list.csv actually targets, just idle at the time): PETSc CUDA build (CUDA_ARCH auto-detected as 121, matching GB10's sm_121), matrix conversion (nnz=77,651,847, correct), and a 1-rank GPU run all succeeded -- solve_time_s=7.57, relative L2=0.0443346 (correct, matches the known-good cross-machine baseline). Stages audikw_1.petscbin at a fixed path under $HOME (this system has no separate group-storage tier, unlike RIKYU/Fugaku), flips RC_DGXSP to enable=yes in list.csv, and drops the now-stale nvhpc-hpcx/26.3 version pin in favor of the unversioned module name actually available here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
The original ra000009 group storage attempt (/vol0002) had a 0-byte hard quota limit -- true across every group tried (ra000009, ra250029, hp250291), and independent of the "0k" shown by lfs quota, which turned out to mean "unlimited" on some volumes and "hard-enforced zero" on others. /vol0005 (also already covered by this app's FJ queue.csv GFSCACHE declaration, alongside 0002-0004) accepted the write under ra250029 with plenty of headroom (only 64K/4.9TB used beforehand). Validated end to end on real hardware: a 4-rank run against the re-staged data succeeded, solve_time_s=55.50, relative L2=0.03154 -- matches the earlier-measured 4-rank baseline exactly. All three systems (RIKYU, Fugaku, RC_DGXSP) are now enable=yes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
…er cwd [code:petsc-gmres] Found by actually running this through BenchKit's own invocation convention (bash programs/petsc-gmres/build.sh <system> from the repo root) rather than continuing to trust a hand-replication of its commands: BenchKit invokes build.sh with $PWD = repo root, not programs/petsc-gmres/, so the bare "src/GMRES-PETSc.cpp" reference in all three system cases never resolved -- "cannot open source file". $PWD-relative paths elsewhere (PETSC_DIR, ARTIFACT_DIR, bk_fetch_source's own dest) were already correct, since those are meant to live at the repo root; only this app's own vendored source needed a different anchor. Fixed with a BASH_SOURCE-derived APP_DIR. Full real-pipeline validation on RIKYU after this fix: real bk_fetch_source, real build.sh producing a working artifact, real scripts/test_submit.sh correctly parsing list.csv/system.csv and constructing the sbatch command, a real sbatch-launched run.sh producing a correct FOM line, and scripts/result.sh turning it into valid Result JSON with the real PETSc commit hash recorded. This is now confirmed against BenchKit's actual machinery end to end, not just a hand-replica of its commands. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
…:petsc-gmres] Ran build.sh + a real pjsub-submitted run.sh from a genuinely clean checkout (no pre-existing petsc/, artifacts/, or results/ -- explicitly not reusing any earlier manually-built state), matching the same rigor already applied to RIKYU. Found two more real bugs, both only visible through the real invocation path, not by reading the script: 1. build.sh's Fugaku case had the PETSC_WITH_EXTERNAL_LIB link-flags string wrapped in double quotes, passing the whole multi-flag string as one malformed argument to the linker instead of word-splitting it -- PETSc itself built fine, only the final app-compile step failed. 2. run.sh's Fugaku DATA path used /vol0005, the "resolved" canonical path a filesystem tool reported when the data was staged -- but that path doesn't resolve from a real compute-node job; /vol0500 (the alias actually used to stage it) does. The exact same class of surprise as the earlier Rikyu APP_DIR bug: trust what actually runs, not what a tool reports as canonical. Full pipeline now confirmed on Fugaku from a clean checkout: real bk_fetch_source, real build.sh producing a working artifact, a real pjsub-submitted run.sh producing a correct FOM (9.17s, matching the already-measured 48-rank baseline), and scripts/result.sh producing valid Result JSON with the same PETSc commit hash as RIKYU's (confirms the pinned v3.25.2 tag resolves identically across systems). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
Per Suzuki-san's recommendation, measure only the GMRES iteration (MatMult-bound SpMV loop), excluding GAMG setup. Call KSPSetUp(ksp) explicitly before the timed KSPSolve so setup (coarsening + PtAP) is outside the timed region; use -log_view for the per-event breakdown (PCSetUp_GAMG, MatMult, ...). Label: solve_time_s -> ksp_iter_time_s; run.sh sed and --fom-version updated to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: William Dawson <william.dawson@riken.jp>
bd75260 to
ff47f16
Compare
GPU scaling re-measured under the iterate-only FOMPer Suzuki-san's recommendation, the FOM now measures only the GMRES iterate (
Setup was 91-97% of the old FOM — even more dominant than the 70% Correctness held throughout (L2 in the expected 0.03-0.04 band, bit-identical to the old runs at each GPU count). |
…c-gmres] Fugaku's pjsub requires a project group (-g); without it, submission fails with 'Group not authorized to submit a job: group(59999)'. Add a BK_PJM_GROUP env var (no safe default — must be user-supplied) and fail fast with a clear message if it's unset. Also add --no-check-directory so jobs can be submitted from $HOME (not a FEFS data area), which is where benchkit is typically cloned. Signed-off-by: William Dawson <william.dawson@riken.jp>
…[code:petsc-gmres] Without -mat_type aijcusparse and CUDA_VISIBLE_DEVICES set per rank, the solve runs entirely on CPU despite GPUs being allocated -- measured 6.125s (4 CPU ranks) vs 0.183s (4 GPU ranks) on the same node. Use the standard bash -c 'export CUDA_VISIBLE_DEVICES=$OMPI_COMM_WORLD_LOCAL_RANK; exec "$@"' wrapper pattern (same as block1-petsc's own job scripts and the salmon/sbd skills) so each rank binds a distinct GPU. Signed-off-by: William Dawson <william.dawson@riken.jp>
Replace audikw_1 (943k rows, SPD structural mechanics) with stokes2 (4.26M rows, Stokes flow saddle-point system from Suzuki-san, generated via Gmsh/FreeFEM). The larger size provides enough rows/GPU for multi-GPU to win: 4-GPU is 2.05x faster than 1-GPU on Rikyu (vs 1.41x slower on audikw_1). No mtx2petsc conversion needed -- FreeFEM writes PETSc binary directly via ObjectView, same format as MatView. Changes: - run.sh: DATA paths -> stokes2.dat, add -matload_block_size 1, add CUDA_VISIBLE_DEVICES binding to DGX Spark (matching RIKYU), --exp stokes2 - README.md: describe stokes2, update correctness (L2 ~0.25 for Stokes saddle-point, not ~0.03 for SPD), update staging table and regeneration Signed-off-by: William Dawson <william.dawson@riken.jp>
stokes2 matrix — full three-machine results (iterate-only FOM)Switched the benchmark matrix from Rikyu (GB200 NVL4, GPU, 1 rank/GPU)
Multi-GPU now wins — at ~1M rows/GPU there is enough work to amortize communication. Compare with Fugaku (A64FX, multi-node CPU, 48 ranks/node,
|
| nodes | ranks | ksp_iter_time_s | relative L2 | speedup |
|---|---|---|---|---|
| 1 | 48 | 44.881 | 0.2663 | 1.00x |
| 2 | 96 | 28.532 | 0.2582 | 1.57x |
| 4 | 192 | 16.777 | 0.2317 | 2.67x |
| 8 | 384 | 15.959 | 0.2641 | 2.81x |
Clean scaling through 4 nodes (2.67× at 4× ranks), then nearly flat 4→8 (2.81× at 8× ranks) — communication wall hits ~192 ranks for this problem size on A64FX.
DGX Spark (GB10 Blackwell, 1 GPU)
| machine | GPU | ksp_iter_time_s | relative L2 |
|---|---|---|---|
| Rikyu | B200 | 1.497 | 0.2516 |
| DGX Spark | GB10 | 21.430 | 0.2516 |
Correctness bit-identical (L2 0.251638 on both). 14.3× slowdown on GB10 vs B200 — larger than audikw_1's 5.2×, since the larger matrix stresses memory bandwidth more and GB10 has a smaller bandwidth budget.
Summary
All three machines validated via test_submit.sh with the stokes2.dat data staged at the per-system paths in run.sh. The f-pt queue was used for the Fugaku multi-node runs (wider node range than small); the committed list.csv/system.csv stay on small.
…-gmres] run.sh has launched RIKYU with -mat_type aijcusparse since the GPU-binding fix, but build.sh still configured PETSc --with-cuda=0. A CPU-only PETSc does not register that Mat type, so the shipped build/run pair could not have worked: the old artifact fails with "Unknown Mat type given: aijcusparse" (PETSc error 86) at MatSetFromOptions. Every GPU and stokes2 number reported on this PR came from the block1-eeas job scripts, not from BenchKit's own build.sh/run.sh. Configure --with-cuda=1 against the loaded nvhpc-hpcx CUDA toolkit, cuda-arch 100 (sm_100, B200). The arch is hardcoded rather than probed with nvidia-smi as RC_DGXSP does, because RIKYU is a cross-mode system whose build runner is a login node where a GPU is not guaranteed visible. PETSC_ARCH becomes arch-rikyu-cuda so a stale CPU-only arch-rikyu tree is never silently reused. Verified end to end on Rikyu off this branch: - bash programs/petsc-gmres/build.sh RIKYU: exit 0, 4m55s; artifact links libcusparse/libcublas/libcudart; PETSC_HAVE_CUDA 1. - bash scripts/test_submit.sh petsc-gmres 1: exit 0, results/result gets FOM:0.680068 FOM_unit:s FOM_version:ksp_iter_time Exp:stokes2 node_count:1 numproc_node:4 nthreads:1, relative L2 0.227831 -- matching the 4-GPU stokes2 figures measured outside BenchKit (0.683s, L2 0.2278). - -log_view on the same binary reports GPU %F = 100 for MatMult and KSPSolve, banner "arch-rikyu-cuda ... CUDA architecture 100", so the solve is genuinely on device rather than silently falling back. Signed-off-by: William Dawson <william.dawson@riken.jp> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEzS2ybD8VEnQa9Sq5qYUM
Any run spanning 2+ nodes on GPU hung indefinitely, 100% reproducibly. A
live gdb backtrace on the spinning ranks showed them split across two
different collectives:
node 1: main -> MatMult -> VecScatterEnd -> PetscSFBcastEnd
-> MPI_Waitall -> ucp_worker_progress [spinning]
node 2: MatGetInfo -> MPIU_Allreduce -> MPI_Allreduce
-> ompi_coll_base_allreduce_intra_recursivedoubling
CPUs at 98% and GPUs at 0% utilisation, stuck at the first inter-node
GPU-buffer exchange -- the MatMult that forms the RHS, before KSP starts.
Cause: PetscInitialize calls MPI_Init before any CUDA context exists, so
UCX/UCC probe for CUDA support while bootstrapping MPI_COMM_WORLD, find
none, and cache a rendezvous protocol that deadlocks on GPU buffers. This
is the same failure mode SALMON hit on this machine, fixed there by
calling acc_init before MPI_Init_thread.
Establish the context with cudaSetDevice/cudaFree ahead of
PetscInitialize. Guarded on PETSC_HAVE_CUDA so Fugaku's CPU-only build is
untouched, and warns rather than aborts when no GPU is present so a CUDA
build still runs on a CPU node. build.sh gains the CUDA include path and
-lcudart on the app link, which it did not need before.
Verified on Rikyu off this branch:
- unfixed binary, 8 GPU / 2 nodes: still hanging at a 180 s timeout.
- fixed binary, same matrix and flags: exit 0 in 13 s, 200 iterations.
- bash programs/petsc-gmres/build.sh RIKYU: BUILD_OK, artifact links
libcudart.so.13 and libcusparse.so.12.
- bash scripts/test_submit.sh petsc-gmres 4 (2 nodes, 8 GPUs): FOM
1.024436 s, against 1.296136 s at 4 GPUs on 1 node.
This changes a recorded conclusion: 8 GPU / 2 nodes was previously
measured as *slower* than 4 GPU / 1 node, which is what the hang looks
like from the outside once a run does complete. Multi-node GPU scaling
needs re-measuring against this build.
Signed-off-by: William Dawson <william.dawson@riken.jp>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEzS2ybD8VEnQa9Sq5qYUM
…etsc-gmres]
Per-routine breakdown (A. Suzuki): capture PETSc's event log with
-log_view and parse MatMult / KSPSolve time, flop and flop/s plus the SF
pack+unpack time with FOM.awk. GPU systems also pass -log_view_gpu_time,
without which MatMult's time and every GPU Mflop/s column read "n/a" --
most of what the breakdown exists to report. The table ships as
results/fom_details.txt and is mirrored into SECTION lines, BenchKit's
only structured channel for sub-timings. A time that is not numeric is
skipped with a warning rather than passed to bk_emit_section, which would
reject it and, under set -e, abort before the FOM was ever emitted.
Three fixes to the original scripts: BEING{ -> BEGIN{ in FOM.awk (awk read
BEING as an always-false variable pattern, so the initialisers never ran
and a missing event printed blank instead of 0.0); "ksp_details = $(...)"
-> no spaces, which was a bash syntax error that aborted every run; and
${logetsc} -> ${logpetsc}.
GMRES restart: PETSc's default of 30 is too small for these Stokes
systems. stokes3 and stokes4 stagnate at it and never converge, hitting
the 10000-iteration cap with a true residual of 1.8e-03. At restart 100
stokes3 converges in 285 iterations and less wall time than the
stagnating run. Overridable via BK_PETSC_GMRES_RESTART. These operators
are singular, so no restart guarantees convergence and larger is not
monotonically better -- restart 80 converged and then broke down on a
rerun of the identical configuration.
BK_PETSC_GMRES_MATRIX selects the matrix without editing this script, and
--exp now follows the file name so results are labelled for the matrix
actually solved. list.csv covers 1, 2 and 4 GPUs on one node plus 8 GPUs
across two.
Verified on Rikyu through the shipped scripts: test_submit.sh lines 3 and
4 both exit 0 and emit FOM plus the three SECTION lines, with
fom_details.txt populated in every column.
Signed-off-by: William Dawson <william.dawson@riken.jp>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEzS2ybD8VEnQa9Sq5qYUM
…de:petsc-gmres] scripts/result.sh attaches SECTION lines to the FOM block currently open and resets the accumulator on every FOM line, so sections written before their FOM are dropped. run.sh emitted them first, which silently discarded the entire per-routine breakdown: result.sh still exited 0 and produced valid Result JSON, just with no fom_breakdown key. results/result looked correct on inspection, so nothing short of running the full pipeline surfaced it. Found by running build.sh -> test_submit.sh -> result.sh end to end from a fresh clone of this branch. After the reorder, result0.json carries fom_breakdown.sections with MatMult, KSPSolve and SFPack_SFUnpack, their times, and the results/fom_details.txt artifact reference on each. Signed-off-by: William Dawson <william.dawson@riken.jp> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEzS2ybD8VEnQa9Sq5qYUM
The comments and README pointed at skills in a separate, private repository that a reader of this repo cannot open, and in places described how a problem was diagnosed rather than what the code does. Rewrite them to be shorter and self-contained: keep the reason a workaround exists, drop the trail that found it and the pointers to material nobody here can read. No functional change. Signed-off-by: William Dawson <william.dawson@riken.jp> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEzS2ybD8VEnQa9Sq5qYUM
0c41518 to
1da485a
Compare
A PETSc KSP (GMRES + GAMG) benchmark, verified on Rikyu, Fugaku, and R-CCS Cloud's DGX Spark.
[code:petsc-gmres]The performance tables previously in this description have been removed rather than updated. They were measured on the
audikw_1matrix under a setup-inclusive FOM, and on a build that deadlocked on any 2+ node GPU run (fixed in this branch), so both the absolute numbers and the multi-node conclusions drawn from them no longer describe what this branch builds. Re-measured results will be posted once they are complete.