| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import time |
|
|
| import torch |
|
|
| from .config import apply_overrides, load_config |
| from .model import build_model |
| from .utils import trainable_parameter_count |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser(description="Profile ObjectModel-v1 parameters and latency") |
| parser.add_argument("--config", default="configs/objectmodel_v1.yaml") |
| parser.add_argument("--device", default="cuda" if torch.cuda.is_available() else "cpu") |
| parser.add_argument("--warmup", type=int, default=10) |
| parser.add_argument("--runs", type=int, default=50) |
| parser.add_argument("--set", action="append", default=[]) |
| args = parser.parse_args() |
| config = apply_overrides(load_config(args.config), args.set) |
| device = torch.device(args.device) |
| model = build_model(config).eval().to(device) |
| size = model.spec.input_size |
| sample = torch.randn(1, 3, size, size, device=device) |
| with torch.inference_mode(): |
| for _ in range(args.warmup): |
| model(sample) |
| if device.type == "cuda": |
| torch.cuda.synchronize() |
| durations = [] |
| for _ in range(args.runs): |
| start = time.perf_counter() |
| model(sample) |
| if device.type == "cuda": |
| torch.cuda.synchronize() |
| durations.append((time.perf_counter() - start) * 1000) |
| durations.sort() |
| parameters = trainable_parameter_count(model) |
| report = { |
| "parameters": parameters, |
| "parameters_millions": round(parameters / 1e6, 3), |
| "fp32_weight_megabytes": round(parameters * 4 / 1024**2, 2), |
| "input_size": size, |
| "device": str(device), |
| "latency_ms_median": round(durations[len(durations) // 2], 3), |
| "latency_ms_p95": round(durations[min(int(len(durations) * 0.95), len(durations) - 1)], 3), |
| } |
| print(json.dumps(report, indent=2)) |
|
|
|
|
| if __name__ == "__main__": |
| main() |