SD3.5-medium-OpenVINO-INT4 / inference_int4.py
HelloSun's picture
Upload folder using huggingface_hub
69cbd51 verified
Raw History Blame Contribute Delete
4.5 kB
#!/usr/bin/env python3
"""Generate one image with the INT4 OpenVINO build of stable-diffusion-3.5-medium.
Inference parameters follow the ORIGINAL model card, not the FLUX.2 reference:
stabilityai/stable-diffusion-3.5-medium
1024x1024, num_inference_steps=40, guidance_scale=4.5
(FLUX.2-klein-4B-OpenVINO-INT4 uses 4 steps / guidance 1.0 because FLUX.2 is a
4-step distilled model. SD3.5-medium is a full flow-matching model, so the step
count is 10x higher. The scheduler shift of 3.0 comes from the repo's
scheduler/scheduler_config.json and is picked up automatically.)
Usage
-----
python inference_int4.py --prompt "Astronaut in a jungle" --seed 43 --output out.png
python inference_int4.py --prompt "..." --steps 28 # faster, lower quality
python inference_int4.py --prompt "..." --resize 512 # cheap preview
"""
from __future__ import annotations
import argparse
import os
import time
from pathlib import Path
REPO_ID = "HelloSun/SD3.5-medium-OpenVINO-INT4"
# Values from the original model card.
DEFAULT_STEPS = 40
DEFAULT_GUIDANCE = 4.5
DEFAULT_SIZE = 1024
def load_pipeline(repo_id: str, device: str, compile_model: bool):
import torch
from optimum.intel import OVDiffusionPipeline
print(f"loading {repo_id} ...", flush=True)
t0 = time.perf_counter()
pipe = OVDiffusionPipeline.from_pretrained(repo_id, device=device, compile=compile_model)
print(f"load+compile {time.perf_counter() - t0:.2f}s", flush=True)
return pipe, torch
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--prompt", required=True)
parser.add_argument("--negative-prompt", default="")
parser.add_argument("--model", default=REPO_ID, help="local path or Hub id")
parser.add_argument("--output", type=Path, default=Path("out.png"))
parser.add_argument("--steps", type=int, default=DEFAULT_STEPS)
parser.add_argument("--guidance", type=float, default=DEFAULT_GUIDANCE)
parser.add_argument("--width", type=int, default=DEFAULT_SIZE)
parser.add_argument("--height", type=int, default=DEFAULT_SIZE)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--stepsize", type=int, default=8, help="scheduler shift; 8 is common for SD3 speed/quality")
parser.add_argument("--resize", type=int, default=None, help="also save a downscaled copy at this size")
parser.add_argument("--device", default="CPU")
parser.add_argument("--no-compile", action="store_true", help="skip OV graph compilation")
parser.add_argument("--num-images", type=int, default=1)
args = parser.parse_args()
pipe, torch = load_pipeline(args.model, args.device, not args.no_compile)
args.output.parent.mkdir(parents=True, exist_ok=True)
started = time.perf_counter()
image = pipe(
prompt=args.prompt,
negative_prompt=args.negative_prompt,
num_inference_steps=args.steps,
guidance_scale=args.guidance,
width=args.width,
height=args.height,
num_images_per_prompt=args.num_images,
generator=torch.Generator().manual_seed(args.seed),
).images[0]
elapsed = time.perf_counter() - started
image.save(args.output)
print(f"saved {args.output} {image.size[0]}x{image.size[1]} {elapsed:.2f}s "
f"({elapsed / max(args.steps, 1):.2f}s/step)", flush=True)
if args.resize:
preview = args.output.with_name(f"{args.output.stem}_{args.resize}.png")
try:
from PIL import Image as _Image
_resample = _Image.Resampling.LANCZOS # Pillow >= 9.1
except (ImportError, AttributeError):
_resample = image.LANCZOS
image.resize((args.resize, args.resize), _resample).save(preview)
print(f"saved {preview}", flush=True)
peak_mb = 0.0
try:
# Kernel high-water mark: exact and dependency-free on Linux.
for line in Path("/proc/self/status").read_text().splitlines():
if line.startswith("VmHWM:"):
peak_mb = int(line.split()[1]) / 1024
break
else:
import psutil
peak_mb = psutil.Process(os.getpid()).memory_info().rss / 1024**2
except (OSError, ValueError, IndexError, ImportError):
pass
if peak_mb:
print(f"peak RSS: {peak_mb:.0f} MB", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())