Skip to content

Evaluate lane-pair nested-scale broadcast in CUDA SIMT 4-bit GEMM #13

Description

@heiheiha798

Hypothesis

The CUDA SIMT 4-bit GEMM currently reconstructs the same nested block scale twice for each adjacent lane pair when blocksize == 64.

Each lane handles 32 consecutive K values per outer iteration. With a 64-value quantization block, lanes (2i, 2i + 1) therefore use the same blk_idx. In the nested-statistics path, both lanes independently load the same uint8 scale index, codebook entry, second-level absmax, and offset. Params4bit and Linear4bit use blocksize 64 and compressed statistics by default, so this path is relevant to repeated small-M 4-bit inference.

This issue tracks a measurement-gated experiment. It does not assert a speedup in advance.

Proposed scope

  • Change only the CUDA branch of csrc/gemm_4bit_simt.cu.
  • For absmax_8bit != nullptr && blocksize == 64, let the even lane reconstruct scale_f and broadcast its exact float bits to the adjacent odd lane with a converged full-warp shuffle.
  • Keep every lane participating in the shuffle, including inactive lanes in the final K group.
  • Preserve the existing code verbatim for non-nested statistics, other blocksizes, and the preprocessor-separated HIP path.
  • Do not change the public API or ABI, quantization format, GEMM launch geometry, Python dispatch, SIMT-vs-MMA selection, or add architecture/shape-specific fallback rules.

The lane-pair invariant depends on the existing custom-op alignment requirement: inner_k = group * 1024 + lane * 32, and public dispatch rejects K values not divisible by blocksize.

Correctness gate

Build isolated baseline and candidate libraries from upstream/main commit 95f9af309d4d5793847169c39288dcd3fcbdf564 with identical settings. Record and assert the actual native library loaded by each benchmark/test process.

Require raw-bit equality of the complete baseline and candidate outputs for:

  • FP4 and NF4;
  • FP16, BF16, and FP32 inputs/outputs;
  • M = 1, 2, and 3, plus forced-SIMT M = 4 and 8 controls;
  • bias absent and present;
  • nested statistics with blocksize 64;
  • K = 64, 128, 960, 1024, 1088, 4096, 4160, and 11008;
  • N around partial output tiles (1, 3, 4, 63, 64, 65) and representative large dimensions.

Also verify that packed weights, activations, bias, nested indices/codebook/state2 absmax, and offset remain unchanged. Compare against the repository dequantize-plus-F.linear reference with existing tolerances, run the relevant gemm_4bit, matmul_4bit, compressed-statistics, bias, and offset-dtype tests, and repeat launches.

Run focused CUDA compute-sanitizer synccheck and racecheck cases. The structural requirement is that the full-mask shuffle is outside lane-active divergence and is reached by every lane in each live warp. Build the official CUDA 13 x64-compatible target list and compile the HIP path if the toolchain is available; disclose unavailable HIP validation rather than claiming it.

B300 benchmark gate

Use one B300/SM103 allocation with clean, isolated baseline and candidate builds. Primary deployed-code evidence must use the official CUDA 13 x64 target input 75;80;86;89;90;100;120; a native SM103 build may be reported only as a separately labeled corroborating control. Record the exact commit, resolved targets, loaded-library paths, node/GPU/driver/CUDA/PyTorch identities, commands, environment, job ID, and raw JSONL/log locations.

Interleave baseline and candidate with CUDA events, at least 20 warmups and at least seven timed batches with enough inner iterations for stable medians. Report every batch, median, p10, and p90.

Primary direct-op cells are nested blocksize-64 FP4/NF4 across FP16/BF16/FP32, M = 1/2/3, and realistic (N, K) families such as (4096,4096), (11008,4096), (4096,11008), (14336,4096), and (8192,8192), plus selected small/tail controls. Verify the SIMT implementation actually executes.

Controls must include non-nested blocksize 64, nested blocksize 128/256, and forced-SIMT M = 4/8. Measure a public bitsandbytes.matmul_4bit or Linear4bit forward path with default compressed statistics on realistic M = 1/2/3 shapes, excluding allocation and quantization from steady-state timing.

Proceed to a production change only if all correctness and sanitizer checks pass, at least two realistic direct nested blocksize-64 cells improve repeatably by at least 5% with dispersion below the effect, at least one realistic public-path cell improves repeatably by at least 3%, and no adjacent primary or source-equivalent control cell regresses materially (5% ceiling). Otherwise record a no-go without adding crossover heuristics, dispatch rules, prefetch changes, or a broader kernel rewrite.

Risks and non-goals

The duplicate reads may already coalesce or hit cache, while the shuffle adds an instruction and dependency. A no-gain outcome is plausible. The experiment must not be broadened to the HIP prefetch path, MMA kernels, blocksize-specific dispatch, other architectures, or the aborted multi-warp quantization work from issue #12.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions