Repository navigation
Score expanded-L2 brute-force tiles with RAFT's GEMM bias epilogue - #3049
Draft
tarang-jain wants to merge 7 commits into
Draft
tarang-jain wants to merge 7 commits into
tarang-jain wants to merge 7 commits into
Conversation
…or small indexes fusedL2Knn has no tensor-core path, so half inputs with k <= 64 now take tiled_brute_force_knn. Float stays on the fused kernel. When the whole index fits in one column tile, chooseTileSize now grows tileRows up to the existing memory target (capped at numQueries) instead of stopping at 512, so small indexes need fewer GEMM + select_k rounds. Large indexes are unchanged. The per-column-tile merge buffers are only allocated when tiling over columns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiled_brute_force_knn raises tile_cols to k after chooseTileSize, so with n < k the row tile sized against n made the distance buffer far larger than the memory target (n=10, k=1000, m=1e6: 4 GB). Pass max(n, k) as the column count so rows are sized against the actual tile width. Unchanged for k <= n. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For L2Expanded and L2SqrtExpanded over float or half rows (FP32 distances, no custom epilogue), each tile is now one cuBLASLt matmul that writes |x|^2 - 2 q.x directly: alpha = -2 scales the dot products and the bias epilogue adds the FP32 index norms. This replaces the inner-product GEMM plus the pass that turned every dot product into a distance. select_k ranks the scores as they are, since |q|^2 is constant along a row, and only the k kept per row get |q|^2 added, clamped and rooted as l2_exp_cutlass_op does. The matmul is planned per tile shape and per operand alignment (tiles start at arbitrary rows), cached through a custom resource, and falls back to the previous path if cuBLASLt has no algorithm for it. Float stays plain FP32 (no TF32); half runs on the tensor cores. H100, brute_force::search vs the parent commit: half 1.3-1.66x faster at 256-4096 queries over 8k-262k rows, float with k = 100 up to 1.28x, results identical up to ties. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
The tile's |x|^2 - 2 q.x now comes from raft::linalg::gemm (column-major: index * search^T, alpha = -2) with the index norms as its bias, which NVIDIA/raft#3205 adds. This drops l2_expanded_scores.cuh and its direct cuBLASLt calls, descriptor cache and alignment handling. Same arithmetic, tests and timings as before. Requires NVIDIA/raft#3205. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cuBLASLt runs slower kernels when the bias (the index norms at norms + j) or the rows of the distance tile aren't 16-byte aligned. When the index is split into column tiles, each tile now spans a multiple of 4 index rows, and precomputed index norms that aren't 16-byte aligned, such as a slice of a larger norm vector, are copied once per search into an aligned buffer. Co-Authored-By: Claude Opus 5.5 <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.
Note
raft::linalg::gemmthat this PR calls. CI fails until it is merged and in the RAFT nightlies.bf-half-tiled-knn, which touches onlyknn_brute_force.cuh.Description
For L2Expanded and L2SqrtExpanded,
tiled_brute_force_knncomputes each tile in two steps. An inner-product GEMM writesq.x, then amap_offsetpass reads and rewrites the whole tile to turn each value into|q|^2 + |x|^2 - 2 q.x. Only then doesselect_krun. This PR removes that pass:raft::linalg::gemmcall per tile writes|x|^2 - 2 q.xdirectly. The call computessearch * index^Twithalpha = -2. Its newbiasargument (Add an optional bias epilogue to raft::linalg::gemm raft#3205, cuBLASLt's bias epilogue) adds the FP32 index norms, one per index row, inside the GEMM.select_kranks those scores as they are, because|q|^2is the same along a row. Afterwards, only thekvalues kept per row get|q|^2added, clamped at 0 and square-rooted, the same arithmetic asl2_exp_cutlass_op.CUBLAS_COMPUTE_32F, no TF32). Half runs on the tensor cores with FP32 accumulation, as before.k). Precomputed index norms that aren't 16-byte aligned, such as a slice of a larger norm vector, are copied once per search into an aligned buffer. Add an optional bias epilogue to raft::linalg::gemm raft#3205 chooses the GEMM's algorithm for the bias's actual alignment, so a misaligned bias would still be correct, just slower.Benchmarks
brute_force::build+brute_force::searchwith L2Expanded on an H100 80GB HBM3. The baseline is #3041 (a3694728e) and the comparison is this branch. Both were built from source for sm_90, with this branch built against NVIDIA/raft#3205's headers. Shapes: half and float, dim 96 and 768, 1K–256K index rows, 16/256/4096 queries, k = 10 and 100. Each time is the mean over every timed call: 3 batches of equal length, about 300 ms each.fusedL2Knn.Alignment, same setup, half, k = 10. "Before" is this PR and NVIDIA/raft#3205 without their alignment commits:
Results match #3041: distances agree to within 2.2e-07 relative at every rank. Neighbor ids differ only between equal-distance ties; the lowest recall against #3041 is 0.99996.
Full table (96 shapes)
Testing
All of the following were built against NVIDIA/raft#3205's headers.
NEIGHBORS_ANN_BRUTE_FORCE_TEST: 78/78 pass.NEIGHBORS_TEST: 373/373 pass. This covers the prefiltered bitmap and bitset tests with k = 0, the half and float tests, and odd dims.pre-commit run --all-filespasses.🤖 Generated with Claude Code