@@ -95,6 +95,37 @@ def test_head_dtype_equal_to_model_dtype_uses_quant_method(default_vllm_config):
9595 assert logits .dtype == torch .bfloat16
9696
9797
98+ @pytest .mark .skipif (
99+ not torch .cuda .is_available (),
100+ reason = "Exercises the torch.mm(out_dtype=...) device fast path, "
101+ "available on CUDA and ROCm." ,
102+ )
103+ def test_fp32_head_uses_mm_fast_path_on_device (default_vllm_config ):
104+ # On ROCm, current_platform.is_cuda() is False, so this previously fell
105+ # through to the cast path (F.linear) instead of torch.mm(out_dtype=...),
106+ # even though ROCm supports the out_dtype mm via its non-Lt GEMM path.
107+ from unittest import mock
108+
109+ vocab_size , hidden_size , num_tokens = 64 , 16 , 4
110+ lp = _build_processor (vocab_size )
111+ lp .head_dtype = torch .float32
112+
113+ hidden_states = torch .randn (
114+ num_tokens , hidden_size , dtype = torch .bfloat16 , device = "cuda"
115+ )
116+ weight = torch .randn (vocab_size , hidden_size , dtype = torch .bfloat16 , device = "cuda" )
117+
118+ with mock .patch (
119+ "vllm.model_executor.layers.logits_processor.F.linear"
120+ ) as linear_mock :
121+ logits = lp ._get_logits (hidden_states , _FakeLmHead (weight ), None )
122+
123+ linear_mock .assert_not_called ()
124+ assert logits .dtype == torch .float32
125+ expected = torch .nn .functional .linear (hidden_states .float (), weight .float ())
126+ torch .testing .assert_close (logits , expected )
127+
128+
98129def test_fp32_head_rejects_quantized_lm_head (default_vllm_config ):
99130 lp = _build_processor (64 )
100131 lp .head_dtype = torch .float32
0 commit comments