TensorRT
TensorRT compila un grafo en un engine ajustado a una GPU concreta. LibreYOLO exporta primero un intermedio ONNX, lo parsea con el parser de ONNX de TensorRT, construye el engine y escribe los metadatos del modelo a su lado como un sidecar JSON.
- Flag
export(format="tensorrt")- Escribe
- Un archivo .engine más un sidecar de metadatos .engine.json
- Extra
pip install "libreyolo[onnx,tensorrt]"- Se recarga con
LibreYOLO("weights/LibreYOLO9t.engine")- Formas
- Estáticas por defecto; dynamic=True añade un perfil de optimización sobre el eje de batch
- Precisión
- FP32, FP16 (half=True), INT8 (int8=True con data=)
- Requiere
- Una GPU NVIDIA al construir y al ejecutar. Los engines no se mueven entre arquitecturas de GPU.
Instalación
Tanto la construcción como la ejecución necesitan una GPU NVIDIA con un stack de CUDA funcional. No hay respaldo por CPU para este formato.
# El engine se construye a partir de un intermedio ONNX, así que hacen falta ambos extras.pip install "libreyolo[onnx,tensorrt]"python -c "import tensorrt, torch; print(tensorrt.__version__, torch.cuda.is_available())"El extra tensorrt fija tensorrt-cu12 y pycuda, y el marcador descarta ambos
en macOS. En una Jetson, no uses ese extra: fija una build de CUDA 12 contra una
plataforma CUDA 13. Usa en su lugar el TensorRT que instala JetPack, como se
describe en NVIDIA Jetson.
Exportación
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Escribe weights/LibreYOLO9t_fp16.engine y weights/LibreYOLO9t_fp16.engine.jsonpath = model.export(format="tensorrt", half=True)print(path)libreyolo export --model LibreYOLO9t.pt --format tensorrt --halfmodel.export( format="tensorrt", imgsz=640, batch=1, half=False, int8=False, data=None, # obligatorio cuando int8=True dynamic=False, workspace=4.0, # GiB de memoria de trabajo al construir min_batch=1, # límites del perfil dinámico opt_batch=1, max_batch=8, hardware_compatibility="none", # o "ampere_plus" gpu_device=0, # dispositivo de construcción en un host multi-GPU verbose=False,)La exportación se ejecuta en dos pasos. El primero escribe un intermedio ONNX en
una ruta temporal, el segundo lo parsea y construye el engine, y después se elimina
el intermedio. workspace es memoria de trabajo en tiempo de construcción, en GiB;
un valor mayor deja al builder probar más kernels y no afecta a la memoria de
inferencia.
El sidecar de metadatos se escribe junto al engine como <engine>.json y registra
la precisión que la build consiguió realmente. Cuando la GPU no tiene FP16 rápido
ni INT8 rápido, el builder avisa y recurre a otra precisión, y el sidecar informa
de la precisión que salió, no de la que se pidió.
Con FP16, si hay un backbone ViT en el grafo se detecta y sus capas float se fijan
a FP32. Los backbones de tipo DINOv2 desbordan en FP16 y producen NaN, así que la
build activa OBEY_PRECISION_CONSTRAINTS e informa de FP16 (FP32 ViT backbone).
La pasada no hace nada sobre backbones CNN.
Batch dinámico
from libreyolo import LibreYOLO # El intermedio ONNX necesita el eje de batch dinámico para que el perfil# tenga algo a lo que enlazarse.LibreYOLO("LibreYOLO9t.pt").export( format="tensorrt", dynamic=True, min_batch=1, opt_batch=4, max_batch=8, half=True,)dynamic=True añade un perfil de optimización que va de min_batch a max_batch,
optimizado en opt_batch, y registra esos tres valores en el sidecar. El perfil
solo se añade cuando el intermedio ONNX lleva realmente una dimensión de batch
dinámica; en caso contrario, la build registra que está usando optimización
estática y continúa.
INT8
from libreyolo import LibreYOLO LibreYOLO("LibreYOLO9t.pt").export( format="tensorrt", int8=True, data="coco128.yaml", # obligatorio: no hay valor por defecto en este formato fraction=1.0,)INT8 usa el calibrador de entropía de TensorRT sobre un loader de calibración de
LibreYOLO, y data es obligatorio: este formato no tiene el respaldo de ocho
imágenes. La calibración necesita cuda-python o pycuda para el buffer del
dispositivo. La caché de calibración se indexa por un hash de los bytes del ONNX,
así que las escalas de un modelo nunca se reutilizan para otro que dé la casualidad
de escribir en la misma ruta de salida.
half=True e int8=True juntos avisan y construyen INT8, que mantiene un respaldo
FP16 para las capas que TensorRT no puede cuantizar.
Ejecutar el artefacto
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t_fp16.engine")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])import json import tensorrt as trt path = "weights/LibreYOLO9t_fp16.engine"runtime = trt.Runtime(trt.Logger(trt.Logger.WARNING))with open(path, "rb") as handle: engine = runtime.deserialize_cuda_engine(handle.read()) for i in range(engine.num_io_tensors): name = engine.get_tensor_name(i) print(engine.get_tensor_mode(name), name, engine.get_tensor_shape(name)) # Los nombres de clase, la tarea y el tamaño de entrada viven en el sidecar, no en el engine.# La reserva de buffers, el preprocesado y el posprocesado corren de tu cuenta aquí.print(json.load(open(path + ".json"))["names"])LibreYOLO() despacha según el sufijo .engine, lee del sidecar los nombres de
clase, la tarea y el esquema de pose, y devuelve el mismo objeto Results que el
checkpoint. Lanza un error de inmediato cuando no hay ningún dispositivo CUDA
presente.
El segundo snippet es la ruta del runtime a secas. La reserva de buffers de host y de dispositivo, el preprocesado, la decodificación, el NMS y el reescalado de coordenadas corren todos de tu cuenta, y el engine en sí no lleva nombres de clase, así que el sidecar tiene que viajar con él.
Restricciones
Un engine serializado queda atado a la arquitectura de GPU, al stack de drivers y a
la versión de TensorRT que lo construyó. Un engine construido en una estación de
trabajo no cargará en una arquitectura distinta, y por eso el paso de construcción
se ejecuta en la máquina de despliegue. hardware_compatibility="ampere_plus" cede
algo de rendimiento a cambio de portabilidad entre Ampere y posteriores. El valor
"same_compute_capability" se mapea a NONE y avisa: el engine está optimizado
solo para la GPU actual, y la exportación lo dice en lugar de afirmar una
portabilidad que no aplicó.
Solo se perfila el eje de batch. Una build con dimensiones espaciales dinámicas no forma parte de este contrato, y por eso FCOS está bloqueado: necesita alto y ancho con padding dinámico para conservar su transformación de aspecto de 800 por 1333.
Bloqueados antes del trazado: la segmentación de YOLO9, la segmentación de
RTMDet-Ins, la detección de SSD, Faster R-CNN y RetinaNet, y el matting de BiRefNet
o FeyNobg, donde TensorRT 10.16 llega al nodo ONNX compartido DeformConv y no
puede parsearlo porque ModulatedDeformConv2d no está en el registro de plugins.
Cuando una combinación no está ni validada ni bloqueada, la ruta del conversor está disponible y el proyecto no ha registrado paridad de runtime en TensorRT para ella. Eso es una afirmación sobre la evidencia, no sobre si la build tiene éxito.
Para la rejilla completa de familias y tareas, consulta la matriz de exportación. Para una combinación concreta:
libreyolo formats --family yolo9 --task detect