convert these two steps commands into one command: 1. check if downloading image or model is already there, if it is, skip. 2. remove prompt-file arg, when generating a new request, roundrobin the generated prompts

This commit is contained in:
Tara Ding 2026-04-27 14:13:01 -07:00
parent 52da6933b4
commit ff5e379cc2

View File

@ -11,35 +11,27 @@ This script is designed to:
Usage Wan 2.2 I2V benchmark Usage Wan 2.2 I2V benchmark
============================== ==============================
Step 1 Generate prompt files (downloads images, writes JSONs, then exits): Images and prompt files are prepared automatically on first run and reused on
subsequent runs. Just specify --model and --task:
# Minimal: uses synthetic images, writes to prompts/wan22_i2v/ # Minimal (synthetic images, default paths):
python3 benchmarks/benchmark_comfyui_serving.py \\ python3 benchmarks/benchmark_comfyui_serving.py \\
--generate-prompts --model wan22 --task i2v \\ --model wan22 --task i2v \\
--num-requests 50 --num-requests 50 --max-concurrency 4
# With model download (needs ComfyUI root): # With model download (needs ComfyUI root):
python3 benchmarks/benchmark_comfyui_serving.py \\ python3 benchmarks/benchmark_comfyui_serving.py \\
--generate-prompts --model wan22 --task i2v \\ --model wan22 --task i2v \\
--download-models --comfyui-base-dir /path/to/ComfyUI \\ --download-models --comfyui-base-dir /path/to/ComfyUI \\
--num-requests 50 --num-requests 50 --max-concurrency 4
# Custom image/output dirs (input-dir must be ComfyUI's input/ folder): # Custom paths:
python3 benchmarks/benchmark_comfyui_serving.py \\ python3 benchmarks/benchmark_comfyui_serving.py \\
--generate-prompts --model wan22 --task i2v \\ --model wan22 --task i2v \\
--input-dir /home/ubuntu/ComfyUI/input \\ --input-dir /home/ubuntu/ComfyUI/input \\
--prompts-dir /home/ubuntu/ComfyUI/benchmarks/prompts/wan22_i2v \\ --prompts-dir /home/ubuntu/ComfyUI/benchmarks/prompts/wan22_i2v \\
--num-images 30 --num-requests 50 --num-images 30 --num-requests 50 --max-concurrency 4 \\
Step 2 Run the benchmark (point at any one of the generated prompt files):
python3 benchmarks/benchmark_comfyui_serving.py \\
--prompt-file benchmarks/prompts/wan22_i2v/wan22_i2v_prompt_0000.json \\
--num-requests 50 \\
--max-concurrency 4 \\
--host http://127.0.0.1:8188 --host http://127.0.0.1:8188
The setup step also prints the exact run command at the end, so you can copy it directly.
""" """
from __future__ import annotations from __future__ import annotations
@ -260,7 +252,6 @@ def generate_prompt_files(
task: str, task: str,
output_dir: Path, output_dir: Path,
input_dir: Path, input_dir: Path,
num_prompts: int = 50,
num_images: int = 20, num_images: int = 20,
download_model_weights: bool = False, download_model_weights: bool = False,
comfyui_base_dir: Path | None = None, comfyui_base_dir: Path | None = None,
@ -269,11 +260,11 @@ def generate_prompt_files(
Full benchmark setup for a given *model*/*task*: Full benchmark setup for a given *model*/*task*:
1. Optionally download model weights into *comfyui_base_dir*. 1. Optionally download model weights into *comfyui_base_dir*.
2. Prepare input images in *input_dir*. 2. Prepare input images in *input_dir* (skipped if images already exist).
3. Generate *num_prompts* prompt JSON files in *output_dir*, cycling 3. Generate one prompt JSON per input image in *output_dir*
through the available images. (skipped if prompt files already exist).
Returns the list of generated prompt file paths. Returns the list of prompt file paths.
""" """
key = (model, task) key = (model, task)
if key not in _MODEL_REGISTRY: if key not in _MODEL_REGISTRY:
@ -287,6 +278,12 @@ def generate_prompt_files(
raise ValueError("--comfyui-base-dir is required when --download-models is set") raise ValueError("--comfyui-base-dir is required when --download-models is set")
download_models(comfyui_base_dir, model, task) download_models(comfyui_base_dir, model, task)
# Skip prompt generation if files already exist.
existing = sorted(output_dir.glob(f"{model}_{task}_prompt_*.json"))
if existing:
print(f"[setup] found {len(existing)} existing prompt files in {output_dir}, skipping generation")
return existing
image_filenames = prepare_input_images( image_filenames = prepare_input_images(
input_dir, input_dir,
num_images=num_images, num_images=num_images,
@ -301,19 +298,12 @@ def generate_prompt_files(
output_dir.mkdir(parents=True, exist_ok=True) output_dir.mkdir(parents=True, exist_ok=True)
generated: list[Path] = [] generated: list[Path] = []
for i in range(num_prompts): for i, image_name in enumerate(image_filenames):
image_name = image_filenames[i % len(image_filenames)]
prompt_path = output_dir / f"{model}_{task}_prompt_{i:04d}.json" prompt_path = output_dir / f"{model}_{task}_prompt_{i:04d}.json"
generate_prompt_file(prompt_path, workflow_path, image_name) generate_prompt_file(prompt_path, workflow_path, image_name)
generated.append(prompt_path) generated.append(prompt_path)
print(f"[setup] generated {len(generated)} prompt files in {output_dir}") print(f"[setup] generated {len(generated)} prompt files in {output_dir}")
print(f"[setup] example run:")
print(
f" python benchmark_comfyui_serving.py"
f" --prompt-file {generated[0]}"
f" --num-requests {num_prompts}"
)
return generated return generated
@ -489,7 +479,7 @@ async def run_request(
semaphore: asyncio.Semaphore, semaphore: asyncio.Semaphore,
session: aiohttp.ClientSession, session: aiohttp.ClientSession,
args: argparse.Namespace, args: argparse.Namespace,
prompt_wrapper_template: dict[str, Any], prompt_templates: list[dict[str, Any]],
) -> RequestResult: ) -> RequestResult:
await asyncio.sleep(max(0.0, (start_time + scheduled_offset_s) - time.perf_counter())) await asyncio.sleep(max(0.0, (start_time + scheduled_offset_s) - time.perf_counter()))
queued_at = time.perf_counter() queued_at = time.perf_counter()
@ -498,7 +488,7 @@ async def run_request(
started_at = time.perf_counter() started_at = time.perf_counter()
prompt_id = None prompt_id = None
try: try:
payload = json.loads(json.dumps(prompt_wrapper_template)) payload = json.loads(json.dumps(prompt_templates[idx % len(prompt_templates)]))
payload.setdefault("extra_data", {}) payload.setdefault("extra_data", {})
payload["client_id"] = args.client_id payload["client_id"] = args.client_id
@ -596,28 +586,17 @@ def parse_args() -> argparse.Namespace:
choices=("/prompt", "/bench/prompt"), choices=("/prompt", "/bench/prompt"),
help="Submission endpoint.", help="Submission endpoint.",
) )
p.add_argument(
"--prompt-file",
type=Path,
default=None,
help="Path to prompt JSON. Required unless --generate-prompts is set.",
)
p.add_argument(
"--generate-prompts",
action="store_true",
help="Prepare input images and generate prompt JSON files, then exit.",
)
p.add_argument( p.add_argument(
"--model", "--model",
choices=_VALID_MODELS, choices=_VALID_MODELS,
default=None, required=True,
help=f"Model to benchmark. Required with --generate-prompts. Choices: {_VALID_MODELS}.", help=f"Model to benchmark. Choices: {_VALID_MODELS}.",
) )
p.add_argument( p.add_argument(
"--task", "--task",
choices=_VALID_TASKS, choices=_VALID_TASKS,
default=None, required=True,
help=f"Task type. Required with --generate-prompts. Choices: {_VALID_TASKS}.", help=f"Task type. Choices: {_VALID_TASKS}.",
) )
p.add_argument( p.add_argument(
"--input-dir", "--input-dir",
@ -668,9 +647,19 @@ def parse_args() -> argparse.Namespace:
async def async_main(args: argparse.Namespace) -> None: async def async_main(args: argparse.Namespace) -> None:
if args.prompt_file is None: prompts_dir = args.prompts_dir or Path("benchmarks/prompts") / f"{args.model}_{args.task}"
raise SystemExit("error: --prompt-file is required (or use --generate-prompts to create one)") prompt_paths = generate_prompt_files(
prompt_template = load_prompt_template(args.prompt_file) model=args.model,
task=args.task,
output_dir=prompts_dir,
input_dir=args.input_dir,
num_images=args.num_images,
download_model_weights=args.download_models,
comfyui_base_dir=args.comfyui_base_dir,
)
prompt_templates = [load_prompt_template(p) for p in prompt_paths]
print(f"[bench] loaded {len(prompt_templates)} prompt templates, round-robining over {args.num_requests} requests")
schedule = build_arrival_schedule( schedule = build_arrival_schedule(
num_requests=args.num_requests, num_requests=args.num_requests,
request_rate=args.request_rate, request_rate=args.request_rate,
@ -691,7 +680,7 @@ async def async_main(args: argparse.Namespace) -> None:
semaphore=semaphore, semaphore=semaphore,
session=session, session=session,
args=args, args=args,
prompt_wrapper_template=prompt_template, prompt_templates=prompt_templates,
) )
) )
for i in range(args.num_requests) for i in range(args.num_requests)
@ -714,21 +703,6 @@ async def async_main(args: argparse.Namespace) -> None:
def main() -> None: def main() -> None:
args = parse_args() args = parse_args()
if args.generate_prompts:
if not args.model or not args.task:
raise SystemExit("error: --model and --task are required with --generate-prompts")
prompts_dir = args.prompts_dir or Path("benchmarks/prompts") / f"{args.model}_{args.task}"
generate_prompt_files(
model=args.model,
task=args.task,
output_dir=prompts_dir,
input_dir=args.input_dir,
num_prompts=args.num_requests,
num_images=args.num_images,
download_model_weights=args.download_models,
comfyui_base_dir=args.comfyui_base_dir,
)
return
asyncio.run(async_main(args)) asyncio.run(async_main(args))