Spaces:
Sleeping
Sleeping
File size: 2,862 Bytes
d4a30e5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | """Benchmark single-image inference latency for the trained model.
No dataset needed — runs over the bundled sample images in `images/`. From repo root:
uv run python scripts/bench_speed.py # all available devices
uv run python scripts/bench_speed.py --device cpu # one device
uv run python scripts/bench_speed.py --imgsz 640 --runs 30
Reports mean inference latency (ms) and FPS per device, warmup excluded. The
"inference" figure is the model forward pass only (Ultralytics' `speed['inference']`),
matching the methodology of the model-card inference table.
"""
from __future__ import annotations
import argparse
from pathlib import Path
import torch
from ultralytics import YOLO
WEIGHTS = "runs/detect/yolov8n_v1_train/weights/best.pt"
IMAGES_DIR = "images"
def available_devices() -> list[str]:
devices = ["cpu"]
if torch.cuda.is_available():
devices.append("0")
if torch.backends.mps.is_available():
devices.append("mps")
return devices
def bench(weights: str, device: str, images: list[str], imgsz: int, runs: int) -> tuple[float, float]:
model = YOLO(weights)
# Warmup — first calls pay lazy init / kernel-compile costs we don't want to time.
model.predict(images[0], device=device, imgsz=imgsz, verbose=False)
latencies: list[float] = []
for _ in range(runs):
for img in images:
r = model.predict(img, device=device, imgsz=imgsz, verbose=False)
latencies.append(r[0].speed["inference"]) # ms, forward pass only
mean_ms = sum(latencies) / len(latencies)
return mean_ms, 1000.0 / mean_ms
def main() -> None:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--weights", default=WEIGHTS)
p.add_argument("--images", default=IMAGES_DIR)
p.add_argument("--device", default=None, help="cpu / mps / 0 (GPU); omit to run all available")
p.add_argument("--imgsz", type=int, default=640)
p.add_argument("--runs", type=int, default=20, help="passes over the image set per device")
args = p.parse_args()
images = sorted(str(p) for p in Path(args.images).glob("*") if p.suffix.lower() in {".jpg", ".jpeg", ".png"})
if not images:
raise SystemExit(f"No images found in {args.images!r}")
devices = [args.device] if args.device else available_devices()
print(f"Weights: {args.weights}")
print(f"Images: {len(images)} from {args.images}/ (imgsz={args.imgsz}, {args.runs} passes each)\n")
print(f"{'Device':<10} {'Latency (ms)':>14} {'FPS':>8}")
print("-" * 34)
for dev in devices:
mean_ms, fps = bench(args.weights, dev, images, args.imgsz, args.runs)
label = {"cpu": "CPU", "mps": "MPS (GPU)", "0": "CUDA GPU"}.get(dev, dev)
print(f"{label:<10} {mean_ms:>14.1f} {fps:>8.1f}")
if __name__ == "__main__":
main()
|