Title: OutOfResources: shared memory (98304 > 65536) on Turing (SM75) — global attention layers with head_dim=512
Summary
I am unable to serve this checkpoint on NVIDIA Turing (compute capability 7.5) GPUs. vLLM fails during Triton JIT compilation of the unified attention kernel, requesting more shared memory per SM than Turing physically provides.
Environment
- GPUs: 2× NVIDIA Quadro RTX 6000 (Turing, SM75, 24 GB each, 64 KB shared memory per SM)
- vLLM: 0.26.0 (official Docker image)
- Parallelism: tensor-parallel-size 2,
NCCL_P2P_DISABLE=1(no NVLink, VMware passthrough) - Model:
google/gemma-4-31B-it-qat-w4a16-ct - Deployment: offline / air-gapped
Error
triton.runtime.errors.OutOfResources: out of resource: shared memory,
Required: 98304, Hardware limit: 65536.
Reducing block sizes or `num_stages` may help.
Analysis
At startup, vLLM logs the Gemma 4 attention configuration:
head_dim=256, global_head_dim=512
Gemma 4 interleaves local sliding-window attention layers (head_dim=256) with full global attention layers (global_head_dim=512).
In vllm/v1/attention/ops/triton_unified_attention.py, the kernel launch parameters are computed as:
head_size = q.shape[2]
BLOCK_M = (
16 if num_queries_per_kv <= 16 else triton.next_power_of_2(num_queries_per_kv)
)
BLOCK_Q = BLOCK_M // num_queries_per_kv
launch_num_warps: int | None = None
launch_num_stages: int | None = None
tuned_large_head = (
head_size == 256
and max_seqlen_q > 1
and num_queries_per_kv <= 16
and current_platform.is_device_capability_family(100)
)
if tuned_large_head:
BLOCK_M = 32
BLOCK_Q = BLOCK_M // num_queries_per_kv
launch_num_warps = 8
launch_num_stages = 2
The reported shared-memory requirement matches the default path exactly:
BLOCK_M × head_size × 2 bytes (fp16) × 3 (Q/K/V) × num_stages
= 16 × 512 × 2 × 3 × 2
= 98304 bytes
This is precisely the number in the error message, and 1.5× Turing’s 65536-byte limit.
Two observations:
- The
tuned_large_headbranch matches onlyhead_size == 256, and is additionally gated oncurrent_platform.is_device_capability_family(100)(Blackwell). Thehead_size == 512global attention layers therefore receive no special handling on any platform, and on Turing this branch is dead code regardless. - I diffed the file between vLLM 0.26.0 and 0.30.0rc1 — this logic is byte-for-byte identical in both, so upgrading vLLM does not change this code path.
This is consistent with an earlier experiment: I manually changed launch_num_stages = 2 → 1 inside the if tuned_large_head: block and it had zero effect on the error — expected, since that block never executes on SM75.
Already attempted
- Alternative attention backends:
FLASHINFER,XFORMERS - Various
--block-sizevalues - Lowering
--max-num-batched-tokens --limit-mm-per-prompt(to disable image input)- Both
--tensor-parallel-size 1and2
None of these changed the outcome.
Proposed workaround
Forcing a single pipeline stage when the head size exceeds 256 brings the allocation to 16 × 512 × 2 × 3 × 1 = 49152 bytes, which fits within the Turing limit:
if launch_num_stages is None and head_size > 256:
launch_num_stages = 1
Placed immediately after the if tuned_large_head: block, this leaves all existing tuned paths untouched and only affects head sizes that currently have no handling at all.
Questions
- Are Turing (SM75) GPUs considered supported for this checkpoint, or for Gemma 4 on vLLM in general?
- Is there a supported configuration flag that avoids this, rather than patching the kernel source?
- If a kernel-level fix for
head_size > 256on pre-Ampere hardware would be welcome upstream, I’m happy to open a vLLM issue or PR with the above analysis.
Thanks in advance for any pointers.