@@ -3995,7 +3995,11 @@ def previous_seq_slots_device():
39953995 self .previous_kv_lens_offsets_cuda *= 0
39963996
39973997 position_ids = self ._apply_position_id_offset (position_ids )
3998- if self .use_mrope and mrope_position_ids :
3998+ # Use the (3,1,N) MRoPE layout whenever the model declares MRoPE, even
3999+ # for text-only batches: keeping position_ids rank-consistent between
4000+ # warmup and serving keeps torch.compile guards stable, so piecewise
4001+ # CUDA graphs captured at warmup remain usable at runtime.
4002+ if self .use_mrope :
39994003 # Mixed batches may have only some requests with multimodal MRoPE
40004004 # data. Seed the full (3,1,N) buffer from scalar position_ids
40014005 # (text-only tokens get the same value on all 3 axes), then
@@ -4154,7 +4158,10 @@ def previous_seq_slots_device():
41544158 if attn_metadata .padded_num_tokens is not None :
41554159 self .input_ids_cuda [total_num_tokens :padded_num_tokens ].fill_ (0 )
41564160 virtual_num_tokens = padded_num_tokens
4157- if self .use_mrope and mrope_position_ids :
4161+ # Match the rank of the unpadded branch: MRoPE models always use
4162+ # the (3,1,N) layout (see the seeding block above), so the padded
4163+ # view must stay 3D as well to keep torch.compile guards stable.
4164+ if self .use_mrope :
41584165 # Zero-fill padding on dim 2 (token dim) of (3,1,N) buffer.
41594166 self .mrope_position_ids_cuda [:, :, total_num_tokens :
41604167 padded_num_tokens ].fill_ (0 )
0 commit comments