Ultralytics YOLO27:
Ultralytics YOLO in Production·Choose a Runtime·Lesson 1/9
Lessonintermediate

Choose a Deployment Target

Turn the device, the latency budget, and the fleet into one runtime and export format, then confirm it on the device.

Traffic camera above a city highway at sunset, with Ultralytics YOLO tracking cars, a van, and trucks, each labeled with a class and ID

The same YOLO26n takes 38.9 ms per image on a CPU with ONNX Runtime and 1.7 ms on a T4 GPU with TensorRT in the YOLO26 benchmarks. Pick the wrong runtime and you either pay for far more hardware than you need or ship cameras that cannot keep up. This lesson turns the choice into a ten-minute decision you can defend with numbers measured on the device itself.

Outcome

Pick the runtime and format= value for a device, convert an FPS target into a millisecond budget, and confirm the choice with repeated benchmarks.

Fast Track
If you already know your way around, here's the short version.
  1. NVIDIA GPU or Jetson → TensorRT (engine), built on the target. Intel CPU, iGPU, or NPU → OpenVINO (openvino).

  2. Apple → CoreML (coreml). Android → LiteRT (litert). Snapdragon NPU → QNN (qnn). Raspberry Pi → NCNN (ncnn).

  3. Anything else → ONNX Runtime (onnx). No servers wanted → a managed Ultralytics Platform endpoint.

  4. Budget = 1000 ÷ FPS, minus decode and postprocessing. Time candidates on the device and judge their p95, not the average.

Hands-on

Start From the Device#

The runtime follows from where inference runs, not from habit. Walk the tree from the top and stop at the first match:

Each runtime maps to one format= value in Export mode:

TargetRuntimeformat=Watch out for
NVIDIA GPU, JetsonTensorRTengineAn engine only runs on the GPU family and TensorRT version that built it
Intel CPU, iGPU, NPUOpenVINOopenvinoTuned for Intel; measure before using it elsewhere
Any CPU or GPUONNX RuntimeonnxChoose the execution provider explicitly
iPhone, iPad, MacCoreMLcoremlExport runs on macOS or Linux, not Windows
Android, embeddedLiteRTlitertINT8 needs calibration data
Snapdragon NPUQualcomm QNNqnnQuantized export only; pass the Hexagon target as name
Raspberry Pi, ARM CPUNCNNncnnThe fastest format in the Raspberry Pi guide
BrowserONNX Runtime WebonnxKeep to n or s models

On recent Apple platforms you can also export Apple's newer Core AI format (format=coreai, exported on macOS 26+ Apple silicon or x86-64 Linux). New to exporting? The Export for Deployment lesson covers the basics.

If you would rather not run inference servers at all, Ultralytics Platform deploys a model as a dedicated endpoint in one of 42 regions, and your profile's Deployments tab maps where each one runs:

Ultralytics Platform profile Deployments tab with a world map of deployment regions and overview cards for active deployments, HTTP requests, error rate, and P95 latency

That path is covered in Deploy and Call an Endpoint. The rest of this course is for when you run the model yourself.

Turn the FPS Target Into a Millisecond Budget#

"Real time" is not a requirement; a number is. Work it out before you benchmark anything:

StepExample: 20 FPS per camera
Frame budget = 1000 ÷ FPS50 ms
Minus decode (RTSP, 1080p)about 10 ms
Minus tracking, counting, sinksabout 5 ms
Minus 20% headroom for peaks10 ms
Left for the modelabout 25–30 ms

Then apply these decision rules:

  • If YOLO26n needs more than your model budget on the device's CPU, move to an accelerator (GPU, iGPU, NPU) or shrink imgsz before anything else; the YOLO26 benchmarks list YOLO26n at 38.9 ms on CPU ONNX and 1.7 ms on a T4 with TensorRT.
  • If one device must serve several cameras, divide the model budget by the camera count.
  • If the fleet has more than a handful of device types, prefer runtimes that do not need per-device builds, or plan a build per device class.
  • If the calling code is Swift, Kotlin, or C++, check the runtime's SDK for that language before committing.

Benchmark the Candidates on the Device#

Spec sheets and other people's benchmarks are a starting point. The decision is made on the hardware you will deploy, and by the slow frames, not the average: a runtime that is fast at the median but stalls on one frame in twenty will still drop frames. This script exports each candidate, times 100 inferences on a real frame, and judges each by its 95th percentile (p95):

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

BUDGET_MS = 30  # the model's share of a 20 FPS frame budget
CANDIDATES = ("onnx", "openvino")  # runtimes the decision tree allows on this machine

