Skip to content
Draft
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
22 changes: 22 additions & 0 deletions tests/models/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,34 @@
from vllm.model_executor.models.utils import (
AutoWeightsLoader,
_merge_multimodal_embeddings,
get_padded_num_video_frames,
)
from vllm.platforms import current_platform

DEVICE_TYPE = current_platform.device_type


@pytest.mark.cpu_test
@pytest.mark.parametrize(
("num_frames", "temporal_patch_size", "expected"),
[
(1, 2, 2),
(16, 4, 16),
(17, 4, 20),
(18, 4, 20),
(19, 4, 20),
(20, 4, 20),
(16.5, 4, 20),
],
)
def test_get_padded_num_video_frames(
num_frames: int | float, temporal_patch_size: int, expected: int
):
padded_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)
assert padded_frames == expected
assert isinstance(padded_frames, int)


class ModuleWithBatchNorm(torch.nn.Module):
def __init__(self):
super().__init__()
Expand Down
7 changes: 4 additions & 3 deletions vllm/model_executor/models/glm4_1v.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
from .utils import (
AutoWeightsLoader,
WeightsMapper,
get_padded_num_video_frames,
init_vllm_registered_model,
maybe_prefix,
)
Expand Down Expand Up @@ -1082,9 +1083,9 @@ def _get_vision_info(
else:
preprocessed_size = ImageSize(width=image_width, height=image_height)

# NOTE: Frames are padded to be divisible by `temporal_patch_size`
# https://github.com/huggingface/transformers/blob/v4.48.3/src/transformers/models/qwen2_vl/image_processing_qwen2_vl.py#L294
padded_num_frames = num_frames + num_frames % temporal_patch_size
# NOTE: Frames are padded to be divisible by `temporal_patch_size`.
# https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/models/qwen2_vl/video_processing_qwen2_vl.py#L249-L252
padded_num_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)

