April 3, 2026
4m 3s

Edge ML teams often treat latency numbers as if they are portable facts. But in real deployments, the measurement system can become part of the result. Our tests on the Jetson Orin Nano and Raspberry Pi 4 show that two platforms can report meaningfully different software-clock latencies for reasons that have little to do with model performance and everything to do with platform-specific instrumentation overhead.
The lesson is that cross-platform validation needs to account for the measurement stack, not just the workload.
Edge ML systems deployed under real-time constraints need their per-inference timing measurements to be defensible across the platforms they run on. When the same workload is benchmarked or validated on two embedded platforms, the practitioner usually assumes the software-clock numbers from each platform can be compared on the same axis. Our results suggest this assumption breaks down in a specific way that uniform tolerance checks do not catch.
Two embedded engineers run the same edge ML workload on two platforms. Both use Python's time.perf_counter to record per-inference latency. Both assume the software-clock numbers are directly comparable. On the NVIDIA Jetson Orin Nano, the software clock reports a mean inference latency that overstates the on-wire interval by about 20 microseconds (µs). On the Raspberry Pi 4, the same software clock overstates it by about 86 µs. Same workload, same instrumentation pattern, but a 66 µs cross-platform asymmetry that is not surfaced in either platform's documentation.
The discrepancy does not imply a broken timing source. The dominant bias comes from platform-dependent GPIO instrumentation overhead, which is at a magnitude that breaks the most common acceptance checks used in edge ML benchmarking practice.
To isolate where the bias comes from, we need to distinguish two things: what the software clock reports, and what actually happens on the wire. The protocol below captures both, on the same per-inference cadence.
For each inference, wrap the call with a GPIO pulse and capture four monotonic timestamps:
t0 = perf_counter_ns(); gpio.high(PIN)
t1 = perf_counter_ns(); y = model.infer(x)
t2 = perf_counter_ns(); gpio.low(PIN)
t3 = perf_counter_ns()
Your reported inference latency is t2 minus t1. A logic analyzer (we used a Saleae Logic Pro 8 at 100 MHz) captures the actual rise and fall on the GPIO pin. Comparing the wire interval to the perf_counter interval gives the per-inference residual:
delta = latency_saleae - latency_perf
This residual is what is platform-dependent. Across 2,030 inferences in our dataset, every delta was nonpositive: the perf_counter interval enclosed the wire interval in every paired measurement. The magnitude |delta| is what matters: it is the GPIO instrumentation overhead, and it differs by ~4x between the platforms we tested.
Across 10 trials per platform at a controlled baseline (no contention workload), with the operating state pinned for reproducibility (Jetson at 25W Super Mode with jetson_clocks; Pi with CPU governor set to performance and pigpiod active), the per-platform constants are:
C_jetson = -20.00 us (mean of per-trial medians, n = 10)
C_pi = -86.13 us (mean of per-trial medians, n = 10)
The deeper point: the measurement coordinate system itself is platform-biased. Each platform's software-clock timing sits on its own axis, offset from the on-wire reality by a platform-specific amount. Comparing software-clock numbers across platforms without correcting for that offset is comparing values on different axes. C_p is the empirical calibration that brings them onto the same axis.
Concretely, C_p is specific to the platform, the GPIO driver path, and the operating state under which you measure it. You compute it by running a hardware-referenced calibration in the deployed configuration, then subtract it from your software-clock measurements.
The cross-platform asymmetry is approximately 66 µs. The Pi's GPIO instrumentation overhead is roughly four times the Jetson's. The asymmetry is several times larger than the within-trial standard deviation on either platform (which ranges from 2.46 to 14.79 µs depending on platform and trial), so it is not within-platform measurement noise.
Reproducibility also differs across platforms. On the Jetson, the 10 trial medians span 0.58 µs within a single session, and the constant reproduces to within 0.14 µs across the two sessions we sampled. On the Pi, the 10 trial medians span 8.97 µs within a single session, and the session-level constant moves by about 6 µs across the three sessions we sampled. The Pi shows lower within-session and cross-session reproducibility than the Jetson under our conditions, which is relevant for any acceptance check that relies on a previously measured calibration.
Table 1 below summarizes the platform-level contrasts. Shared parameters (Saleae rate, trial count, workload) are listed beneath the table.
Table 1. Platform contrasts (shared parameters omitted)
Shared parameters across both platforms: Saleae Logic Pro 8 at 100 MHz, n = 10 trials per platform, 407 inferences per trial, 1D CNN ECG arrhythmia classifier (~115k params, ~1.2 ms median inference), MIT-BIH AAMI EC57 5-class workload.

