[Core][Diffusion] Add a typed pre-D2H video media contract (#6615)

Signed-off-by: NancyFyong <NancyFyong@users.noreply.github.com>
Signed-off-by: Samit <285365963@qq.com>
Co-authored-by: NancyFyong <NancyFyong@users.noreply.github.com>
Co-authored-by: Samit <285365963@qq.com>
This commit is contained in:
authored and GitHub committed 2026-09-10 09:50:54 +00:00
1 parent 5b927b7ceb
commit a2486dd00b
31 files changed
+3054 -60

No files matched your search

+113 -1
View File
@@ -10,9 +10,19 @@ import torch
import vllm_omni.diffusion.worker.diffusion_model_runner as model_runner_module
from tests.helpers.mark import hardware_test
from vllm_omni.diffusion.data import DiffusionOutput
from vllm_omni.diffusion.data import DiffusionOutput, VideoOutputTransportConfig
from vllm_omni.diffusion.diffusion_kv.config import DiffusionKVCacheMode
from vllm_omni.diffusion.diffusion_kv.model_runner_backend import DiffusionKVModelRunnerBackend
from vllm_omni.diffusion.media import (
DiffusionMediaOutput,
VideoMediaOutput,
VideoTensorEncoding,
VideoTensorLayout,
VideoTensorSpec,
VideoValueRange,
)
from vllm_omni.diffusion.request import OmniDiffusionRequest
from vllm_omni.diffusion.sched.interface import CachedRequestData, DiffusionSchedulerOutput, NewRequestData
from vllm_omni.diffusion.worker.diffusion_model_runner import DiffusionModelRunner
from vllm_omni.diffusion.worker.request_batch import DiffusionRequestBatch, split_diffusion_output_by_request
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
@@ -144,6 +154,19 @@ def _make_request():
)
def _raw_video_media(batch_size: int = 1, tensor: torch.Tensor | None = None) -> DiffusionMediaOutput:
return DiffusionMediaOutput(
video=VideoMediaOutput(
tensor=tensor if tensor is not None else torch.randn(batch_size, 3, 2, 4, 5),
spec=VideoTensorSpec(
layout=VideoTensorLayout.BCTHW,
encoding=VideoTensorEncoding.NORMALIZED_FLOAT,
value_range=VideoValueRange.NEGATIVE_ONE_TO_ONE,
),
)
)
def _make_request_with_params(req_id: str, sampling_params):
return SimpleNamespace(
request_id=req_id,
@@ -214,6 +237,7 @@ def _make_runner(cache_backend, cache_backend_name: str, enable_cache_dit_summar
enable_cache_dit_summary=enable_cache_dit_summary,
parallel_config=SimpleNamespace(use_hsdp=False),
streaming_output=False,
video_output_transport=VideoOutputTransportConfig(),
)
runner.diffusion_kv_backend = DiffusionKVModelRunnerBackend(
vllm_config=runner.vllm_config,
@@ -546,6 +570,48 @@ def test_execute_stepwise_streaming_returns_chunks_at_boundaries(monkeypatch):
assert fourth.get_request_output("req").finished is True
@pytest.mark.core_model
@pytest.mark.cpu
def test_execute_stepwise_prepares_typed_media(monkeypatch):
runner = _make_runner(cache_backend=None, cache_backend_name=None)
runner.pipeline = _ChunkStepPipeline([DiffusionOutput(media=_raw_video_media())])
runner.od_config.streaming_output = True
runner.od_config.step_execution = True
runner.od_config.video_output_transport = VideoOutputTransportConfig(enable_device_postprocess=True)
req = OmniDiffusionRequest(
prompt="a prompt",
sampling_params=OmniDiffusionSamplingParams(num_inference_steps=4),
request_id="req",
)
monkeypatch.setattr(model_runner_module, "set_forward_context", _noop_forward_context)
monkeypatch.setattr(model_runner_module.current_omni_platform, "reset_peak_memory_stats", lambda: None)
monkeypatch.setattr(model_runner_module.current_omni_platform, "max_memory_reserved", lambda: 0)
monkeypatch.setattr(model_runner_module.current_omni_platform, "max_memory_allocated", lambda: 0)
scheduler_output = DiffusionSchedulerOutput(
step_id=0,
scheduled_new_reqs=[NewRequestData(request_id="req", req=req)],
scheduled_cached_reqs=CachedRequestData.make_empty(),
finished_req_ids=set(),
num_running_reqs=1,
num_waiting_reqs=0,
)
DiffusionModelRunner.execute_stepwise(runner, scheduler_output)
scheduler_output = DiffusionSchedulerOutput(
step_id=1,
scheduled_new_reqs=[],
scheduled_cached_reqs=CachedRequestData(request_ids=["req"]),
finished_req_ids=set(),
num_running_reqs=1,
num_waiting_reqs=0,
)
result = DiffusionModelRunner.execute_stepwise(runner, scheduler_output).get_request_output("req").result
assert result.media.prepared_for_transport is True
assert result.media.video.spec.encoding is VideoTensorEncoding.UINT8_FRAMES
@pytest.mark.core_model
@pytest.mark.cpu
def test_execute_stepwise_streaming_decodes_final_only_pipeline(monkeypatch):
@@ -819,6 +885,7 @@ def _make_batch_runner(pipeline):
cache_backend="none",
enable_cache_dit_summary=False,
parallel_config=SimpleNamespace(use_hsdp=False),
video_output_transport=VideoOutputTransportConfig(),
)
runner.kv_transfer_manager = SimpleNamespace(
receive_multi_kv_cache_distributed=lambda req, cfg_kv_collect_func=None, target_device=None: None,
@@ -938,6 +1005,21 @@ def test_execute_model_batch_uses_runner_output_helper(monkeypatch):
assert helper_calls == [(["req-0", "req-1"], ["a", "b"])]
@pytest.mark.core_model
@pytest.mark.cpu
def test_execute_model_batch_prepares_typed_media_before_return(monkeypatch):
monkeypatch.setattr(model_runner_module, "set_forward_context", _noop_forward_context)
monkeypatch.setattr(model_runner_module, "current_omni_platform", _fake_platform_for_peak_memory())
runner = _make_batch_runner(_BatchPipeline(outputs=[DiffusionOutput(media=_raw_video_media())]))
runner.od_config.video_output_transport = VideoOutputTransportConfig(enable_device_postprocess=True)
result = DiffusionModelRunner.execute_model_batch(runner, _make_scheduler_output(num_reqs=1), runner.od_config)
prepared = result.runner_outputs[0].result.media
assert prepared.prepared_for_transport is True
assert prepared.video.spec.encoding is VideoTensorEncoding.UINT8_FRAMES
@pytest.mark.core_model
@pytest.mark.cpu
def test_split_diffusion_output_by_request_slices_single_and_multi_request_outputs():
@@ -959,6 +1041,36 @@ def test_split_diffusion_output_by_request_slices_single_and_multi_request_outpu
assert single[0].output == ["img-0a", "img-0b"]
@pytest.mark.core_model
@pytest.mark.cpu
def test_split_diffusion_output_by_request_preserves_typed_media():
reqs = [_make_request(), _make_request()]
batch = DiffusionRequestBatch(requests=reqs)
source = torch.randn(4, 3, 2, 4, 5)
result = DiffusionOutput(media=_raw_video_media(tensor=source))
outputs = split_diffusion_output_by_request(result, batch, num_outputs_per_prompt=2)
assert [output.media.video.tensor.shape for output in outputs] == [
torch.Size([2, 3, 2, 4, 5]),
torch.Size([2, 3, 2, 4, 5]),
]
assert all(output.media.prepared_for_transport is False for output in outputs)
torch.testing.assert_close(outputs[0].media.video.tensor, source[:2])
torch.testing.assert_close(outputs[1].media.video.tensor, source[2:])
@pytest.mark.core_model
@pytest.mark.cpu
def test_split_diffusion_output_by_request_validates_media_batch_dimension():
reqs = [_make_request(), _make_request()]
batch = DiffusionRequestBatch(requests=reqs)
result = DiffusionOutput(media=_raw_video_media(batch_size=3))
with pytest.raises(ValueError, match=r"request_count \* num_outputs_per_prompt \(4\), got 3"):
split_diffusion_output_by_request(result, batch, num_outputs_per_prompt=2)
@pytest.mark.core_model
@pytest.mark.cpu
def test_split_diffusion_output_by_request_slices_tuple_outputs():