os_helper.profile_utils module
Profiling Utilities
Context managers for timing code blocks at three different levels:
wall_timer— real elapsed wall-clock time (time.perf_counter).cpu_timer— CPU time consumed by the current process across allthreads (
time.process_time). Excludes I/O / sleep and subprocesses.
gpu_timer— GPU execution time via PyTorch CUDA events (ortorch.mps.synchronize+ wall-clock on Apple Silicon, since MPS does not expose timing events).
The three context managers yield a small dict
{"seconds": float, "milliseconds": float} populated when the with
block exits, so the result survives beyond the context.
Plus a pair of MATLAB-flavored convenience functions for the “sprinkle-a-timer-mid-script” style:
tic/toc— wall-clock stopwatch.tic()resets the implicitglobal timer and returns a handle;
toc()reads elapsed seconds since the lasttic()(or since the passed-in handle, for nested timings).
- Author:
Warith HARCHAOUI, https://linkedin.com/in/warith-harchaoui
- os_helper.profile_utils.cpu_timer()[source]
Measure CPU time consumed by the current process using
time.process_time()(sums user + system CPU across all threads).Differs from
wall_timer()in two important ways:It excludes time spent blocked on I/O, sleeping, or waiting on the GPU — so it isolates “actual computation done by Python+native code”.
It excludes subprocesses (ffmpeg, etc.). For those, use
wall_timer()oros.times()directly.
On a multi-threaded computation it can report more seconds than wall-clock — that’s intentional: it counts the CPU work, not the elapsed time.
- Yields:
dict –
{"seconds": float, "milliseconds": float}.- Return type:
Examples
>>> with cpu_timer() as t: ... total = sum(i * i for i in range(1_000_000)) >>> assert t["seconds"] > 0
- os_helper.profile_utils.gpu_timer(backend='auto')[source]
Measure GPU execution time, synchronizing before and after the block.
Backends
"cuda"— usestorch.cuda.Event(enable_timing=True)pairs, which give microsecond-level GPU-side timing."mps"— Apple Silicon. PyTorch’s MPS backend does not expose timing events, so this falls back totorch.mps.synchronize()+time.perf_counter()around the block. Accuracy ~1 ms."auto"— pick CUDA if available, else MPS, else raise.
Both paths synchronize before and after the block so the measured duration corresponds to actual GPU work, not just kernel-queue submission. Without synchronization, GPU ops are asynchronous and the timer would understate the cost dramatically.
- param backend:
"auto"(default),"cuda", or"mps".- type backend:
str, optional
- Yields:
dict –
{"seconds": float, "milliseconds": float}.- raises RuntimeError:
If PyTorch is not installed, or if the requested backend is unavailable on this machine.
- raises ValueError:
If
backendis not one of"auto","cuda","mps".
Examples
>>> import torch >>> if torch.cuda.is_available(): ... x = torch.randn(2048, 2048, device="cuda") ... with gpu_timer() as t: ... y = x @ x ... print(t["milliseconds"])
- os_helper.profile_utils.tic()[source]
Start (or restart) the implicit global stopwatch.
Returns the start timestamp so callers can pin a handle for nested or interleaved measurements:
>>> t_outer = tic() >>> # ... work ... >>> t_inner = tic() # implicit global now points at t_inner >>> # ... more work ... >>> toc(t_inner) # explicit handle works regardless of which tic() was last >>> toc(t_outer)
- os_helper.profile_utils.toc(handle=None, *, log=False)[source]
Return seconds elapsed since the matching
tic()call.- Parameters:
- Returns:
Seconds elapsed (does not reset the timer — call
tic()again to restart).- Return type:
- Raises:
RuntimeError – If called with no handle and no prior
tic().
Examples
>>> tic() >>> # ... work ... >>> elapsed = toc()
- os_helper.profile_utils.wall_timer()[source]
Measure real elapsed wall-clock time using
time.perf_counter().Use this when you want to know “how long did this take to run from the user’s perspective” — it includes I/O, sleeps, GPU waits, and subprocess time.
- Yields:
dict –
{"seconds": float, "milliseconds": float}, both fields populated when thewithblock exits.- Return type:
Examples
>>> with wall_timer() as t: ... time.sleep(0.05) >>> assert t["seconds"] >= 0.05