Write a complete latency-benchmarking script with warmup, synchronisation, percentiles, and memory tracking. Use when you need help with skill latency profiler.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill skill-latency-profiler --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Skill Latency Profiler?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-skill-latency-profiler)More formats (shields.io, HTML) on the badges page.
---
name: skill-latency-profiler
description: Write a complete latency-benchmarking script with warmup, synchronisation, percentiles, and memory tracking. Use when you need help with skill latency profiler.
license: CC-BY-NC-SA-4.0
phase: 4
lesson: 15
metadata:
version: 1.0.0
tags: [edge, deployment, profiling, benchmarking]
---
# Latency Profiler
Produce a disciplined latency benchmark for any PyTorch model. Reports that anyone downstream can actually trust.
## When to use
- Comparing multiple candidate backbones before picking one to deploy.
- Before and after quantisation or pruning.
- After a runtime change (eager vs ONNX vs TensorRT).
- Generating a deployment-readiness report.
## Inputs
- `model`: PyTorch `nn.Module`.
- `input_shape`: tuple like `(1, 3, 224, 224)`.
- `device`: `cpu` | `cuda` | `mps`.
- `warmup`: default 10.
- `iters`: default 100.
## Checks
### 1. Warmup
Run the model `warmup` times without timing. Catches first-forward JIT compilation and cold cache effects.
### 2. Synchronisation
For `cuda`, call `torch.cuda.synchronize()` before and after each timed forward pass.
For `mps`, call `torch.mps.synchronize()`.
### 3. Timer
Use `time.perf_counter()` for wall-clock measurement. Convert to milliseconds.
### 4. Percentiles
Sort the full list of timings. Report `p50, p90, p95, p99, mean, std`.
### 5. Memory
For `cuda`, call `torch.cuda.max_memory_allocated()` after the run and subtract any baseline.
For `cpu`, use `tracemalloc` or `psutil.Process().memory_info().rss` before and after.
### 6. Batch-size sweep
Optionally repeat the benchmark for `batch_size in [1, 4, 16, 32]` to reveal throughput vs latency tradeoffs.
## Output template
```python
import time
import torch
import psutil, os
def profile(model, input_shape, device="cpu", warmup=10, iters=100):
proc = psutil.Process(os.getpid())
baseline_rss = proc.memory_info().rss / 1e6
model = model.to(device).eval()
x = torch.randn(input_shape, device=device)
def sync():
if device == "cuda":
torch.cuda.synchronize()
elif device == "mps":
torch.mps.synchronize()
with torch.no_grad():
for _ in range(warmup):
model(x)
sync()
if device == "cuda":
torch.cuda.reset_peak_memory_stats()
times = []
for _ in range(iters):
sync()
t0 = time.perf_counter()
model(x)
sync()
times.append((time.perf_counter() - t0) * 1000)
times.sort()
mean = sum(times) / len(times)
std = (sum((t - mean) ** 2 for t in times) / len(times)) ** 0.5
def pct(p):
idx = max(0, min(len(times) - 1, int(len(times) * p) - 1))
return times[idx]
report = {
"p50_ms": pct(0.50),
"p90_ms": pct(0.90),
"p95_ms": pct(0.95),
"p99_ms": pct(0.99),
"mean_ms": mean,
"std_ms": std,
"rss_mb": proc.memory_info().rss / 1e6 - baseline_rss,
}
if device == "cuda":
report["peak_cuda_mb"] = torch.cuda.max_memory_allocated() / 1e6
return report
```
## Rules
- Always run warmup; never trust a first-forward timing.
- Percentiles, not mean — a single outlier can double the mean but barely move p50.
- Use the same input_shape as production; latency on 224x224 is not latency on 384x384.
- For CUDA, never omit `torch.cuda.synchronize()`; the numbers are meaningless without it.
- Log the torch version, CUDA version, and device name alongside the numbers — they stop being comparable otherwise.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!