Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Get Started
Ultralytics YOLO in produzione·Scala e osservazione·Lezione 9/9
Lezioneintermedio

Ottimizzazione di costi e latenza

Esegui la profilazione dell'intera pipeline, aziona nell'ordine le leve che incidono davvero su latenza e costo e fermati al raggiungimento del budget.

I team perdono settimane per limare millisecondi al modello, mentre il vero collo di bottiglia è una scrittura sul database o un decoder RTSP. Le leve principali sono poche e ben misurate: YOLO26s impiega 2.2 volte più tempo di YOLO26n su CPU per ottenere 7.7 punti mAP in più, mentre eseguire il rilevamento un fotogramma sì e uno no dimezza il lavoro. In questa lezione imparerai a eseguire prima la profilazione, azionare la leva più efficace tra quelle adatte e fermarti al budget che hai stabilito in anticipo.

Esito

Esegui la profilazione end-to-end di una pipeline, applica una leva e confronta latenza e mAP prima e dopo, quindi giustifica il punto in cui ti sei fermato.

Percorso rapido
Se sai già come muoverti, ecco la versione breve.
  1. Esegui prima la profilazione: le fasi di r.speed più le misurazioni dei tempi di decodifica e di output della tua pipeline.

  2. Leve, in ordine: modello più piccolo → imgsz più piccolo → runtime più veloce e FP16 → INT8 → vid_stride.

  3. Misura latenza e mAP prima e dopo ogni modifica, sull'hardware di destinazione e usando lo stesso set di convalida.

  4. Definisci prima il budget (giorni, perdita di mAP, FPS obiettivo); quando lo esaurisci, migliora i dati.

Pratico

Misura prima l'intera pipeline#

Ogni oggetto Results suddivide il proprio tempo in fasi:

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
totals = {"preprocess": 0.0, "inference": 0.0, "postprocess": 0.0}
for n, r in enumerate(model.predict(video, stream=True, verbose=False), 1):
    for stage in totals:
        totals[stage] += r.speed[stage]
print({stage: round(ms / n, 1) for stage, ms in totals.items()}, "ms per frame")
{'preprocess': 0.7, 'inference': 36.1, 'postprocess': 0.7} ms per frame

Qui l'inferenza occupa il 95% del tempo del modello, quindi le leve relative al modello saranno utili. Misura allo stesso modo i tempi di decodifica e di output della tua pipeline (inserendo time.perf_counter() attorno a ciascuna fase), poi applica la regola corrispondente a ciò che rilevi:

MisurazionePrimo intervento
60 ms per decodificare RTSP, 5 ms per l'inferenzaDecodifica hardware, risoluzione inferiore del flusso o più thread del decoder
30 ms per l'inferenza, 100 ms per la post-elaborazione in PythonVettorizza con NumPy o sposta l'elaborazione in un processo worker
5 ms per l'inferenza, 200 ms per le scritture sul databaseRaggruppa le scritture o rendile asincrone
L'inferenza è il fattore dominanteLa classifica delle leve qui sotto

La classifica delle leve#

Prova le opzioni partendo dall'alto e fermati quando raggiungi il budget:

SoluzioneAumento di velocità tipicoCosto tipico in termini di precisione
Modello più piccolo (m → s, s → n)1.5–2.5×4.5–7.7 punti mAP su COCO; meno nei task specifici
imgsz più piccolo (640 → 480)circa 1.8×Prima gli oggetti piccoli e lontani
Runtime più veloce, FP16circa 1.5× su GPUDi solito nessuno; verifica la parità
INT8 con calibrazioneun ulteriore 1.2× su GPU; fino a 2.9× su CPU1 punto (YOLO26n) fino a 4–6 punti (modelli più grandi); QAT recupera gran parte della perdita
Meno fotogrammi (vid_stride=N)fino a N×Si possono perdere oggetti veloci ed eventi brevi
Batch più grande (server)Più throughput, non meno latenzaNessuna

