Add Cholesky factorization benchmark (bench_potrf_compact) - #28
Merged
Conversation
Add the potrf analogue of bench_geqrf_compact: a throughput benchmark of the batched Cholesky factorization on symmetric positive-definite matrices, comparing three implementations of the same ?potrf math -- cqr-compact cqr_mkl_dpotrf_compact (this project's batched SIMD kernel) mkl-compact mkl_dpotrf_compact (Intel MKL's batched compact kernel) per-matrix LAPACKE_dpotrf (conventional one-matrix-at-a-time) over pools of small SPD matrices across the target size range, on the tuned column-major lower path (A = L L^T). It reports per-size throughput (matrices/s, GFLOP/s from the n^3/3 + n^2/2 + n/6 Cholesky flop count) and a geometric-mean speedup, and -- since the SPD factor is unique -- gates the compact factor elementwise against LAPACKE_dpotrf, so it doubles as an integration test. Unlike geqrf, potrf needs no workspace, so there is no lwork query and no per-thread work array. The SPD pool uses the cheap diagonally dominant A_ii = 2n form (SPD without an O(n^3) M^T M). The --size-sweep and --simdlen flags mirror bench_geqrf_compact. Wire it into CMakeLists.txt as the bench_potrf_compact target plus a small CTest integration run (33 1, exercising a padded final group). Document it in the README (Examples bullets/table, CTest list), flip the potrf benchmark note in PLANS.md from Deferred to Benchmarked, and add a section 9 (Benchmark) to the potrf design doc mirroring geqrf's. Verified: full ctest suite passes on both GCC and Clang (12/12), the accuracy gate holds at machine precision, and a -march=native run shows the expected story -- the compact path beats per-matrix LAPACK and is competitive with mkl_dpotrf_compact on the small-size range, LAPACK's blocked algorithm crossing ahead only at larger orders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKgcv8eoffP2gWrED44KqH
Per the project's convention to stop documenting benchmarks in the routine design documents, consolidate all benchmark documentation into a single examples/BENCHMARKS.md next to the programs it describes. - Add examples/BENCHMARKS.md documenting all three benchmarks (bench_geqrf_compact, bench_potrf_compact, bench_qr_compact): what each measures, the three-way comparison, how to run them, the -march=native fairness caveat, the OpenMP outer loop, the optional --size-sweep/--simdlen flags, how to read the output, and the CTest integration gating. - Remove the "9. Benchmark" section from both the geqrf and potrf design docs (it was the last section in each), replacing it with a one-line pointer to examples/BENCHMARKS.md. - Fix every stale "section 9" cross-reference: the two benchmark source-file header comments, both PLANS.md "Benchmarked" bullets, and the CMakeLists.txt target comments now point to examples/BENCHMARKS.md. - Link the new doc from the root README's Examples section. No functional change: the benchmarks build and their CTest integration runs still pass on GCC (bench_qr/geqrf/potrf_compact_integration, 3/3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKgcv8eoffP2gWrED44KqH
Address review feedback on the benchmark work: - Deduplicate the two compact-format helpers that were copied across the benchmark files. compact_format_name (3 copies) and format_for_vlen (2 copies) now live once in cqr::detail (cqr_mkl_ext.h), next to their sibling vlen_for_format; the benchmarks pull them in with using-declarations. format_for_vlen is now the type-correct inverse of vlen_for_format (templated on the scalar type, keyed on v*sizeof(T) register bytes) instead of a double-only mapping; call sites pass <double>. Behavior is unchanged for the double benchmarks. - Drop the two "documented in examples/BENCHMARKS.md" pointer lines from the geqrf and potrf design docs, per the convention to keep benchmark docs out of the design documents entirely. - Trim examples/BENCHMARKS.md (148 -> 108 lines): fold the per-benchmark three-way lists into the overview table, state the shared "pack once, time only the factorization" methodology once, and drop the standalone Threading section. Verified: full ctest passes on both GCC and Clang (12/12), including the three benchmark integration runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKgcv8eoffP2gWrED44KqH
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.
Summary
This PR adds a comprehensive throughput benchmark for the batched Cholesky factorization (
cqr_mkl_dpotrf_compact), mirroring the existing QR factorization benchmark (bench_geqrf_compact). The benchmark compares three implementations: the project's compact SIMD kernel, Intel MKL's compact kernel, and conventional per-matrix LAPACK, over pools of small symmetric positive-definite (SPD) matrices.Key Changes
New benchmark executable (
bench_potrf_compact):A = L L^T)cqr_mkl_dpotrf_compactvsmkl_dpotrf_compactvs per-matrixLAPACKE_dpotrfBenchmark features:
--size-sweep=nmin:nmax[:stride]for cqr-only throughput scans--simdlen=2|4|8to force narrower interleave widths than the host defaultIntegration testing:
bench_potrf_compact_integration) with 33 matrices and 1 repBuild integration:
cqr_mkl_extandMKL::CompactDocumentation:
Implementation Details
A_ii = 2n) rather than expensiveM^T Mproductsgeqrf,potrfrequires no workspace, so no per-thread work arrays are neededstd::chrono::steady_clockwith best-of-multiple-passes methodologyhttps://claude.ai/code/session_01GKgcv8eoffP2gWrED44KqH