Enable fused 1-NN for small dim on consumer Blackwell (sm_120) - #2382
Draft
maxwbuckley wants to merge 1 commit into
Draft
Enable fused 1-NN for small dim on consumer Blackwell (sm_120)#2382maxwbuckley wants to merge 1 commit into
maxwbuckley wants to merge 1 commit into
Conversation
use_fused() selected the unfused split GEMM/reduction path for all prop.major >= 10. That predicate covers both datacenter Blackwell (sm_100/103, major 10) and consumer Blackwell (sm_120/121, major 12), which differ in shared memory per SM and tensor core generation. On sm_120 the fused kernel still wins for small dim, where the unfused path's m x n distance matrix costs more memory traffic than the GEMM costs arithmetic. Measured on RTX 5090 against the batched unfused path, fused is 1.13-1.34x faster for k <= 16 at n >= 1024 and 1.09-1.32x for k <= 8 at n = 256, and 0.77-0.97x slower from k = 20 upward. Datacenter Blackwell behaviour is unchanged; that branch was not measured. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Enable the fused 1-NN kernel for small
dimon consumer Blackwell (sm_120)Problem
use_fused()incpp/src/cluster/detail/kmeans_common.cuhselects the unfusedsplit GEMM/reduction path for
prop.major >= 10:That predicate covers two different machines:
prop.majorThe rule was introduced in #1768 along with the unfused path, benchmarked on
IVF-PQ. On sm_120 it is too broad: the fused kernel still wins for small
dim,where the unfused path's
m x ndistance matrix costs more memory traffic thanthe GEMM costs arithmetic.
This matters for a real workload. IVF-PQ trains its PQ codebooks by running
kmeans_balancedonpq_len-dimensional subspaces withpq_book_sizeclusters(
ivf_pq_build.cuh:407), andpq_len = dim / pq_dimis typically 4-8 — squarelyin the regime where the gate currently picks the slower path.
Change
Split
sm_120/121out of themajor >= 10branch and enable fused for smalldimthere.sm_100/103behaviour is unchanged — see Caveats.Measurements
RTX 5090 (sm_120), CUDA 12.9. Fused vs. the current batched unfused path (post
#2346), interleaved A/B, 40 reps, medians, dedicated GPU. Speedup > 1 means fused
is faster. All entries significant at |Welch t| > 3 unless noted.
m ∈ {200K, 1M, 4M}; ranges span m. The crossover is sharp between dim 16 and 20.
At n=256 the gain is gone by dim 16, hence the
n >= 512 || k <= 8condition.Above dim 20 the existing rule is correct and is left alone — fused degrades to
0.22-0.30x by dim 512, which is what #1768 measured.
End-to-end effect is small
Being upfront: the primitive-level win does not translate into a large
IVF-PQ build speedup, because PQ codebook training is only a modest share of
build time.
ivf_pq::build, N=1M, dim=128, n_lists=1024, interleaved A/B,30 reps:
The effect appears only once
pq_dimis large enough that codebook training is ameaningful fraction of the build. So this is a small, no-regression improvement
rather than a headline one — it is worth taking because the dispatch is free, not
because it transforms build times.
Correctness
Labels differ from the unfused path at very small dim (up to 25% of rows at
dim=2, n=4096). These are ties, not errors: the achieved objective (total
min-distance) agrees to 5.3e-4 relative with sign-varying difference, so neither
path finds systematically worse minima. The per-row gaps are the cancellation
error of expanded-L2 under TF32 when
||x||^2is large relative to the distance,which affects both paths equally.
Caveats
conclusion to datacenter Blackwell without data would repeat the overreach this
PR is fixing, so that branch is untouched. If someone can run the same sweep on
B200, the same treatment may well apply there.
minClusterDistanceCompute(thedistance-only variant used by k-means++ init) calls
fusedDistanceNNMinReducewith no
use_fused()gate at all. So on Blackwell, k-means++ init already runsthe fused kernel while the Lloyd loop refuses to. That asymmetry looks
unintentional — happy to file it separately.
Reproducing
Benchmark harness used for the table is
bench_fused_vs_unfused.cu(not includedin this PR); it calls
fusedDistanceNNMinReduceandunfusedDistanceNNMinReducedirectly at the shapes
minClusterAndDistanceComputeuses.