I valori provengono dalle tabelle dei benchmark di YOLO26, TensorRT e OpenVINO, oltre che dalle misurazioni qui sotto; i tuoi risultati saranno diversi, quindi misura.

Modello più piccolo#

La tabella dei benchmark di YOLO26 su COCO:

ModellomAP50-95CPU ONNX (ms)T4 TensorRT10 (ms)
YOLO26n40.938.91.7
YOLO26s48.687.22.5
YOLO26m53.1220.04.7

Su CPU, ogni passaggio al modello più piccolo è 2.2–2.5× più veloce. La differenza di precisione su COCO rappresenta il caso peggiore: un rilevatore per magazzino a 3 classi con oggetti grandi di solito perde molto meno passando da m a n rispetto a un rilevatore generalista a 80 classi, quindi vale sempre la pena provare il modello più piccolo sul proprio set di convalida.

Input più piccolo#

Il calcolo aumenta all'incirca in proporzione al numero di pixel, quindi imgsz=480 richiede circa il 56% del lavoro rispetto a 640. Misurazione eseguita sulla CPU del laptop di prova con ONNX Runtime e batch 1 (mediana di 25 esecuzioni su bus.jpg):

Modello640480320
YOLO26n21.3 ms12.1 ms7.1 ms
YOLO26s55.0 ms24.2 ms12.9 ms

Criterio decisionale: se l'oggetto importante più piccolo occupa ancora circa 10 pixel o più alla nuova dimensione, prova questa opzione; se gli oggetti sono piccoli o lontani (droni, scaffali distanti dalla telecamera), mantieni la risoluzione e riduci il modello.

Meno fotogrammi#

Se l'inferenza limita il frame rate e la scena si muove lentamente, esegui il rilevamento a ogni N-esimo fotogramma con vid_stride=N e lascia che il tracker colmi gli intervalli:

import time

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
model.predict(video, vid_stride=30, verbose=False)  # warm up so the first timing is fair

for stride in (1, 2, 3):
    start, ids, frames = time.perf_counter(), set(), 0
    for r in model.track(video, stream=True, vid_stride=stride, tracker="bytetrack.yaml", classes=[0], verbose=False):
        frames += 1
        if r.boxes.is_track:
            ids.update(r.boxes.id.int().tolist())
    print(f"vid_stride={stride}: {frames} frames in {time.perf_counter() - start:.2f} s, {len(ids)} person IDs")
vid_stride=1: 62 frames in 2.66 s, 32 person IDs
vid_stride=2: 31 frames in 1.19 s, 30 person IDs
vid_stride=3: 20 frames in 0.95 s, 28 person IDs

Usare la metà dei fotogrammi richiede circa la metà del tempo e il tracker ha mantenuto 30 identità su 32. Con vid_stride=3 ne ha perse 4: per questa scena con persone che camminano, è il segnale che indica di fermarsi.

Riduci i costi del cloud#

Panoramica della distribuzione su Ultralytics Platform: 59 richieste HTTP in 24 ore, tasso di errore dello 0%, latenza P95 di 226 ms e un endpoint con 1 vCPU e 4 GiB in us-west2 al costo di $0.17 all'ora

Il costo è dato dalle ore di utilizzo dell'istanza divise per il lavoro utile. Una scheda come questa mostra i due valori che ti servono: il costo orario ($0.17 per 1 vCPU e 4 GiB in questo caso) e il lavoro svolto (59 richieste in 24 ore a una latenza P95 di 226 ms: un endpoint perlopiù inattivo). Poi:

  • Aumenta l'utilizzo. Una GPU con un utilizzo del 30% spreca il 70% della spesa. Raggruppa i flussi (come spiegato nelle lezioni precedenti) o servi le richieste tramite Triton Inference Server.
  • Scegli la dimensione giusta. Esegui benchmark su una GPU più piccola o su una CPU con OpenVINO prima di dare per scontato di averne bisogno di una grande.
  • Usa capacità spot o prerilasciabile per i job batch. La rielaborazione di video archiviati tollera le interruzioni; i flussi live no.

