From db4125bb5689a230b21e015f05c125c40a64e12f Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang <1182563586@qq.com> Date: Thu, 27 Aug 2026 20:53:25 +0800 Subject: [PATCH] [diffusion] Accept mesh benchmark artifacts (#36553) --- .../SKILL.md | 3 +- .../benchmark-and-profile.md | 8 ++--- .../scripts/bench_diffusion_denoise.py | 11 +++++- .../unit/test_diffusion_benchmark_skill.py | 35 +++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/SKILL.md b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/SKILL.md index b2e57b8bf..3bc260378 100644 --- a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/SKILL.md +++ b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/SKILL.md @@ -107,7 +107,8 @@ temporal shape. Treat any remaining temporal or conditioning signature miss as Eager fallback, not as a valid BCG measurement. A zero process exit is not sufficient evidence: every accepted row must also -contain its requested perf dump and a generated image, video, or audio file. +contain its requested perf dump and a generated image, video, audio, or 3D mesh +file. The helper gives every cell a unique output name and rejects missing artifacts. On machines with a read-only Hugging Face cache, combine diff --git a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/benchmark-and-profile.md b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/benchmark-and-profile.md index b5a05922a..fa8422623 100644 --- a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/benchmark-and-profile.md +++ b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/benchmark-and-profile.md @@ -161,10 +161,10 @@ Eager/BCG/BCG/Eager at `lossless`, then the same sequence at `high`, while holding one GPU set and one isolated checkpoint cache. The high+BCG cells test whether the combination is actually supported; do not average them when the runtime rejects the combination or the helper detects a late quality-fusion -mount. The helper also hashes every generated artifact, first requires the two -Eager rows at each quality to agree, then rejects any BCG row whose hash differs -from that Eager reference. Cleanup occurs only after all eight runs, including -on failure or interruption: +mount. The helper hashes every generated image, video, audio, or 3D mesh +artifact. It first requires the two Eager rows at each quality to agree, then +rejects any BCG row whose hash differs from that Eager reference. Cleanup occurs +only after all eight runs, including on failure or interruption: ```bash MODEL_CACHE_ROOT=/path/to/task-owned/model-caches diff --git a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/scripts/bench_diffusion_denoise.py b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/scripts/bench_diffusion_denoise.py index c81bf2326..5a199aa11 100755 --- a/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/scripts/bench_diffusion_denoise.py +++ b/python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/scripts/bench_diffusion_denoise.py @@ -121,7 +121,16 @@ MODEL_WEIGHT_SUFFIXES = { ".pth", ".safetensors", } -GENERATED_OUTPUT_SUFFIXES = {".jpeg", ".jpg", ".mp4", ".png", ".wav", ".webp"} +GENERATED_OUTPUT_SUFFIXES = { + ".glb", + ".jpeg", + ".jpg", + ".mp4", + ".obj", + ".png", + ".wav", + ".webp", +} NIGHTLY_PRESET_ORDER = ( "flux", "flux2", diff --git a/python/sglang/multimodal_gen/test/unit/test_diffusion_benchmark_skill.py b/python/sglang/multimodal_gen/test/unit/test_diffusion_benchmark_skill.py index 7ae845f15..c0b233391 100644 --- a/python/sglang/multimodal_gen/test/unit/test_diffusion_benchmark_skill.py +++ b/python/sglang/multimodal_gen/test/unit/test_diffusion_benchmark_skill.py @@ -472,6 +472,41 @@ class TestDiffusionBenchmarkSkill(unittest.TestCase): result["missing_artifacts"], ["perf dump", "generated output"] ) + def test_mesh_artifacts_are_accepted_and_hashed(self): + with tempfile.TemporaryDirectory() as tmpdir: + temp_root = Path(tmpdir) + module = _load_benchmark_module(temp_root) + output_dir = temp_root / "outputs" + output_dir.mkdir() + + def finish_run(): + (output_dir / "hunyuan3d-shape_mesh-output.json").write_text( + json.dumps({"total_duration_ms": 1000, "steps": []}), + encoding="utf-8", + ) + (output_dir / "hunyuan3d-shape-mesh-output.obj").write_bytes( + b"v 0 0 0\n" + ) + return 0 + + with patch.object(module.subprocess, "Popen") as popen: + popen.return_value.stdout = iter(()) + popen.return_value.wait.side_effect = finish_run + result = module._run_benchmark_once_impl( + "hunyuan3d-shape", + "mesh-output", + output_dir, + warmup=False, + cuda_visible_devices="0", + ) + + self.assertFalse(result["error"]) + self.assertEqual( + result["output_artifacts"], + [str(output_dir / "hunyuan3d-shape-mesh-output.obj")], + ) + self.assertEqual(len(result["output_sha256"]), 1) + def test_high_bcg_rejects_quality_fusion_mounted_after_capture(self): with tempfile.TemporaryDirectory() as tmpdir: temp_root = Path(tmpdir)