perf(sparsecore): enable dense gather reduce for v6e via FP32 intermediate buffer - #3493
Open
prishajain1 wants to merge 10 commits into
Open
perf(sparsecore): enable dense gather reduce for v6e via FP32 intermediate buffer#3493prishajain1 wants to merge 10 commits into
prishajain1 wants to merge 10 commits into
Conversation
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
…cab logits sharded - Add SAMPLING_KEEP_SHARDED_LOGITS (default False) to allow optionally skipping the full-vocabulary all-gather before sampling. - Implement distributed top-k candidate sampling (_distributed_topk_sample): each TP shard extracts local top 128 candidates from its shard, gathers compact candidates across shards, and computes global top-64 and top-p filtering. - Guarantee exactness by detecting boundary tie overflows and safely falling back to full-vocabulary sampling. - Guard with USE_DISTRIBUTED_TOPK_SAMPLING (default False) and fallback on logprobs or unsupported top-k. - Preserve explicit unshard constraint when neither option is enabled to ensure zero regression for existing models. - Add unit tests verifying candidate merging, tie-preservation, and truncated tie detection. Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
Signed-off-by: Prisha Jain <prishajain@google.com>
prishajain1
force-pushed
the
gemma4_sparsecore_enablement
branch
2 times, most recently
from
August 31, 2026 10:10
8a0bd78 to
6e1f903
Compare
prishajain1
force-pushed
the
gemma4_sparsecore_enablement
branch
from
August 31, 2026 10:18
6e1f903 to
47463eb
Compare
…diate buffer Signed-off-by: Prisha Jain <prishajain@google.com>
prishajain1
force-pushed
the
gemma4_sparsecore_enablement
branch
from
August 31, 2026 10:27
47463eb to
b21969d
Compare
prishajain1
marked this pull request as ready for review
August 31, 2026 10:30
prishajain1
requested review from
QiliangCui,
a1yssan13,
bythew3i,
gpolovets1,
gxd3,
jrplatin,
kwang3939,
kyuyeunk,
lk-chen and
vipannalla
as code owners
August 31, 2026 10:30
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.
SparseCore Dense Gather Reduce for v6e
Tensor cores are primarily designed for regular matrix multiplication. Since gathering for each token by expert and subsequent multiplication with expert router weights can be an irregular operation, we leverage the dedicated SparseCore kernel for this. There already exists an implementation of this kernel which works for v7x, but not on v6e. This PR explains why it did not work on v6e, and implements the fix to enable SparseCore dense gather reduce on v6e.
Why did it work for v7x and not v6e?
On v7x (16 lanes):
Hence, we get 2 output rows for one SIMD step. These two output rows are stored as
bfloat16, and packed into a 32-bit unit:On v6e (8 lanes):
One SIMD step produces 1 output row. But when attempting to store that output directly as
bfloat16, 2 values are required to fill one 32-bit packed unit:The Fix
We allow storing the temporary SparseCore output as FP32 (packing = 1):
Why is this lossless?
There is no difference in the order of operations; both the reference and SparseCore paths perform FP32 accumulation before casting to
bfloat16:bfloat16output array.bfloat16output array.Benchmark Results
We tested on Gemma4 MoE model on v6e-8:
jit_dense_gather_reduceKernel Execution Time: 1.198 ms → 522 µs (56% reduction)Tests Added / Updated
test_output_block_packing_gateintests/kernels/dense_gather_reduce_test.py: Verifies thatv6e_bf16_topk8is enabled via the FP32 intermediate buffer.