Insidie#

Ottimizzare il modello quando non è il collo di bottiglia

Sintomo: due settimane di ottimizzazione hanno fatto risparmiare 10 ms, ma il sistema è ancora lento. Soluzione: analizza prima le prestazioni dell'intera pipeline e intervieni sullo stadio più lento, qualunque esso sia.

Saltare fotogrammi dopo l'inferenza

Sintomo: inserire if i % 2: continue nel ciclo dei risultati non fa risparmiare nulla. Soluzione: il modello ha già elaborato quel fotogramma; salta i fotogrammi alla sorgente con vid_stride.

Usare batch per ridurre la latenza

Sintomo: il throughput è aumentato, ma ora ogni fotogramma arriva più tardi. Soluzione: batch più grandi aumentano il throughput per dollaro, non riducono la latenza per fotogramma; usali per molti flussi o per processi offline, non per una singola telecamera in tempo reale.

La leva dei dati

Quando hai esaurito le leve di ottimizzazione del modello, il passo successivo è migliorare i dati. Un dataset che rispecchia la produzione permette a un modello più piccolo di raggiungere l'accuratezza che prima richiedeva un modello più grande: costi inferiori senza perdita di accuratezza.

Provalo

Definisci un budget di ottimizzazione (giorni, perdita massima di mAP, FPS obiettivo sull'hardware di destinazione). Profila la pipeline con r.speed e le tue misurazioni di decodifica e sink, individua la leva più efficace per il collo di bottiglia, applicala e registra latenza e mAP50-95 prima e dopo, sullo stesso hardware e sullo stesso set di validazione. Consegna il budget, il profilo, la tabella comparativa e indica quando ti sei fermato.

Conferma
git add -A && git commit -m "perf(production): tuned model + runtime for target latency budget"
Criteri di completamento
La lezione è completata quando tutte le seguenti condizioni sono soddisfatte.
  • Sai quale fase incide maggiormente sul tempo end-to-end per frame, e hai i dati per dimostrarlo.

  • Hai applicato una leva e registrato latenza e mAP prima e dopo, sullo stesso hardware e sullo stesso set di validazione.

  • Ti sei fermato al budget che avevi stabilito e sai dire cosa proveresti dopo.

Mostra la soluzione
from ultralytics import YOLO

if __name__ == "__main__":  # validation starts worker processes on macOS and Windows
    data, img = "coco8.yaml", "https://ultralytics.com/images/bus.jpg"  # use your val YAML and a production frame
    for weights, imgsz in (("yolo26s.pt", 640), ("yolo26n.pt", 640), ("yolo26n.pt", 480)):
        model = YOLO(weights)
        runs = [model(img, imgsz=imgsz, verbose=False)[0].speed["inference"] for _ in range(20)][5:]
        m = model.val(data=data, imgsz=imgsz, batch=1, plots=False, verbose=False).box.map
        print(f"{weights} imgsz={imgsz}: {sorted(runs)[len(runs) // 2]:.1f} ms, mAP50-95 {m:.3f}")

Ogni riga esclude le prime cinque esecuzioni come fase di riscaldamento e riporta la mediana delle restanti. Scegli la prima riga che rispetta il budget di latenza con una perdita di mAP entro il limite stabilito. Un esempio di budget concreto: "due giorni, al massimo 1 punto di mAP, 20 FPS sul computer del negozio". Se yolo26s a 640 supera i 50 ms per frame e yolo26n a 640 rispetta il limite entro 1 punto sul tuo set di validazione, fermati lì; non dedicare il secondo giorno alla risoluzione 480.

Prossimi passi

Corso completato. Sostieni l'esame per ottenere il certificato, poi prosegui con Crea con Ultralytics Platform, che esegue questo flusso di lavoro come sistema end-to-end gestito.

Accedi per salvare i progressi