Fix wan2.2 VBench accuracy pipeline: drain timeouts, .mp4 staging, torch>=2.6, wget preflight#401
Fix wan2.2 VBench accuracy pipeline: drain timeouts, .mp4 staging, torch>=2.6, wget preflight#401wu6u3tw wants to merge 3 commits into
Conversation
The benchmark session hard-coded a 240 s drain timeout after every phase. For slow generative workloads (e.g. wan2.2 text-to-video at ~2 min per sample on a single GPU), this silently abandoned every in-flight sample: a performance run could exit green with 0 samples completed (observed on GB300: 144 issued, 0 completed), and accuracy phases, which issue all samples up front, could never finish at all. Add settings.drain (DrainConfig) with per-phase timeouts: - warmup_timeout_s: 240 (raise when warmup requests take minutes each, so leftovers don't leak into the measured performance phase) - performance_timeout_s: 240 (unchanged default) - accuracy_timeout_s: None = wait for all responses, because abandoning in-flight accuracy samples silently invalidates the score PhaseConfig gains drain_timeout_s and the phase builder wires the config through. None waits indefinitely.
VBench's load_video dispatches purely on the file extension and raises NotImplementedError for anything but .mp4/.gif/frame dirs. trtllm-serve emits MJPEG .avi when ffmpeg is unavailable server-side, so a full accuracy run generated 248 videos and then failed at scoring. decord (libav) detects the real container by content, so an .avi symlinked under an .mp4 name decodes fine (verified on GB300: 81-frame 720x1280 MJPEG-AVI reads correctly). Always name the staged symlinks .mp4.
Two cold-start failures observed on aarch64 GB300 runs: - The accuracy venv resolves torch 2.12, where torch.load defaults to weights_only=True (since 2.6). VBench's reference checkpoints (motion_smoothness AMT, RAFT) are full pickles and fail with UnpicklingError. Default torch.load to weights_only=False in this subprocess only; explicit weights_only callers are unaffected. - vbench.utils.init_submodules downloads per-dimension weights via literal wget/unzip subprocesses; without them the run dies with an opaque FileNotFoundError after videos were already generated. Fail fast preflight with a structured error naming the missing tools.
|
MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅ |
There was a problem hiding this comment.
Code Review
This pull request introduces configurable per-phase drain timeouts to prevent slow generative workloads from timing out prematurely, patches torch.load to support older VBench reference checkpoints, and ensures staged videos are named with an .mp4 extension to satisfy VBench's loader. The review feedback is highly constructive: it suggests checking if the VBench cache is already populated before failing on missing system tools (wget/unzip), and points out a potential TypeError when formatting a None timeout in the drain exception handler.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| missing_tools = [t for t in ("wget", "unzip") if shutil.which(t) is None] | ||
| if missing_tools: |
There was a problem hiding this comment.
If the VBench cache directory (typically ~/.cache/vbench) is already pre-populated with the required model weights, wget and unzip are not needed. However, this preflight check unconditionally fails and blocks execution if either tool is missing, even if the cache is fully populated.
To support offline or air-gapped environments where the cache is pre-populated but these tools are not installed, we should check if the cache is already populated before failing.
from pathlib import Path
cache_dir = Path.home() / ".cache" / "vbench"
cache_populated = cache_dir.exists() and any(cache_dir.iterdir())
missing_tools = [t for t in ("wget", "unzip") if shutil.which(t) is None]
if missing_tools and not cache_populated:| except TimeoutError: | ||
| logger.error( | ||
| "Drain timed out after 240 s with %d responses still in flight; " | ||
| "Drain timed out after %.0f s with %d responses still in flight; " | ||
| "proceeding to next phase.", | ||
| timeout_s, | ||
| phase_issuer.inflight, | ||
| ) |
There was a problem hiding this comment.
If timeout_s is None (which is the default for accuracy phases), asyncio.wait_for will wait indefinitely and won't raise a TimeoutError. However, if a TimeoutError is raised from within the try block (e.g., propagated from another task or manually raised), formatting timeout_s with %.0f in the exception handler will raise a TypeError: must be real number, not NoneType.
To prevent the exception handler from crashing and masking the original error, we should format timeout_s safely.
| except TimeoutError: | |
| logger.error( | |
| "Drain timed out after 240 s with %d responses still in flight; " | |
| "Drain timed out after %.0f s with %d responses still in flight; " | |
| "proceeding to next phase.", | |
| timeout_s, | |
| phase_issuer.inflight, | |
| ) | |
| except TimeoutError: | |
| timeout_str = f"{timeout_s:.0f}" if timeout_s is not None else "infinite" | |
| logger.error( | |
| "Drain timed out after %s s with %d responses still in flight; " | |
| "proceeding to next phase.", | |
| timeout_str, | |
| phase_issuer.inflight, | |
| ) |
Fix wan2.2 VBench accuracy pipeline: configurable drain timeouts, .mp4 staging, torch>=2.6 and wget cold-start failures
Summary
Running the wan2.2 (
videogen) benchmark end to end on GB300-NVL72 (aarch64, SLURM/enroot) surfaced four independent client-side failures. Each one only manifests after a full generation pass (30-50 min on 18 nodes), and together they made VBench accuracy runs impossible to complete. This PR fixes all four, with regression tests for the two library-level changes.All fixes were validated on hardware: with them applied (initially as runtime monkeypatches), a full Offline run completed with 144/144 performance samples, a clean warmed-up perf phase, and a VBench score of 0.69998 over 248 samples.
Fix 1: configurable per-phase drain timeouts (
settings.drain)BenchmarkSession._drain_inflighthard-coded a 240 s wait for in-flight responses after every phase, then abandoned whatever was left and moved on.For workloads at minutes per sample this is fatal, and silently so:
min_durationwith every sample still in flight. Observed:Drain timed out after 240 s with 144 responses still in flightfollowed byTotal samples issued: 144 / Total samples completed: 0, and the run exits green.New
settings.drain(DrainConfig), wired throughPhaseConfig.drain_timeout_s:warmup_timeout_sperformance_timeout_saccuracy_timeout_sNone(wait for all)Nonewaits indefinitely. The only behavior change with default configs is the accuracy drain, which previously produced wrong results whenever it triggered.Example for slow generative workloads:
Fix 2: stage VBench videos as
.mp4regardless of source suffixVBenchScorer._stage_videoskept the source extension (src.suffix or '.mp4'). VBench'sload_videodispatches purely on the extension and raises bareNotImplementedErrorfor anything but.mp4/.gif/frame dirs. trtllm-serve emits MJPEG.aviwhen ffmpeg is not installed server-side, so a full accuracy pass generated all 248 videos and then died at scoring.decord (libav) detects the container by content, not extension; an MJPEG-AVI symlinked under an
.mp4name decodes correctly (verified on GB300: 81 frames, 720x1280). Staged symlinks are now always named{prompt}-{idx}.mp4.Fix 3:
vbench_runner.pyfails on torch >= 2.6 checkpoint loadingThe wan2.2 accuracy subproject resolves torch 2.12, where
torch.loaddefaults toweights_only=True(changed in 2.6). VBench's reference checkpoints (motion_smoothness AMT, RAFT) are full pickles and fail withUnpicklingError. The runner now defaultstorch.loadtoweights_only=Falsewithin the scorer subprocess only; callers passingweights_onlyexplicitly (e.g.torch.hub) are unaffected, and the parent benchmark process keeps stock semantics.Fix 4: opaque failure when
wget/unzipare missingvbench.utils.init_submodulesdownloads per-dimension weights via literalwget/unzipsubprocesses on a cold cache. In a minimal client container this dies mid-evaluation withFileNotFoundError: 'wget', after the videos were already generated. The runner now preflights both tools and exits with a structured error naming what is missing and how to fix it.Testing
test_drain_respects_per_phase_timeout(session honorsPhaseConfig.drain_timeout_s).test_stage_videos_renames_non_mp4_sources_to_mp4.tests/unit(minus two modules needing optional deps not in the default group): 1024 passed; the 5 pre-existingtest_profiler.pyfailures are identical on the unmodified base commit..avivideos (0.69998).Notes for reviewers
accuracy_timeout_s: Nonedefault is a deliberate behavior change: the old fixed bound could only ever truncate accuracy runs into invalid scores. A hung endpoint now blocks until the job walltime, which is loud rather than silently wrong.