Skip to content

feat(cuda): add resilient native and grouped GEMM dispatch - #1440

Open
ppodolsky wants to merge 8 commits into
tracel-ai:mainfrom
ppodolsky:feat/cublaslt-gemm-dispatch
Open

feat(cuda): add resilient native and grouped GEMM dispatch#1440
ppodolsky wants to merge 8 commits into
tracel-ai:mainfrom
ppodolsky:feat/cublaslt-gemm-dispatch

Conversation

@ppodolsky

@ppodolsky ppodolsky commented Jul 18, 2026

Copy link
Copy Markdown

Summary

This PR adds resilient native GEMM paths to CubeCL's CUDA runtime:

  • reclaim unused cached pages and retry once after BufferTooBig
  • add backend-optional single and grouped GEMM descriptors with capability flags
  • implement asynchronous BF16 GEMM with FP32 accumulation through cuBLASLt
  • implement heterogeneous grouped GEMM through cublasGemmGroupedBatchedEx on CUDA 12.5+
  • validate layouts, dimensions, batch strides, binding ranges, overlap, zero-K behavior, and stream ownership before launch
  • cache cuBLASLt descriptors and algorithms by shape, with separate workspaces per CUDA stream

The allocation retry was previously proposed separately in #1438. It is consolidated here so the CUDA accelerator integration has one review thread.

Behavior and compatibility

Both GEMM primitives are optional runtime capabilities. Their server trait methods have default fail-loud implementations, so other backends require no changes. Callers can independently inspect features.matmul.accelerated_gemm and features.matmul.accelerated_grouped_gemm before dispatch.

CUDA advertises single BF16 GEMM only on SM80+. Grouped BF16 GEMM additionally requires CUDA 12.5. The grouped descriptor supports independent M, N, K, transpose state, and binding offsets per problem. Host metadata uses a bounded pinned staging ring guarded by CUDA events, so repeated and multi-stream launches remain asynchronous without overwriting in-flight arguments.

The allocator cleanup path runs only after storage reports BufferTooBig. It rechecks the selected pool after cleanup before attempting one new device allocation.

Dependency validation

Validation

  • cargo fmt --all -- --check
  • allocator retry regression test
  • cargo check -p cubecl-runtime
  • cargo check -p cubecl-cuda --examples
  • A100 checks for padding, offsets, all transpose pairs, regular and broadcast batches, heterogeneous grouped shapes, repeated queued launches, asynchronous error propagation, and multi-stream ordering
  • downstream CUDA linear forward and dx/dW/db parity under fusion, autotune, and autodiff
  • 10,000 queued single GEMMs followed by one drain, confirming no per-call host synchronization

Performance

On an A100-SXM4 40GB, BF16 native single-GEMM dispatch beat or matched PyTorch matmul on 14 of 17 transformer-training shapes. A heterogeneous grouped expert projection measured 0.290 ms versus 0.438 ms for the prior padded batched path; activation time is excluded from both measurements.

@ppodolsky ppodolsky changed the title feat(cuda): add optional cuBLASLt GEMM dispatch feat(cuda): add resilient cuBLASLt GEMM dispatch Jul 18, 2026
@ppodolsky ppodolsky changed the title feat(cuda): add resilient cuBLASLt GEMM dispatch feat(cuda): add resilient native and grouped GEMM dispatch Jul 21, 2026
@ppodolsky
ppodolsky marked this pull request as ready for review July 21, 2026 13:04
@nathanielsimard

Copy link
Copy Markdown
Member

Agreed that grouped GEMM is a gap in the cubecl/cubek/burn stack. That said, our goal is to avoid depending on pre-built binaries like cuBLAS wherever we can.

To that end, we're working on a tile API that should simplify cross-platform compatibility, cover all dtypes including quantized tensors, and compose with Burn's automatic fusion (both on-read and on-write).

We're happy to keep this PR around as a baseline to benchmark other implementations against, but we're trying hard to avoid the combinatorial explosion of kernels per platform × dtype × fusion group.

cublasGemmEx with CUBLAS_GEMM_DEFAULT_TENSOR_OP leaves algorithm
selection to the legacy heuristic. cublasLt exposes the real heuristic
API, so each GEMM shape now gets a cached execution plan (descriptor,
layouts, and the heuristic-selected algorithm) plus a 32 MiB workspace
so split-K algorithms are eligible - the same machinery PyTorch's linear
uses. Workspaces are per CUDA stream since concurrent matmuls must not
share scratch. Shapes the heuristic rejects surface as validation
errors, which the autotune arbitration already treats as candidate
unavailable.
@ppodolsky
ppodolsky force-pushed the feat/cublaslt-gemm-dispatch branch from dd61293 to dcdb2b7 Compare August 1, 2026 07:45
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.

2 participants