grid_t = max(padded_num_frames // temporal_patch_size, 1)
grid_h = preprocessed_size.height // patch_size
Expand Down
13 changes: 9 additions & 4 deletions vllm/model_executor/models/kanana_v.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@

from .interfaces import MultiModalEmbeddings, SupportsMultiModal, SupportsPP
from .qwen2_vl import Qwen2VisionTransformer
from .utils import AutoWeightsLoader, init_vllm_registered_model, maybe_prefix
from .utils import (
AutoWeightsLoader,
get_padded_num_video_frames,
init_vllm_registered_model,
maybe_prefix,
)

logger = init_logger(__name__)

Expand Down Expand Up @@ -408,9 +413,9 @@ def _get_vision_info(
else:
preprocessed_size = ImageSize(width=image_width, height=image_height)

# NOTE: Frames are padded to be divisible by `temporal_patch_size`
# https://github.com/huggingface/transformers/blob/v4.48.3/src/transformers/models/qwen2_vl/image_processing_qwen2_vl.py#L294
padded_num_frames = num_frames + num_frames % temporal_patch_size
# NOTE: Frames are padded to be divisible by `temporal_patch_size`.
# https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/models/qwen2_vl/video_processing_qwen2_vl.py#L249-L252
padded_num_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)

grid_t = max(padded_num_frames // temporal_patch_size, 1)
grid_h = preprocessed_size.height // patch_size
Expand Down
3 changes: 2 additions & 1 deletion vllm/model_executor/models/keye.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
from .utils import (
AutoWeightsLoader,
WeightsMapper,
get_padded_num_video_frames,
init_vllm_registered_model,
maybe_prefix,
)
Expand Down Expand Up @@ -983,7 +984,7 @@ def _get_vision_info(
else:
preprocessed_size = ImageSize(width=image_width, height=image_height)

padded_num_frames = num_frames + num_frames % temporal_patch_size
padded_num_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)

grid_t = max(padded_num_frames // temporal_patch_size, 1)
grid_h = preprocessed_size.height // patch_size
Expand Down
3 changes: 2 additions & 1 deletion vllm/model_executor/models/llava_onevision2.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
from vllm.model_executor.models.utils import (
AutoWeightsLoader,
WeightsMapper,
get_padded_num_video_frames,
init_vllm_registered_model,
maybe_prefix,
)
Expand Down Expand Up @@ -1354,7 +1355,7 @@ def _get_vision_info(
preprocessed = ImageSize(width=rw, height=rh)
else:
preprocessed = ImageSize(width=image_width, height=image_height)
padded_frames = num_frames + num_frames % temporal_patch_size
padded_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)
grid_t = max(padded_frames // temporal_patch_size, 1)
grid_h = preprocessed.height // patch_size
grid_w = preprocessed.width // patch_size
Expand Down
12 changes: 10 additions & 2 deletions vllm/model_executor/models/mimo_v2_omni.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@
Qwen2_5_VLVideoPixelInputs,
)
from .qwen2_vl import _create_qwen2vl_field_factory
from .utils import AutoWeightsLoader, IntermediateTensors, WeightsMapper, maybe_prefix
from .utils import (
AutoWeightsLoader,
IntermediateTensors,
WeightsMapper,
get_padded_num_video_frames,
maybe_prefix,
)


class MiMoVisionMLP(Qwen2_5_VisionMLP):
Expand Down Expand Up @@ -715,7 +721,9 @@ def _get_vision_info(
effective_frames = num_frames * tokens_per_second
else:
effective_frames = num_frames
padded_num_frames = effective_frames + effective_frames % temporal_patch_size
padded_num_frames = get_padded_num_video_frames(
effective_frames, temporal_patch_size
)
grid_t = max(padded_num_frames // temporal_patch_size, 1)
grid_h = preprocessed_size.height // patch_size
grid_w = preprocessed_size.width // patch_size
Expand Down
7 changes: 4 additions & 3 deletions vllm/model_executor/models/qwen2_vl.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
from .utils import (
AutoWeightsLoader,
WeightsMapper,
get_padded_num_video_frames,
init_vllm_registered_model,
maybe_prefix,
)
Expand Down Expand Up @@ -897,9 +898,9 @@ def _get_vision_info(
else:
preprocessed_size = ImageSize(width=image_width, height=image_height)

# NOTE: Frames are padded to be divisible by `temporal_patch_size`
# https://github.com/huggingface/transformers/blob/v4.48.3/src/transformers/models/qwen2_vl/image_processing_qwen2_vl.py#L294
padded_num_frames = num_frames + num_frames % temporal_patch_size
# NOTE: Frames are padded to be divisible by `temporal_patch_size`.
# https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/models/qwen2_vl/video_processing_qwen2_vl.py#L249-L252
padded_num_frames = get_padded_num_video_frames(num_frames, temporal_patch_size)

grid_t = max(padded_num_frames // temporal_patch_size, 1)
grid_h = preprocessed_size.height // patch_size
Expand Down
9 changes: 8 additions & 1 deletion vllm/model_executor/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from vllm.model_executor.models.interfaces import supports_any_eagle
from vllm.multimodal import NestedTensors
from vllm.sequence import IntermediateTensors
from vllm.utils.math_utils import cdiv
from vllm.utils.math_utils import cdiv, round_up
from vllm.utils.torch_utils import (
async_tensor_h2d,
direct_register_custom_op,
Expand All @@ -40,6 +40,13 @@
ShardId: TypeAlias = str | int | tuple[int, ...]


def get_padded_num_video_frames(
num_frames: int | float, temporal_patch_size: int
) -> int:
"""Pad video frames to a multiple of the temporal patch size."""
return int(round_up(num_frames, temporal_patch_size))


@dataclass
class WeightsMapper:
"""Maps the name of each weight if they match the following patterns.
Expand Down
24 changes: 21 additions & 3 deletions vllm/utils/math_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Math utility functions for vLLM."""

from typing import overload

# Approximate value of 1/ln(2), used for log/exp base conversion
# Best FP32 approximation: 1.4426950216 (hex 0x3FB8AA3B)
RCP_LN2 = 1.4426950216


def cdiv(a: int, b: int) -> int:
@overload
def cdiv(a: int, b: int) -> int: ...


@overload
def cdiv(a: float, b: int) -> float: ...


def cdiv(a: int | float, b: int) -> int | float:
"""Ceiling division."""
return -(a // -b)

Expand All @@ -17,9 +27,17 @@ def next_power_of_2(n: int) -> int:
return 1 if n < 1 else 1 << (n - 1).bit_length()


def round_up(x: int, y: int) -> int:
@overload
def round_up(x: int, y: int) -> int: ...


@overload
def round_up(x: float, y: int) -> float: ...


def round_up(x: int | float, y: int) -> int | float:
"""Round up x to the nearest multiple of y."""
return ((x + y - 1) // y) * y
return cdiv(x, y) * y


def round_down(x: int, y: int) -> int:
Expand Down
Loading