GÖREV KAYDI

GÖREV KAYDI

KAYIT AÇIK

ATILIM UAV · YER KONTROL İSTASYONU

GÖREV KAYDI / DETAY

Arşiv

CANLI · OKUMA MODU

Gömülü Sistemler

TensorRT ile Çıkarımı Hızlandırmak: FP16 Engine'ler ve Jetson Optimizasyonu

TensorRT ile Çıkarımı Hızlandırmak: FP16 Engine'ler ve Jetson Optimizasyonu

FIG. 01

KAYIT KÜNYESİ

Kategori

Gömülü Sistemler

TARİH

TÜM KAYITLAR

Uçuş öncesi son testte kameradan gelen kare ile ekrana çizilen kutu arasındaki gecikmeyi gözle görebiliyorsanız, sorun genelde modelin doğruluğu değil, modelin nasıl çalıştırıldığıdır. Bizim durumumuzda YOLO11m, Jetson Orin NX 16GB üzerinde 640 pikselde tam-kare çıkarım yaparken 15-20 FPS veriyor. Bu, 20 m irtifadan hedef tespiti için yeterli; ama aynı hat aynı anda SIYI A8 mini'den gelen 1080p RTSP akışını çözmek, FastMosaic'in kare biriktirmesine izin vermek ve pymavlink telemetrisini işlemek zorunda. GPU'da harcadığımız her milisaniye başka bir işten kesiliyor.

PyTorch'ta eğitilmiş bir .pt dosyası aslında bir tariften ibarettir: her katman ayrı ayrı, Python yorumlayıcısının gözetiminde, genel amaçlı çekirdekler üzerinde çalışır. Masaüstü bir RTX kartında bunun bedelini hiç fark etmezsiniz. 10-25 W güç zarfının içinde yaşayan bir modülde ise aynı bedel doğrudan FPS olarak karşınıza çıkar.

Bu yazı, modele hiç dokunmadan hız kazanmanın en doğrudan yolunu anlatıyor: NVIDIA TensorRT ile derlenen .engine dosyaları. Bir de burada en sık çiğnenen kuralı: engine dosyası taşınabilir bir model formatı değildir.

TensorRT tam olarak ne yapıyor?

TensorRT bir çıkarım derleyicisidir. Eğitilmiş bir ağ grafiğini alır ve hedef GPU'ya göre biçilmiş bir yürütme planı üretir. NVIDIA'nın saydığı temel teknikler şunlar:

  • Katman ve tensör füzyonu: Conv + BatchNorm + aktivasyon gibi ardışık işlemler tek bir GPU çekirdeğinde birleştirilir. Her füzyon, bir çekirdek başlatması ve bellekle bir gidiş-dönüş daha az demek.

  • Hassasiyet kalibrasyonu: ağırlıkların ve ara sonuçların FP16 ya da INT8 gibi daha dar sayı formatlarında tutulması. Tensor Core'lar bu formatlarda belirgin biçimde daha hızlıdır.

  • Çekirdek otomatik ayarı: her katman için en hızlı aday CUDA çekirdeği, tam olarak o kart üzerinde alınan gerçek ölçümlere bakılarak seçilir.

  • Dinamik tensör belleği: ara tensörlerin belleği, ömürleri çakışmayan katmanlar arasında yeniden kullanılır.

Yazının ilerisindeki kritik kural işte üçüncü maddeden çıkıyor. TensorRT tahmin etmiyor; hedef GPU üzerinde ölçüyor, sonra karar veriyor.

FP32, FP16, INT8: doğruluğu hıza takas etmek

Ultralytics Jetson kılavuzundaki Orin NX 16GB sayıları bu takası net biçimde gösteriyor. Aşağıdaki tablo bizim YOLO11m'imize değil, dökümantasyonda referans alınan YOLO26n modeline ait ve 640 piksel girdiyle ölçülmüş; ama formatlar arasındaki oranlar aynı şekilde okunuyor (2026 itibarıyla):

Format

Çıkarım (ms)

mAP50-95

Ne zaman tercih edilir

PyTorch (.pt)

13.90

0.4799

Geliştirme, hata ayıklama, hızlı denemeler

TorchScript

11.60

0.4787

Python bağımlılığından kurtulmak isteyip TensorRT kuramadığınızda

ONNX

14.18

0.4763

Taşınabilirlik gerektiğinde; Jetson'da hız için değil

TensorRT FP32

7.01

0.4770

Doğruluk riskini sıfırda tutmak istediğiniz doğrulama koşuları

TensorRT FP16

4.13

0.4789

Uçuş konfigürasyonu: varsayılan tercihimiz

TensorRT INT8

3.49

0.4489

Kare bütçesi gerçekten sıkışıksa ve doğruluk kaybı ölçülmüşse

