Skip to content

Fix skipped workspace initialization for parallel split-K in GemmUniversalBase - #3578

Open
AyaanFaisal21 wants to merge 1 commit into
NVIDIA:mainfrom
AyaanFaisal21:fix/parallel-splitk-init-workspace
Open

Fix skipped workspace initialization for parallel split-K in GemmUniversalBase#3578
AyaanFaisal21 wants to merge 1 commit into
NVIDIA:mainfrom
AyaanFaisal21:fix/parallel-splitk-init-workspace

Conversation

@AyaanFaisal21

@AyaanFaisal21 AyaanFaisal21 commented Sep 1, 2026

Copy link
Copy Markdown

Problem

Fixes #3538.

Since 3.2, GemmUniversalBase::initialize() only calls Params::init_workspace() for kGemm, but GemmWithKReduction::Params::init_workspace() performs the parallel split-K pointer setup only for kGemmSplitKParallel. That makes the setup unreachable: partials are written through the user's ptr_D, causing OOB writes when grid.k > 1, while the reduction reads workspace that was never written.

The gate only appeared in the 3.2 squash commit; v2.11 and v3.1 called init_workspace() in every mode. Every kernel that customizes init_workspace() checks the mode inside its own implementation, so the unconditional call is the contract those implementations were written against.

Fix

Restore the unconditional init_workspace() call and move the mode check to ParamsBase's workspace memset. Only serial split-K needs that memset to zero its semaphore; parallel split-K fully overwrites its workspace before reduction.

This restores the required parallel setup while still skipping the pointless whole-buffer memset for parallel split-K, since it fully overwrites its workspace before reduction.

Testing

Example 23 (ampere_gemm_operand_reduction_fusion), SM86, CUDA 12.8, m=1024 n=1024 k=8192:

Before: plain and serial split-K pass; 8-slice parallel split-K miscompares, with compute-sanitizer reporting invalid 16-byte writes past D.

After: all three pass; compute-sanitizer reports 0 errors.

Serial split-K also exercises the re-gated semaphore memset and remains unchanged.


AI assistance was used during investigation and drafting. The proposed logic, code changes, and reported test results were reviewed and verified by the author.

…ersalBase

Fixes NVIDIA#3538. GemmUniversalBase::initialize() only calls
Params::init_workspace when mode == kGemm, while GemmWithKReduction's
init_workspace only acts when mode == kGemmSplitKParallel, so its ptr_D /
ptr_gemm_k_reduction redirect can never run: partials go through the
user's D buffer (out of bounds for grid.k > 1) and the reduction reads
uninitialized workspace.

Before 3.2 the call was unconditional (v2.11, v3.1), and the Python
cppgen backend still calls it unconditionally. Restore the unconditional
call and move the mode condition onto the one side effect it plausibly
guarded: the whole-workspace memset in ParamsBase, which only serial
split-K needs for semaphore zeroing.

Tested with example 23 on SM86 (m=1024 n=1024 k=8192, 8 slices): before,
parallel split-k miscompares and compute-sanitizer reports OOB 16-byte
global writes past D; after, plain, serial, and parallel all pass and
compute-sanitizer reports 0 errors. Serial split-K exercises the
re-gated memset path directly.

This change was developed with AI assistance; I have reviewed and
verified it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GemmWithKReduction parallel split-K: workspace initialization is skipped, partials land in the user output buffer

1 participant