| name | tensorrt-deployment |
| description | TensorRT 部署技能 - ONNX 转换、Engine 构建、INT8 量化、ROS2 加速推理 |
| argument-hint | TensorRT OR ONNX OR INT8 OR GPU加速 OR tensorrt deployment |
| user-invocable | true |
TensorRT 部署技能
NVIDIA Jetson/Desktop GPU 推理加速
何时使用
当需要以下帮助时使用此技能:
- ONNX 模型转 TensorRT
- FP16/INT8 量化
- Engine 优化
- Jetson 部署
- CUDA 流处理
核心实现
ONNX 转 TensorRT
import tensorrt as trt
import onnx
class TensorRTConverter:
def __init__(self, logger_level=trt.Logger.WARNING):
self.logger = trt.Logger(logger_level)
self.builder = trt.Builder(self.logger)
def convert_onnx_to_engine(self, onnx_path, engine_path, fp16=True, int8=False):
"""ONNX 转 TensorRT Engine"""
network = self.builder.create_network(
1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
parser = trt.OnnxParser(network, self.logger)
with open(onnx_path, 'rb') as f:
parser.parse(f.read())
config = self.builder.create_builder_config()
if fp16:
config.set_flag(trt.BuilderFlag.FP16)
if int8:
config.set_flag(trt.BuilderFlag.INT8)
config.int8_calibrator = self.create_calibrator()
engine = self.builder.build_serialized_network(network, config)
with open(engine_path, 'wb') as f:
f.write(engine)
return engine
def create_calibrator(self):
"""创建 INT8 校准器"""
return INT8Calibrator()
INT8 量化
class INT8Calibrator(trt.IInt8Calibrator):
def __init__(self, calibration_data, batch_size=8):
self.calibration_data = calibration_data
self.batch_size = batch_size
self.cache_file = 'calibration.cache'
def get_batch(self, names):
"""获取校准批次"""
return self.calibration_data[:self.batch_size]
def get_batch_size(self):
return self.batch_size
def read_calibration_cache(self):
"""读取缓存"""
if os.path.exists(self.cache_file):
with open(self.cache_file, 'rb') as f:
return f.read()
def write_calibration_cache(self, cache):
"""写入缓存"""
with open(self.cache_file, 'wb') as f:
f.write(cache)
ROS2 TensorRT 节点
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <cv_bridge/cv_bridge.hpp>
#include <opencv2/opencv.hpp>
#include <cuda_runtime.h>
class TensorRTNode : public rclcpp::Node {
public:
TensorRTNode() : Node("tensorrt_node") {
loadEngine("/path/to/model.engine");
cudaMalloc(&device_input_, BATCH_SIZE * INPUT_SIZE);
cudaMalloc(&device_output_, BATCH_SIZE * OUTPUT_SIZE);
sub_ = create_subscription<sensor_msgs::msg::Image>(
"/image", 10,
std::bind(&TensorRTNode::callback, this, std::placeholders::_1));
pub_ = create_publisher<sensor_msgs::msg::Image>("/output", 10);
}
private:
void loadEngine(const std::string& engine_path) {
std::ifstream file(engine_path, std::ios::binary);
file.seekg(0, std::ios::end);
size_t size = file.();
file.(, std::ios::beg);
* trt_model = [size];
file.(trt_model, size);
file.();
runtime_ = nvinfer1::(logger_);
engine_ = runtime_->(trt_model, size);
context_ = engine_->();
}
{
cv::Mat image = cv_bridge::(msg)->image;
cv::Mat resized;
cv::(image, resized, cv::(, ));
* input_data = (resized);
(device_input_, input_data, INPUT_SIZE * (),
cudaMemcpyHostToDevice);
context_->(device_ptrs_);
output[BATCH_SIZE * OUTPUT_SIZE];
(output, device_output_, OUTPUT_SIZE * (),
cudaMemcpyDeviceToHost);
results = (output);
pub_->(results);
}
{
input[INPUT_SIZE];
input;
}
* device_input_;
* device_output_;
* device_ptrs_[];
nvinfer1::IRuntime* runtime_;
nvinfer1::ICudaEngine* engine_;
nvinfer1::IExecutionContext* context_;
};