Burada okunmaya değer üç oran var. TensorRT FP32 bile PyTorch'tan kabaca 2x daha hızlı; yani hassasiyeti hiç düşürmeden atılan ilk adım bile kendini ödüyor. FP16'ya geçmek bunun üstüne yaklaşık 1.7x daha ekliyor ve bu tabloda mAP'e ölçülebilir bir zarar vermiyor. INT8 ise FP16'nın üstüne yalnızca ~1.2x getirirken mAP50-95'i 0.479'dan 0.449'a, yaklaşık 3 puanlık bir kayıpla çekiyor.

Biz FP16'da karar kıldık. 20 m'den küçük hedefleri yakalamaya çalışan bir tespit hattında 3 puanlık mAP, 0.6 ms uğruna verilecek bir taviz değil.

.pt → ONNX → .engine hattı

Ultralytics dışa aktarıcısı ara grafik olarak ONNX kullanıyor; opset argümanı da buna işliyor. Tek bir komut işi görüyor:

# Run this ON the Jetson itself
yolo export model=best.pt format=engine imgsz=640 quantize=16 batch=1 workspace=4
# Run this ON the Jetson itself
yolo export model=best.pt format=engine imgsz=640 quantize=16 batch=1 workspace=4

Aynı şey Python tarafında:

from ultralytics import YOLO

model = YOLO("best.pt")
model.export(format="engine", imgsz=640, quantize=16, batch=1)

# The inference side does not change at all
trt = YOLO("best.engine")
results = trt("frame.jpg", conf=0.25)
from ultralytics import YOLO

model = YOLO("best.pt")
model.export(format="engine", imgsz=640, quantize=16, batch=1)

# The inference side does not change at all
trt = YOLO("best.engine")
results = trt("frame.jpg", conf=0.25)

Önemli bir API değişikliği: eski half=True ve int8=True bayrakları quantize=16 ve quantize=8 şekline taşındı. Eskiler hâlâ kabul ediliyor ama kullanımdan kaldırma uyarısı basıyor (2026 itibarıyla). En sık başvuracağınız argümanlar:

Argüman

Varsayılan

Ne işe yarar

quantize

None

Hassasiyet: 32, 16 ya da 8

imgsz

640

Engine'e gömülen girdi boyutu

batch

1

Azami izin verilen batch boyutu

dynamic

False

Değişken girdi boyutu profili

workspace

None

Derleme sırasında GiB cinsinden azami çalışma alanı

data

None

INT8 kalibrasyonu için veri seti yapılandırması

fraction

1.0

Kalibrasyonda kullanılacak veri seti oranı

Kritik kural: engine hedef cihazda derlenmeli

Ultralytics dökümantasyonu bunu açıkça söylüyor: TensorRT, engine'i hangi GPU'da derliyorsa onun üzerinde profilleyip ayarlıyor; dolayısıyla .engine taşınabilir bir model formatı gibi görülmemeli. NVIDIA tarafındaki gerekçe daha da keskin. Varsayılan olarak serileştirilmiş bir plan dosyası üç şeye kilitlidir:

  1. Derlendiği TensorRT sürümü. Bu bilgi planın içine yazılır ve yükleme anında kontrol edilir.

  2. GPU'nun compute capability değeri. Ana ve alt sürüm numaraları plana yazılır ve yüklenirken karttaki değerle doğrulanır.

  3. Platform. İşletim sistemi ve CPU mimarisi de sabittir; x86 bir masaüstünde derlenmiş bir plan, ARM tabanlı bir Jetson'da açılmaz.

NVIDIA bu kısıtları gevşetmek için bayraklar sunuyor: VERSION_COMPATIBLE, kAMPERE_PLUS (Ampere ve sonrasındaki tüm mimariler) ve kSAME_COMPUTE_CAPABILITY. Hepsi, cihaza özel bir engine'e kıyasla performanstan götürebilir. Pratik sonuç değişmiyor: uçacak kartın üzerinde derleyin, .engine dosyalarını sürüm kontrolüne sokmayın ve bunları CI'da üretip sahaya göndermeye kalkmayın.

Sabit girdi boyutu mu, dinamik mi?

Varsayılan olarak engine sabit girdiyle derlenir: imgsz ve batch planın içine gömülür. dynamic=True değişken boyutlu bir profil açar; INT8 dışa aktarımlarında ise zaten varsayılan olarak etkindir.

Seçenek

Ne zaman

Bedeli

Sabit (dynamic=False)

Tek ve değişmeyen bir çıkarım boyutu

Farklı bir boyut denemek istediğinizde her seferinde yeniden derleme

Dinamik (dynamic=True)

Tam kare artı kırpma/tiling gibi karışık boyutlar

Optimizasyon profilinin dışındaki boyutlarda düşük hız

batch argümanının bir üst sınır belirttiğini aklınızda tutun: daha küçük batch'ler kabul edilir, daha büyükleri hata verir.

imgsz çıkarım hattıyla eşleşmeli

Bunu zor yoldan öğrendik. Modeli imgsz=1280 ile eğitiyoruz, ama uçuşta tam kareyi 640'ta işliyoruz. Eğitim değeri bu diye engine'i 1280'de derlerseniz, çıkarım hattı 640 gönderdiğinde ya bir şekil (shape) uyuşmazlığı hatası ya da sessiz bir yeniden ölçekleme alırsınız; ölçtüğünüz hız da gerçekte aldığınız hız olmaz.