if __name__ == "__main__":  # exports and inference can start worker processes on macOS and Windows
    frame = str(safe_download("https://ultralytics.com/images/bus.jpg"))  # use a real frame from your camera
    for fmt in CANDIDATES:
        model = YOLO(YOLO("yolo26n.pt").export(format=fmt))
        for _ in range(5):  # warm up: the first calls include one-time setup
            model(frame, verbose=False)
        runs = sorted(model(frame, verbose=False)[0].speed["inference"] for _ in range(100))
        p50, p95 = runs[49], runs[94]
        verdict = "meets" if p95 <= BUDGET_MS else "misses"
        print(f"{fmt:9s} p50 {p50:5.1f} ms  p95 {p95:5.1f} ms  {verdict} the {BUDGET_MS} ms budget")

On the Apple silicon laptop used to test this course, while other jobs shared the CPU:

onnx      p50  30.0 ms  p95  46.4 ms  misses the 30 ms budget
openvino  p50  22.8 ms  p95 113.5 ms  misses the 30 ms budget

Read it line by line:

  • speed["inference"] is the model's own time for that frame, without decoding or drawing, so it compares runtimes fairly.
  • OpenVINO wins the median and loses the p95 by a factor of more than two. Judged on averages, you would ship the runtime that stalls on busy moments; judged on p95, ONNX Runtime is the steadier choice on this machine.
  • Both miss the budget, so the next move here is a smaller imgsz, an accelerator, or fewer cameras per device, not another CPU runtime.

For a quick accuracy-and-speed sweep across formats, Benchmark mode exports, validates, and times each one:

yolo benchmark model=yolo26n.pt data=coco8.yaml imgsz=640 format=onnx

Drop format= to sweep every format the machine supports. COCO8 has only four validation images, so treat its mAP column as a smoke test and use your own dataset YAML for accuracy decisions.

Pitfalls#

Benchmarking on the wrong machine

Symptom: the model hit 60 FPS on your workstation and drops frames on the device. Fix: benchmark on the deployment hardware, or the closest machine you can get, and run it under the load it will see in production (other processes, other cameras).

TensorRT engines are device-specific

Symptom: an .engine built on a data-center GPU fails to load on a Jetson Orin. Fix: build on the target at install time (a YOLO26n FP16 build takes about 5 minutes on a Jetson Orin, per the Platform export docs), or keep one build per device class and TensorRT version, and ship the .pt or .onnx so any device can rebuild.

Benchmark at the size you'll serve

yolo benchmark measures at the imgsz you pass. If production runs at imgsz=1280, benchmark at 1280: compute grows with pixel count, so 640 numbers understate a 1280 deployment about 4×.

Edge Devices Add Four Questions#

The Raspberry Pi, NVIDIA Jetson, and DeepStream on Jetson guides cover the common targets in detail. Before you commit to an edge box, answer:

  • Cold start: where is the TensorRT engine built, and who waits for it?
  • Power and heat: can the enclosure sustain the model at full FPS all day?
  • Memory: is there room for frame buffers and tracker state next to the model? INT8 halves the model's share.
  • Updates: how does a new best.pt reach 1,000 devices? A Docker image keeps them consistent.
Try It

Write a five-line deployment brief for a real or planned project: target device, FPS per camera, cameras per device, calling language, and fleet size. Convert it into a model budget in milliseconds, pick candidates from the decision tree, and run pick_runtime.py (with your model and the candidates) on the target or the closest machine you have.

Done When
You've finished the lesson when all of these are true.
  • Your brief names the device, the runtime, and the exact format= value.

  • You derived the model's millisecond budget from the FPS target, showing what you subtracted.

  • You have p50 and p95 inference times for each candidate, measured on the device, and a verdict against the budget.

Show solution

A worked brief for a retail analytics rollout:

QuestionAnswer
Device40 in-store mini PCs with Intel Core Ultra CPUs, no discrete GPU
FPS and cameras10 FPS per camera, 2 cameras per box
CallerPython service on Linux
Fleet40 boxes, updated from a Docker image

Budget: 1000 ÷ 10 = 100 ms per frame; minus about 15 ms for decode and tracking and 20% headroom leaves about 65 ms, shared by two cameras, so about 30 ms per inference. The decision tree says OpenVINO (Intel CPU), with ONNX Runtime as the fallback, so on one store box:

python pick_runtime.py  # CANDIDATES = ("onnx", "openvino"), BUDGET_MS = 30

The Core Ultra 7 155H CPU benchmark in the OpenVINO docs puts YOLO26n at 13.4 ms with OpenVINO FP32, so yolo26n should fit with room to spare; if the p95 on the real box, with both camera pipelines running, is under 30 ms, ship OpenVINO. If it misses, try the box's integrated GPU with device="intel:gpu" before buying hardware.

What's next

With a target chosen, the next lesson exports to ONNX and proves the export gives the same answers as PyTorch.