Prototype: weighted-static partitioning for heterogeneous cores#941
Draft
jeffhammond wants to merge 1 commit into
Draft
Prototype: weighted-static partitioning for heterogeneous cores#941jeffhammond wants to merge 1 commit into
jeffhammond wants to merge 1 commit into
Conversation
On a heterogeneous machine (e.g. NVIDIA GB10's Cortex-X925 + Cortex-A725
clusters) a single level-3 op loses much of its throughput to barrier sync:
the equal static loop split gives every thread the same work, so the fast
cores idle at each pack/compute barrier waiting for the slow ones (all-20
DGEMM: ~380 vs ~890 GFLOP/s). This partitions the dense forward loop range
in proportion to each thread's core throughput instead of equally, so all
threads finish each phase together.
Hooked into the unweighted branch of bli_thread_range() (where trsm/syrk's
triangular weighting already lives). The weight is per datatype (measured
X925:A725 GEMM optima: s 4.2 d 3.6 c 4.0 z 4.4). Compile-gated by
BLIS_ENABLE_HETERO_SCHED; runtime-gated by env BLIS_HETERO_WEIGHT
("auto" = per-datatype table, a number = fixed weight, unset = disabled),
so default builds are unchanged. Measured ~2.2-2.5x over the equal split
across s/d/c/z; GEMM stays bit-correct (the split only chooses which rows a
thread owns).
PROTOTYPE limitations: assumes the loop work_id equals the logical CPU it
runs on (holds for a pinned 1D-IC layout) and hardcodes the GB10 X925 CPU
set. A production version should derive per-work_id core identity from
sched_getcpu() gathered through the thread communicator, so it holds for any
factorization and pinning.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jeffhammond
marked this pull request as draft
July 16, 2026 15:23
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.
On a heterogeneous machine (e.g. NVIDIA GB10's Cortex-X925 + Cortex-A725 clusters) a single level-3 op loses much of its throughput to barrier sync: the equal static loop split gives every thread the same work, so the fast cores idle at each pack/compute barrier waiting for the slow ones (all-20 DGEMM: ~380 vs ~890 GFLOP/s). This partitions the dense forward loop range in proportion to each thread's core throughput instead of equally, so all threads finish each phase together.
Hooked into the unweighted branch of bli_thread_range() (where trsm/syrk's triangular weighting already lives). The weight is per datatype (measured X925:A725 GEMM optima: s 4.2 d 3.6 c 4.0 z 4.4). Compile-gated by BLIS_ENABLE_HETERO_SCHED; runtime-gated by env BLIS_HETERO_WEIGHT ("auto" = per-datatype table, a number = fixed weight, unset = disabled), so default builds are unchanged. Measured ~2.2-2.5x over the equal split across s/d/c/z; GEMM stays bit-correct (the split only chooses which rows a thread owns).
PROTOTYPE limitations: assumes the loop work_id equals the logical CPU it runs on (holds for a pinned 1D-IC layout) and hardcodes the GB10 X925 CPU set. A production version should derive per-work_id core identity from sched_getcpu() gathered through the thread communicator, so it holds for any factorization and pinning.