Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions vllm/_xpu_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,37 @@ def _xpu_mxfp4_quantize_fake(
return x_q, x_s


def _xpu_fused_input_norm_impl(
x: torch.Tensor,
weight: torch.Tensor | None,
bias: torch.Tensor | None,
visual_dtype: torch.dtype,
) -> torch.Tensor:
patches, size = x.shape
out = torch.empty(
(patches, size),
dtype=visual_dtype,
device=x.device,
)
torch.ops._xpu_C.fused_input_norm(out, x.contiguous(), weight, bias)
return out


def _xpu_fused_input_norm_fake(
x: torch.Tensor,
weight: torch.Tensor | None,
bias: torch.Tensor | None,
visual_dtype: torch.dtype,
) -> torch.Tensor:
patches, size = x.shape
out = torch.empty(
(patches, size),
dtype=visual_dtype,
device=x.device,
)
return out


@triton.jit
def _softplus(x):
return tl.where(x <= 20.0, tl.math.log(tl.math.exp(x) + 1.0), x)
Expand Down Expand Up @@ -1287,6 +1318,12 @@ def register_ops_once() -> None:
fake_impl=_xpu_deepseek_fused_indexer_q_rope_mxfp4_fake,
)

direct_register_custom_op(
op_name="xpu_fused_input_norm",
op_func=_xpu_fused_input_norm_impl,
fake_impl=_xpu_fused_input_norm_fake,
)

_OPS_REGISTERED = True


Expand Down
14 changes: 14 additions & 0 deletions vllm/model_executor/models/vision.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,20 @@ def forward(
patches, size = grid_thw.shape
patch_size = size // self.channel

# On XPU, fuse the whole rescale + normalize into a single custom
# kernel. The eager path below materializes an fp32 intermediate and
# then casts back, which adds device-side compute that cancels the
# bandwidth saving of transferring uint8 pixel_values. The fused
# kernel reads uint8 directly and writes ``visual_dtype`` in one pass.
if (
current_platform.is_xpu()
and grid_thw.dtype == torch.uint8
and self.weight.dtype == torch.float32
):
return torch.ops.vllm.xpu_fused_input_norm(
grid_thw, self.weight, self.bias, visual_dtype
)

# Apply the per-channel affine transform directly instead of via
# F.batch_norm. batch_norm dispatches to cuDNN, whose batch-norm
# kernels cap the batch dimension near the CUDA grid limit (~65535);
Expand Down
Loading