The obvious explanation for the asymmetry is that the Pi's GPIO calls are simply slower. A separate harness on each platform times gpio.high() and gpio.low() in tight loops (no Saleae capture, no inference, n = 5,000 iterations). The medians:
Jetson: median(HIGH + LOW) = 17.89 us
Pi: median(HIGH + LOW) = 102.37 us
On the Jetson, direct call duration accounts for 88 percent of |C_jetson| (17.89 of 20.00 µs). The 2.11 µs residual is consistent with Saleae edge-detection latency, sample-rate quantization at 100 MHz, and small orchestrator overhead. The Jetson's instrumentation overhead is mechanistically explained by its call duration.
On the Pi, direct call duration is 102.37 µs but |C_pi| is 86.13 µs. The tight-loop profile over-predicts the deployed overhead by 19 percent. One possible explanation is that pigpio queueing behavior differs between tight-loop and inference-interleaved execution patterns. We did not instrument pigpiod internally, so the mechanism remains unverified.

The practical implication matters more than the mechanism. On at least one platform tested here, deployed measurement overhead cannot be characterized by profiling GPIO calls in a microbenchmark. The calibration has to run with the inference cadence the production code uses.
One practical acceptance check is a uniform tolerance applied to the raw residual: accept the measurement chain if |delta| is below some threshold tau. In our setup, this does not work. A tau of 30 µs admits the Jetson but flags every Pi measurement as out-of-tolerance, which is inconsistent with the Pi's measurement chain behaving as expected for that platform. A tau of 100 µs admits the Pi but is non-binding on the Jetson. No single tau both constrains the Jetson and admits the Pi.
Subtracting the per-platform constant first makes a single threshold feasible:
Acceptance check: |delta - C_p| <= tau
C_p is the empirically calibrated per-platform constant. After the subtraction, both platforms produce residuals centered on zero, with within-trial standard deviation in the same range (2.46 to 5.12 µs on Jetson, 6.02 to 14.79 µs on Pi). Setting tau at roughly 2.5x the worst within-trial standard deviation gives tau around 37 µs. This threshold accepts normal measurement noise on both platforms while remaining tight enough to flag real measurement faults (a stuck-high GPIO line, a daemon timeout, a kernel-scheduling pathology), which would produce residuals many times beyond tau.

The cost of this approach is one short calibration trial at the start of each measurement session, sufficient to estimate C_p with reasonable precision. The benefit is that driver-induced overhead is not misclassified as a faulty measurement source, and the platforms are not forced to agree on a single tolerance.
Here are three concrete changes for engineers running edge ML timing studies on more than one platform.
1. Calibrate C_p in the deployed context. Capture the GPIO pin at 100 MHz or higher with a logic analyzer, bracket inference with gpio.high() / gpio.low(), and compute the median of (latency_saleae - latency_perf) over a few hundred inferences. Run the calibration under the actual inference cadence and call-interleaving pattern your production code will use, not a tight benchmark loop. The interleaving pattern matters: on the Raspberry Pi we tested, a tight-loop microbenchmark over-predicts the deployed C_p by 19 percent (about 16 µs). A Saleae Logic Pro 8 or equivalent is sufficient; the harness is a few dozen lines of Python plus a USB connection.
2. Make the acceptance check platform-aware. In whatever pipeline currently asserts that |residual| is within some uniform tolerance, swap in the per-platform subtraction: |residual - C[platform]| within tolerance. The change is one extra subscript. Setting tolerance at ~2.5x your worst measured within-trial standard deviation is a defensible default in our conditions; in this study that came out to ~37 µs.
3. Plan for session-aware recalibration where it matters. The Jetson's C_p was stable to within 0.14 µs across the two sessions we sampled, so a one-time calibration is likely fine. The Pi's C_p moved by about 6 µs across three sessions; if your tolerance budget is tight on Pi, recalibrate at the start of each measurement session under the same operating state, rather than relying on a calibration from a previous run.
Limits and What Is Left to Future Work
There are three things this characterization does not cover. First, all measurements are at C0 baseline, with no contention workload; whether C_p shifts under sustained CPU, memory, I/O, or network contention is left to future work. Second, statistical replication is at the work-in-progress tier (n = 10 per platform in the current session, with two prior Pi sessions and one prior Jetson session pooled into the cross-day analysis); the Pi cross-day variance is observational, with mechanism left open. Third, only two GPIO drivers are tested (Jetson.GPIO chardev and pigpio daemon); other drivers such as lgpio or legacy sysfs may exhibit different overhead profiles.
None of this changes the core practical takeaway. These results suggest that cross-platform edge ML timing studies may require platform-aware acceptance checks when software-clock measurements are compared against external hardware references. The cost of running a per-platform calibration is small relative to the cost of mis-validating a measurement chain that is actually working as expected.
As edge ML moves into systems where latency claims influence architecture, procurement, safety cases, and release gates, measurement discipline becomes part of the system design. A benchmark that looks precise but ignores platform-specific instrumentation overhead can create false confidence.
–––––––––––––––––––––––––––––––––––––––
Resources
Full experimental protocol, raw timing data, and analysis code: github.com/akulswami/cross-platform-ecg-characterization. Underlying preprint: arXiv:2605.02835.
About the Authors
Akul Swami is an independent researcher in runtime assurance for safety-critical edge ML systems, with nine-plus years of embedded software engineering experience in regulated industries. Site: akulswami.github.io. ORCID: 0009-0003-9549-5543.
Nikhil Chougule is an independent researcher focused on embedded systems and edge ML timing characterization.