A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 6, 02:00 UTC
nano_nemotron_vl: suppress readonly torch.from_numpy() warning in image and video resize paths (#37903)
Signed-off-by: Netanel Haber <58652339+netanel-haber@users.noreply.github.com>
Netanel Haber committed
Mar 25, 2026 at 01:25 UTC
a0d487b2e1d56a3e5e0fcdf7026d24282f20f13f
1 file changed
+32
-44
vllm/transformers_utils/processors/nano_nemotron_vl.py
+32
-44
@@ -8,6 +8,7 @@
8
# --------------------------------------------------------
9
10
import math
11
+import warnings
12
from abc import ABC, abstractmethod
13
from collections.abc import Sequence
14
from dataclasses import dataclass
@@ -66,6 +67,30 @@ def input_conditioner(x: torch.Tensor, norm_mean: torch.Tensor, norm_std: torch.
67
return (x - norm_mean) / norm_std
68
69
70
+def _bicubic_from_ndarray(
71
+ array: npt.NDArray[Any], *, size: tuple[int, int]
72
+) -> torch.Tensor:
73
+ """
74
+ Convert a 4D NHWC ndarray to NCHW and interpolate with bicubic.
75
+ Suppresses PyTorch's non-writable NumPy warning because interpolate copies,
76
+ and torch.from_numpy(array) is discarded at the end of function scope.
77
+ """
78
+
79
+ with warnings.catch_warnings():
80
+ msg = "The given NumPy array is not writ.*"
81
+ # Apparently, different versions of PyTorch use writable or writeable.
82
+ warnings.filterwarnings("ignore", message=msg, category=UserWarning)
83
+ tensor = torch.from_numpy(array)
84
+ assert tensor.ndim == 4, f"{tensor.ndim=}"
85
+ tensor = tensor.permute(0, 3, 1, 2)
86
+ return (
87
+ torch.nn.functional.interpolate(
88
+ tensor, size=size, mode="bicubic", align_corners=False, antialias=True
89
+ )
90
+ / 255.0
91
+ )
92
+
93
+
94
def dynamic_preprocess(
95
image,
96
*,
@@ -90,36 +115,19 @@ def dynamic_preprocess(
115
image.convert("RGB") if image.mode != "RGB" else image, dtype=np.uint8
116
)
117
93
- image = torch.from_numpy(image).unsqueeze(0) # (1, H, W, 3)
94
- image = image.permute(0, 3, 1, 2) # (1, 3, H, W)
118
+ image = np.expand_dims(image, axis=0)
119
96
- resized_img = torch.nn.functional.interpolate(
97
- image,
98
- size=(target_height, target_width),
99
- mode="bicubic",
100
- align_corners=False,
101
- antialias=True,
102
- )
120
+ resized_img = _bicubic_from_ndarray(image, size=(target_height, target_width))
121
B, C, H, W = resized_img.shape
122
hp, wp = H // image_size, W // image_size
123
patches = (
124
resized_img.reshape(B, C, hp, image_size, wp, image_size)
125
.permute(0, 2, 4, 1, 3, 5)
126
.reshape(B * hp * wp, C, image_size, image_size)
109
- / 255.0
127
)
128
129
if use_thumbnail and patches.shape[0] > 1:
113
- thumb = (
114
- torch.nn.functional.interpolate(
115
- image,
116
- size=(image_size, image_size),
117
- mode="bicubic",
118
- align_corners=False,
119
- antialias=True,
120
- )
121
- / 255.0
122
- )
130
+ thumb = _bicubic_from_ndarray(image, size=(image_size, image_size))
131
patches = torch.cat([patches, thumb], dim=0)
132
133
return list(patches)
@@ -241,21 +249,9 @@ def video_to_pixel_values(
249
downsample_ratio=downsample_ratio,
250
)
251
if video_tensor.shape[2] != target_h or video_tensor.shape[3] != target_w:
244
- video_tensor = torch.nn.functional.interpolate(
245
- video_tensor,
246
- size=(target_h, target_w),
247
- mode="bicubic",
248
- align_corners=False,
249
- antialias=True,
250
- )
252
+ return _bicubic_from_ndarray(video, size=(target_h, target_w))
253
elif video_tensor.shape[2] != input_size or video_tensor.shape[3] != input_size:
252
- video_tensor = torch.nn.functional.interpolate(
253
- video_tensor,
254
- size=(input_size, input_size),
255
- mode="bicubic",
256
- align_corners=False,
257
- antialias=True,
258
- )
254
+ return _bicubic_from_ndarray(video, size=(input_size, input_size))
255
256
video_tensor = video_tensor / 255.0
257
@@ -385,16 +381,8 @@ class DynamicResolutionImageTiler:
381
params.media.convert("RGB") if params.media.mode != "RGB" else params.media,
382
dtype=np.uint8,
383
)
388
- resized_img = (
389
- torch.nn.functional.interpolate(
390
- torch.from_numpy(image).unsqueeze(0).permute(0, 3, 1, 2),
391
- size=target_size,
392
- mode="bicubic",
393
- align_corners=False,
394
- antialias=True,
395
- )
396
- / 255.0
397
- )
384
+ image = np.expand_dims(image, axis=0)
385
+ resized_img = _bicubic_from_ndarray(image, size=target_size)
386
return list(resized_img)
387
388
def process_media(