@@ -2033,9 +2033,12 @@ def _validate_dsv4_epilogue_buffers(
20332033 return fp8_o , output_sf
20342034
20352035 def _should_use_fused_oproj (self ) -> bool :
2036- return (os .environ .get ("DSV4_FUSE_OPROJ" , "0" ) == "1"
2036+ # Eligible Blackwell paths are on by default; keep an emergency fallback.
2037+ return (not _is_env_truthy ("TRTLLM_DSV4_DISABLE_FUSED_OPROJ" )
2038+ and is_sm_100f () and IS_CUTLASS_DSL_AVAILABLE
20372039 and self .n_local_groups == self .num_groups
20382040 and getattr (self .o_b_proj , "tp_size" , 1 ) == 1
2041+ and self .o_a_proj .dtype == torch .float8_e4m3fn
20392042 and self .o_b_proj .has_fp8_block_scales and not getattr (
20402043 self .o_b_proj , "use_cute_dsl_blockscaling_mm" , False ))
20412044
@@ -2073,16 +2076,22 @@ def _fused_ob_gemm(self, o_lora_fp8: torch.Tensor, sf_out: torch.Tensor,
20732076 SK = _select_dsv4_ob_split_k (M , getattr (self , "ob_split_k" , None ))
20742077 packed_k = K_ob // _DSV4_OB_PACKED_SCALE_K
20752078 # CuTe specializes the DSV4-Pro O_b shape.
2076- can_try_cute = (IS_CUTLASS_DSL_AVAILABLE and M > 0
2077- and (M >= _DSV4_OB_CUTE_SK1_MIN_M or SK > 1 )
2078- and N == _DSV4_PRO_OB_N and K_ob == _DSV4_PRO_OB_K
2079- and K_ob % (_DSV4_OB_PACKED_SCALE_K * SK ) == 0
2080- and sf_out .dtype == torch .int32 and sf_out .dim () == 2
2081- and sf_out .shape == (M , packed_k )
2082- and sf_out .stride (0 ) == 1 and sf_out .stride (1 ) >= M
2083- and sf_out .stride (1 ) % _UE8M0_SCALES_PER_WORD == 0 )
2079+ use_cute_tactic = (IS_CUTLASS_DSL_AVAILABLE and M > 0
2080+ and (M >= _DSV4_OB_CUTE_SK1_MIN_M or SK > 1 )
2081+ and N == _DSV4_PRO_OB_N and K_ob == _DSV4_PRO_OB_K
2082+ and K_ob % (_DSV4_OB_PACKED_SCALE_K * SK ) == 0 )
2083+ activation_layout_ok = (sf_out .dtype == torch .int32
2084+ and sf_out .dim () == 2
2085+ and sf_out .shape == (M , packed_k )
2086+ and sf_out .stride (0 ) == 1
2087+ and sf_out .stride (1 ) >= M and
2088+ sf_out .stride (1 ) % _UE8M0_SCALES_PER_WORD == 0 )
2089+ if use_cute_tactic and not activation_layout_ok :
2090+ raise RuntimeError (
2091+ "DSV4-Pro O_b CuTe tactic requires packed activation scales." )
2092+
20842093 cute_wsf = wsf
2085- if can_try_cute and cute_wsf .dtype != torch .int32 :
2094+ if use_cute_tactic and cute_wsf .dtype != torch .int32 :
20862095 from tensorrt_llm .quantization .utils .fp8_utils import \
20872096 transform_sf_into_required_layout
20882097 cute_wsf = getattr (self .o_b_proj , "_ob_wsf_int" , None )
@@ -2100,12 +2109,17 @@ def _fused_ob_gemm(self, o_lora_fp8: torch.Tensor, sf_out: torch.Tensor,
21002109 is_sfa = False )
21012110 self .o_b_proj ._ob_wsf_int = cute_wsf
21022111
2103- can_use_cute = (can_try_cute and cute_wsf .dtype == torch .int32
2104- and cute_wsf .dim () == 2
2105- and cute_wsf .shape == (N , packed_k )
2106- and cute_wsf .stride (0 ) == 1 and cute_wsf .stride (1 ) == N )
2107- if not can_use_cute :
2108- # Keep DeepGEMM for unsupported shapes and layouts.
2112+ weight_layout_ok = (cute_wsf .dtype == torch .int32
2113+ and cute_wsf .dim () == 2
2114+ and cute_wsf .shape == (N , packed_k )
2115+ and cute_wsf .stride (0 ) == 1
2116+ and cute_wsf .stride (1 ) == N )
2117+ if use_cute_tactic and not weight_layout_ok :
2118+ raise RuntimeError (
2119+ "DSV4-Pro O_b CuTe tactic requires packed weight scales." )
2120+
2121+ if not use_cute_tactic :
2122+ # Keep DeepGEMM for shapes outside the tuned CuTe buckets.
21092123 hidden = torch .empty ([M , N ],
21102124 device = o_lora_fp8 .device ,
21112125 dtype = self .dtype )
0 commit comments