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
5 changes: 3 additions & 2 deletions python/sglang/multimodal_gen/configs/sample/zimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class ZImageTurboSamplingParams(SamplingParams):

num_frames: int = 1
negative_prompt: str = None
# height: int = 720
# width: int = 1280
# Z-Image officially recommends starting at 1024x1024
height: int = 1024
width: int = 1024
# fps: int = 24

guidance_scale: float = 0.0
Expand Down
23 changes: 18 additions & 5 deletions python/sglang/multimodal_gen/runtime/warmup_request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,28 @@ def _resolve_default_warmup_resolution(
*,
server_based_warmup: bool,
) -> tuple[int, int]:
"""returns a default resolution to warmup"""
if server_based_warmup:
return _resolve_representative_warmup_resolution(server_args, sampling_defaults)

"""Return the default warmup resolution.

Prefer the model's sampling-default resolution — the most likely real
request shape — so warmup specializes kernels for it. Server-based image
warmup used to shrink this to an area cap (``SERVER_WARMUP_IMAGE_MAX_AREA``,
768x768) to bound startup, but that left a residual first-request
cold-start when the real request is larger (e.g. 1024x1024 paid ~0.1s of
first-shape kernel autotuning, measured on H100).
"""
width = sampling_defaults.width
height = sampling_defaults.height
if width is not None and height is not None:
is_image_gen = server_args.pipeline_config.task_type.is_image_gen()
if (
width is not None
and height is not None
and (not server_based_warmup or is_image_gen)
):
Comment on lines +79 to +84

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The is_image_gen variable is evaluated unconditionally, even when server_based_warmup is False. When server_based_warmup is False, the condition not server_based_warmup is True, meaning is_image_gen is not needed to determine the outcome.\n\nEvaluating this unconditionally can lead to unnecessary attribute access and potential AttributeError or NoneType errors if server_args is mocked or partially initialized (e.g., in unit tests).\n\nWe can leverage Python's short-circuit evaluation to lazily evaluate is_image_gen only when server_based_warmup is True.

    if (\n        width is not None\n        and height is not None\n        and (not server_based_warmup or server_args.pipeline_config.task_type.is_image_gen())\n    ):
References
  1. Enforce defensive programming by ensuring appropriate guards exist before object property accesses, especially when inputs might be partially initialized or mocked in tests.

return width, height

if server_based_warmup:
return _resolve_representative_warmup_resolution(server_args, sampling_defaults)

supported_resolutions = sampling_defaults.supported_resolutions
if supported_resolutions:
return min(supported_resolutions, key=lambda size: size[0] * size[1])
Expand Down
10 changes: 5 additions & 5 deletions python/sglang/multimodal_gen/test/server/perf_baselines.json
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,10 @@
"ImageVAEEncodingStage": 0.01
},
"denoise_step_ms": {
"0": 16.21,
"1": 13.42,
"2": 17.64,
"3": 63.6
"0": 28.54,
"1": 12.61,
"2": 57.24,
"3": 64.49
},
"expected_e2e_ms": 434.57,
"expected_avg_denoise_ms": 39.98,
Expand Down Expand Up @@ -2101,7 +2101,7 @@
"3": 650.0,
"4": 271.46,
"5": 266.71,
"6": 232.55,
"6": 650.0,
"7": 270.08,
"8": 259.96
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,11 @@ def test_server_based_warmup_resolutions_keep_sampling_defaults_and_caps(self):
self.assertEqual(req.negative_prompt, "model default negative")
self.assertIs(req.do_classifier_free_guidance, True)

def test_server_based_warmup_uses_supported_resolution_within_budget(self):
def test_server_based_image_warmup_uses_model_default_over_supported(self):
"""Server-based image warmup uses the model's default resolution so it
warms up at the real inference shape (avoiding a residual
cudagraph/compile gap), rather than shrinking to the smallest supported
resolution within an area budget."""
server_args = MagicMock()
server_args.warmup_steps = 1
server_args.enable_cfg_parallel = False
Expand All @@ -344,9 +348,12 @@ def test_server_based_warmup_uses_supported_resolution_within_budget(self):
server_based_warmup=True,
)

self.assertEqual((reqs[0].width, reqs[0].height), (512, 512))
self.assertEqual((reqs[0].width, reqs[0].height), (1024, 1024))

def test_server_based_warmup_scales_large_image_default(self):
def test_server_based_image_warmup_uses_full_model_default(self):
"""Server-based image warmup keeps the model's full default resolution
instead of scaling down to a server-warmup area budget, so warmup hits
the real inference shape."""
server_args = MagicMock()
server_args.warmup_steps = 1
server_args.enable_cfg_parallel = False
Expand All @@ -370,9 +377,11 @@ def test_server_based_warmup_scales_large_image_default(self):
server_based_warmup=True,
)

self.assertEqual((reqs[0].width, reqs[0].height), (768, 768))
self.assertEqual((reqs[0].width, reqs[0].height), (1024, 1024))

def test_server_based_warmup_uses_diffusers_image_budget(self):
def test_server_based_image_warmup_diffusers_uses_model_default(self):
"""Even on the diffusers backend, server-based image warmup uses the
model default resolution rather than the diffusers image area budget."""
server_args = MagicMock()
server_args.warmup_steps = 1
server_args.enable_cfg_parallel = False
Expand All @@ -396,7 +405,7 @@ def test_server_based_warmup_uses_diffusers_image_budget(self):
server_based_warmup=True,
)

self.assertEqual((reqs[0].width, reqs[0].height), (512, 512))
self.assertEqual((reqs[0].width, reqs[0].height), (1024, 1024))

def test_server_based_warmup_keeps_video_warmup_lightweight(self):
server_args = MagicMock()
Expand Down
Loading