diff --git a/deepinfer/model_executor/models/v4_modules/attn.py b/deepinfer/model_executor/models/v4_modules/attn.py index c14f88d..326a0d9 100644 --- a/deepinfer/model_executor/models/v4_modules/attn.py +++ b/deepinfer/model_executor/models/v4_modules/attn.py @@ -200,6 +200,23 @@ class V4AttentionBase(nn.Module): def _wv_and_o_proj(self, context: torch.Tensor | tuple[torch.Tensor, torch.Tensor], positions: torch.Tensor) -> torch.Tensor: if not self.use_fused_norm_rope_attn_rope_cast: self.rotary_emb(positions, context[..., -self.qk_rope_head_dim :], conjugate=True) + if ( + PLATFORM.is_neuron + and not isinstance(context, tuple) + and not self.use_fp8_einsum_output + and self.einsum_out_clamp_value is None + and nki_gemm.has_kernel(self.wv_weight) + ): + # The NKI kernel quantizes the bf16 context itself (1x32, as per_token_cast): no fp8 encode in the graph. + ctx = context.view(context.shape[0], self.n_wv_group, self.wv_group_dim) + wv = torch.stack([nki_gemm.linear_qdq(ctx[:, h], self.wv_weight, group=h) for h in range(self.n_wv_group)], dim=1) + out = self.out_proj(wv.flatten(1, 2)) + tp_group = getattr(self, "tp_group", None) + if tp_group is not None: + import torch.distributed._functional_collectives as funcol + + out = funcol.wait_tensor(funcol.all_reduce(out.float(), "sum", tp_group)).to(out.dtype) + return out if isinstance(context, tuple): context_fp8, context_sf = context gran = 32