---
title: "Timing and CPU usage"
description: "Measure planning, execution, and end-to-end time separately, and interpret thread utilization and path metrics."
eyebrow: "Benchmark"
---

## Common timing scopes {#time}

Path search and numerical execution answer different questions: how long finding the path takes, and how long computing the result along that path takes. A complete task may include both, or load an existing path and execute directly.

| Timing | Included work |
| --- | --- |
| Planning-call time | The path-search function call itself |
| Total planning-process time | Startup to exit, including imports, search, and whatever path conversion, metric computation, and file saving the test program performs |
| Numerical-execution time | Computing tensor arrays along a given path |
| End-to-end time | Task input to result, including preprocessing, planning, slicing, execution, and synchronization |

For example, readings of `perf_counter()` immediately before and after `arctn_plan()` measure that call; a subsequent `plan.execute()` is excluded. Metrics computed separately after return should not be added to the earlier timing. Scoring performed inside the interface to select candidates or decide when to stop is part of search and must not be subtracted.

Test programs may include different preparation steps, so state timing boundaries in comparisons. GPU operations may be asynchronous, with computation continuing after the host call returns. Use the array library's synchronization or device-timing facilities to measure full device time; see [backend timing](/docs/execution-backends#timing).

## CPUs and threads {#cores}

Physical cores, Rayon workers, independent search tasks, and slices are different counts.

| Level | Work |
| --- | --- |
| Multiple processes | Different networks or independent search runs |
| Path search | Parallel candidates in Light, Heavy, or low-level algorithms |
| Sliced execution | Slice chunks or ranges assigned to MPI processes |
| Numerical kernels | Matrix multiplication and threads internal to array backends |

Wall time is elapsed time from start to finish; process CPU time accumulates time spent on CPUs across the process's threads. Their ratio for the same stage estimates average CPU usage:

$$
C_{\mathrm{eff}}=\frac{T_{\mathrm{CPU}}}{T_{\mathrm{wall}}}.
$$

For example, if a stage lasts two seconds and its threads consume eight CPU-seconds in total, the ratio is four: equivalent on average to four CPU threads running continuously. Eight configured workers may still yield this value because of sequential stages, waiting, or insufficient tasks.

This average is not physical-core count. CPU affinity only specifies eligible CPUs, not continuous usage; with SMT, multiple logical CPUs may share one physical core.

More threads may also change the amount of search work completed by Light and Heavy. Fixed-work strong-scaling comparisons require the same task and budget. Shared-server concurrency is useful for throughput measurements; when measuring single-task latency, state other load and resource allocation.

## Path metrics versus execution {#quality}

FLOPs, reads/writes, intermediate size, and peak live elements describe path structure. Actual runtime also depends on tensor shapes, transposes, data types, kernels, caches, threads, and device synchronization.

Cross-library comparisons should state whether the network, objective, budget, and metric implementation are identical. If reporting only instances on which every method succeeds, also list the full test set and failure counts. See the [benchmark suite](/docs/benchmarks) for datasets and intended uses.
