@@ -44,6 +44,27 @@ def test_select_dsv4_ob_split_k_overrides(monkeypatch):
4444 _select_dsv4_ob_split_k (32 , configured_split = 3 )
4545
4646
47+ def test_dsv4_fused_oproj_is_enabled_by_default (monkeypatch ):
48+ module = SimpleNamespace (
49+ n_local_groups = 16 ,
50+ num_groups = 16 ,
51+ o_a_proj = torch .empty ((), device = "meta" , dtype = torch .float8_e4m3fn ),
52+ o_b_proj = SimpleNamespace (
53+ tp_size = 1 ,
54+ has_fp8_block_scales = True ,
55+ use_cute_dsl_blockscaling_mm = False ,
56+ ),
57+ )
58+ monkeypatch .setattr (attention_module , "IS_CUTLASS_DSL_AVAILABLE" , True )
59+ monkeypatch .setattr (attention_module , "is_sm_100f" , lambda : True )
60+ monkeypatch .delenv ("TRTLLM_DSV4_DISABLE_FUSED_OPROJ" , raising = False )
61+
62+ assert MLA ._should_use_fused_oproj (module )
63+
64+ monkeypatch .setenv ("TRTLLM_DSV4_DISABLE_FUSED_OPROJ" , "1" )
65+ assert not MLA ._should_use_fused_oproj (module )
66+
67+
4768def test_dsv4_fmha_epilogue_output_uses_fused_oproj ():
4869 attn_fp8 = torch .empty ((16 , 4 , 4096 ), device = "meta" , dtype = torch .float8_e4m3fn )
4970 attn_scale = torch .empty ((16 , 32 , 4 ), device = "meta" )
@@ -368,7 +389,7 @@ def calculate_reference_deepseek_v4_o_proj(
368389
369390def _build_dsv4_o_proj_case (num_tokens : int , dtype_str : str , device : torch .device ):
370391 """Build an MLA module, inputs, and reference-path tensors for the DeepSeek-V4
371- o_proj tests. Shared by the correctness test and the DSV4_FUSE_OPROJ fused
392+ o_proj tests. Shared by the correctness test and the default fused
372393 fp8-equivalence test so both exercise an identical setup.
373394
374395 Returns:
@@ -622,18 +643,16 @@ def test_deepseek_v4_o_proj(num_tokens: int, dtype_str: str):
622643@pytest .mark .skip_less_device_memory (80000 )
623644@pytest .mark .parametrize ("num_tokens" , [1 , 16 , 32 , 128 , 256 ])
624645def test_deepseek_v4_o_proj_fused_fp8_equivalence (num_tokens : int , monkeypatch ):
625- """The opt-in DSV4_FUSE_OPROJ fused fp8 epilogue must be numerically
626- equivalent to the default unfused path.
646+ """The default fused FP8 epilogue must match the disabled baseline.
627647
628- Fused (DSV4_FUSE_OPROJ=1 ): o_a's CuTe-DSL GEMM emits o_lora directly as fp8
648+ Fused (default ): o_a's CuTe-DSL GEMM emits o_lora directly as fp8
629649 e4m3 + packed-UE8M0 1x128 scale factors, fed straight to o_b.
630- Unfused (default): o_a emits bf16 o_lora, then ``o_b_proj`` runs the separate
631- 1x128 quant + DeepGEMM. Since the fusion only folds the *same* quant into o_a's
632- epilogue, the two production paths must match far tighter than the fp8-vs-bf16
633- reference bar.
650+ Disabled: o_a emits bf16 o_lora, then ``o_b_proj`` runs the separate 1x128
651+ quant + DeepGEMM. Since the fusion only folds the *same* quant into o_a's
652+ epilogue, the two paths must match far tighter than the fp8-vs-bf16 reference.
634653 """
635654 if get_sm_version () < 100 :
636- pytest .skip ("DSV4_FUSE_OPROJ fp8 fusion requires Blackwell (SM100+)" )
655+ pytest .skip ("fused DeepSeek-V4 FP8 O-projection requires Blackwell (SM100+)" )
637656
638657 device = torch .device ("cuda" )
639658 mla , attn_out_latent , position_ids , refs = _build_dsv4_o_proj_case (num_tokens , "fp8" , device )
@@ -645,12 +664,12 @@ def test_deepseek_v4_o_proj_fused_fp8_equivalence(num_tokens: int, monkeypatch):
645664 assert mla .o_b_proj .has_fp8_block_scales
646665 assert not getattr (mla .o_b_proj , "use_cute_dsl_blockscaling_mm" , False )
647666
648- # Unfused (default): DSV4_FUSE_OPROJ unset .
649- monkeypatch .delenv ( "DSV4_FUSE_OPROJ " , raising = False )
667+ # Explicit kill switch retains the unfused fallback .
668+ monkeypatch .setenv ( "TRTLLM_DSV4_DISABLE_FUSED_OPROJ " , "1" )
650669 out_unfused = mla ._deepseek_v4_o_proj (attn_out_latent .clone (), position_ids )
651670
652- # Fused: opt in .
653- monkeypatch .setenv ( "DSV4_FUSE_OPROJ " , "1" )
671+ # Unset is the production default and must take the fused path .
672+ monkeypatch .delenv ( "TRTLLM_DSV4_DISABLE_FUSED_OPROJ " , raising = False )
654673 mla .ob_split_k = 1
655674 out_fused = mla ._deepseek_v4_o_proj (attn_out_latent .clone (), position_ids )
656675
0 commit comments