Repository navigation
perf(tensilelite): overlap the benchmark helper compile with codegen and generate all steps of a config in one pool - #15286
Draft
Alex-Vasile wants to merge 1 commit into
Conversation
Alex-Vasile
force-pushed
the
users/alvasile/tl-speedup-36-benchmark-build-pipeline
branch
from
November 6, 2026 18:24
66dfff6 to
33c546a
Compare
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
…and generate all steps of a config in one pool writeSolutionsAndKernels becomes prepare / generate / finish: helper kernels are written first and compiled on a background thread while assembly kernels are generated, the kernels of all benchmark steps of a config are generated in one process pool (TensileBackend; Ductile stays per step), and the invalid-kernel check runs in the parent. One branch because the procs parameter the first commit adds to removeInvalidSolutionsAndKernels and the last one removes cannot exist on the final diff.
Alex-Vasile
force-pushed
the
users/alvasile/tl-speedup-36-benchmark-build-pipeline
branch
from
November 6, 2026 18:45
33c546a to
5f71aea
Compare
1 task done
This branch has not been deployed
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.
JIRA ID : AIHPBLAS-5256
Motivation
When TensileLite benchmarks a config (the path every common test and every tuning run takes), each benchmark step generates assembly kernels in a process pool, then assembles them, then compiles
Kernels.cpp, the C++ source of the step's helper kernels, with clang. That helper compile was 1,004.7 s, 39% of a gfx950 per-config build aggregate, and it started only after codegen and assembly, although its input is ready at the start. Each step also filled and drained its own pool, so configs of many small steps left most workers idle. A third cost: the invalid-kernel check ran in its own pool, which pickled every kernel's state to a worker and back for a one-attribute test.Technical Details
TensileCreateLibrary/Run.pyreplaceswriteSolutionsAndKernelswith 3 phases:prepareSolutionsAndKernels: setup, writeKernels.cpp/Kernels.h, and queue the helper compile onhelperCompileExecutor(), a 1-thread executor that compiles steps one at a time, in step order, so a later step still hits the helper cache.generateBenchmarkKernels: 1ParallelMap2pool over the kernels of any number of steps. Sources held across steps are compressed with the existingmemcompress.finishSolutionsAndKernels: invalid-kernel check, now a list comprehension in the parent, then assemble, link, and wait for the helper compile (timerpython_kernel_build_src_co_wait).benchmarkPoolSize()gives every pool of the run the CPU budget minus 1, reserving 1 slot for the compile; with a budget of 1 the compile finishes before codegen. One size per run avoids loky, joblib's process-pool backend, restarting workers when the pool size changes.BenchmarkProblems.py:mainprepares every step of a config, generates all their kernels in 1 pool, then finishes each step in config order as before (validate, assemble, library, client run, results). A step waits for the batch to finish first only when it reads what earlier steps write: the same cache directory, or a repeated problem-size group name. The Ductile backend, a search that reads each evaluation's results to pick the next candidates, keeps stepping one at a time through a newOptimizationBackend.uses_benchmark_results()(defaultTrue;TensileBackendreturnsFalse).scripts/analyze_timing.pyputs the wait in the timer tree and movespython_kernel_build_src_coto the overlapping totals so it is not double counted.New tests:
test_benchmark_helper_compile_overlap.pyandtest_benchmark_steps_one_pool.py(17 cases), plusTestHelperCompileOverlapintest_analyze_timing.py; 4 existing test files follow the new names.Test Plan
Run from
projects/hipblaslt/tensilelite:tox -e unit -- tensilelite/Tests/unit/test_benchmark_steps_one_pool.py tensilelite/Tests/unit/test_benchmark_helper_compile_overlap.py tensilelite/Tests/unit/test_benchmarkProblems_solution_pool.py tensilelite/Tests/unit/Ductile tensilelite/Tests/unit/test_codegen_worker_state.py tensilelite/Tests/unit/test_analyze_timing.py tensilelite/Tests/unit/characterization/TensileCreateLibraryRunchecks the phase order, overlap, wait rules, Ductile stepping, error handling and the timing report.tox -e py3 -- tensilelite/Tests -m common -k 'custom_mainloop_scheduling or spmm_i8_sb or dtl'on a gfx950 GPU builds and runs configs with many steps.pre-commit run --fileson the changed files checks formatting and lint.Test Result
Time saved: overlapping the helper compile cut build wall time by 12% on
fp16_tn, 6% onsubtile_mxfp4and 2% ondtl; one pool per config then cut it by a further 58% oncustom_mainloop_scheduling(72.3 to 30.0 s), 32% onsubtile_mxfp4, 23% onspmm_i8_sb, 18% onf8_gate_rand 8% ondtl. Each was measured on the original unsplit branch against the commit before it,--build-onlyon the gfx950 (MI355X) host, 24 cores reserved withtaskset(budget 24), cold helper cache, 2 runs per side. Moving the invalid-kernel check to the parent saved no wall time: CI-like gfx942 (MI300X) build stage, 25 cores,-n 4 --dist=worksteal, 441 s against 441.5 s, mean of 2 runs per side.The individual runs:
fp16_tn(3)custom_mainloop_scheduling(66)spmm_i8_sb(8)dtl(26)subtile_mxfp4(130)The table joins 2 separate before/after measurements, one per source commit. Where both measured the middle column, it shows the second; the first gave
dtl139.5, 139.6 s andsubtile_mxfp477.7, 78.5 s.__hip_cuid_*symbol in the helper code objects. Solution state after each step's build and every output file matched for 3 configs.dtl2.8 to 1.5 GB. All processes together:custom_mainloop_scheduling6.9 to 8.5 GB, because all workers generate at once.python_kernel_validate124.1 to 27.7 s summed over the 4 workers, while assembly time rose by 71.4 s. The unit suite there had the same 519 failures as its parent, intest_custom_kernel_staggeru_metadata.pyandtest_subtile_ds_read_emit.py.Not yet run on this branch. Automated GitHub checks are pending.
Related
Device / Architecture Coverage
This changes the benchmark kernel-build pipeline: order, concurrency and pool sizes; generated kernels and helper sources are unchanged. The overlay requires CI coverage of kernel-generation changes on the affected archs, gfx942 and gfx950 at least. An arch that is only built counts as uncovered.
Submission Checklist
Risk level
High (4/5): restructures the benchmark build used by every common test and tuning run. The order of work and log output changes. A helper-compile failure is raised when its step finishes, and an error in the shared pool now ends the run before earlier steps are built. The Tensile process holds every step's compressed sources until they finish. Coverage so far is from the original branch only.