Kural basit: engine'in imgsz değeri, uçuşta ona gerçekten verdiğiniz tensörün boyutu olmalı. Bunu eğitim çözünürlüğüyle karıştırmayın. Ayrıca farklı bir çözünürlükte tiling da yapıyorsanız ya her boyut için ayrı bir engine derleyin ya da dynamic=True kullanıp profil aralığını bilerek seçin.

INT8'e geçiyorsanız kalibrasyon verisi

INT8, eğitim sonrası niceleme (post-training quantization) ile çalışır ve aktivasyon aralıklarını öğrenmek için gerçek veriye ihtiyaç duyar. NVIDIA en az 500 temsil edici kalibrasyon görüntüsü öneriyor. Ultralytics tarafında bunu data argümanını bir veri seti yapılandırmasına yönlendirerek yapıyorsunuz; fraction ile de bir alt küme alabiliyorsunuz.

yolo export model=best.pt format=engine imgsz=640 quantize=8 \
     data=suas_aerial.yaml fraction=0.5 batch=1
yolo export model=best.pt format=engine imgsz=640 quantize=8 \
     data=suas_aerial.yaml fraction=0.5 batch=1

Buradaki asıl yükü "temsil edici" ifadesi taşıyor. Kalibrasyon setiniz webden toplanmış yakın çekim fotoğraflardan oluşuyorsa, 20 m'den çekilmiş küçük hedeflerin aktivasyon aralıkları hiç görünmez ve saha performansı doğrulama metriğinizin vaat ettiğinden kötü çıkar. Kalibrasyon bir .cache dosyası üretir; veri seti ya da batch boyutu belirgin biçimde değiştiğinde bu dosyayı silin, yoksa eski aralıklar yeniden kullanılır.

Sık düşülen hatalar

  • Masaüstünde derleyip Jetson'a kopyalamak. En sık yapılan hata. Ya bir yükleme hatası ya da mimari uyuşmazlığı alırsınız. İkisi de uçuş sabahında isteyeceğiniz türden bir sürpriz değil.

  • JetPack yükseltmesinden sonra engine'i yeniden derlememek. JetPack kendi TensorRT ve CUDA sürümlerini de beraberinde getirir; eski bir plan yeni çalışma zamanında açılmayabilir.

  • Eğitimdeki imgsz ile dışa aktarımdaki imgsz değerini karıştırmak. Ölçtüğünüz FPS'in hangi çözünürlüğe ait olduğunu bilmeden optimizasyon yapmış olursunuz.

  • Güç modunu ayarlamadan ölçüm almak. sudo nvpmodel -m 0 ve sudo jetson_clocks çalıştırılmadan alınan sayılar kartın gerçek tavanını göstermez. Sıcaklığı ve saat frekansını jtop ile izlemek de işe yarar.

  • DLA'yı bedava hız sanmak. Orin NX 16GB'de 614 MHz'de çalışan 2 DLA çekirdeği var; ama DLA öncelikle iş hacmini ve enerji verimliliğini hedefler, GPU'ya kıyasla gecikmeyi düşürmek gibi bir yükümlülüğü yoktur. Üstelik TensorRT 11.0'da DLA desteklenmiyor; DLA dışa aktarımı TensorRT 10.x istiyor (2026 itibarıyla).

  • Doğrulama koşusu yapmadan INT8'e geçmek. Nicelenmiş engine'i her zaman kendi doğrulama setinizde yeniden ölçün. Yalnızca havadan görüntülerden oluşan doğrulama setimizdeki 0.950'lik mAP50 değeri FP32 modeline ait; INT8'den sonra aynı sayıyı varsaymak yanlış olur.

Pratik özet

  1. Engine'i her zaman uçacak Jetson üzerinde derleyin. .engine dosyasını depoya koymayın, derleme adımını kurulum betiğinize ekleyin.

  2. Varsayılanınız FP16 (quantize=16) olsun. Referans ölçümlerde PyTorch'un ~3x hızını, ölçülebilir bir doğruluk kaybı olmadan veriyor.

  3. Dışa aktarımdaki imgsz ve batch değerlerini eğitim çözünürlüğüne değil, çıkarım hattınızın gerçekte gönderdiği tensöre birebir uydurun.

  4. INT8'i yalnızca kare bütçeniz gerçekten sıkışıksa düşünün; en az 500 temsil edici görüntüyle kalibre edin ve doğrulama setinizdeki mAP kaybını ölçerek karar verin.

  5. Her hız ölçümünü nvpmodel -m 0 + jetson_clocks sonrasında, kart ısındıktan sonra alın. JetPack ya da Ultralytics sürümü her değiştiğinde engine'i yeniden derleyin ve ölçümü tekrarlayın.

©2026 ATILIM UAV TEAM

©2026 ATILIM UAV TEAM