void inference(const string& image_path) {
TRTLogger logger;
auto engine_data = load_file("classifier.trtmodel");
auto runtime = make_nvshared(nvinfer1::createInferRuntime(logger));
auto engine = make_nvshared(runtime->deserializeCudaEngine(engine_data.data(), engine_data.size()));
if (engine == nullptr) {
printf("Deserialize cuda engine failed.\n");
runtime->destroy();
return;
if (engine->getNbBindings() != 2) {
printf("Must be single input, single Output, got %d output.\n", engine->getNbBindings() - 1);
return;
cudaStream_t stream = nullptr;
checkRuntime(cudaStreamCreate(&stream));
auto execution_context = make_nvshared(engine->createExecutionContext());
int input_batch = 1;
int input_channel = 3;
int input_height = 224;
int input_width = 224;
int input_numel = input_batch * input_channel * input_height * input_width;
float* input_data_host = nullptr;
float* input_data_device = nullptr;
checkRuntime(cudaMallocHost(&input_data_host, input_numel * sizeof(float)));
checkRuntime(cudaMalloc(&input_data_device, input_numel * sizeof(float)));
float mean[] = {0.406, 0.456, 0.485};
float std[] = {0.225, 0.224, 0.229};
auto image = cv::imread(image_path);
cv::resize(image, image, cv::Size(input_width, input_height));
int image_area = image.cols * image.rows;
unsigned char* pimage = image.data;
float* phost_b = input_data_host + image_area * 0;
float* phost_g = input_data_host + image_area * 1;
float* phost_r = input_data_host + image_area * 2;
for (int i=0; i<image_area; ++i, pimage += 3) {
*phost_r++ = (pimage[0] / 255.0f - mean[0]) / std[0];
*phost_g++ = (pimage[1] / 255.0f - mean[1]) / std[1];
*phost_b++ = (pimage[2] / 255.0f - mean[2]) / std[2];
checkRuntime(cudaMemcpyAsync(input_data_device, input_data_host, input_numel *sizeof(float), cudaMemcpyHostToDevice, stream));
const int num_classes = 1000;
float output_data_host[num_classes];
float* output_data_device = nullptr;
checkRuntime(cudaMalloc(&output_data_device, sizeof(output_data_host)));
auto input_dims = engine->getBindingDimensions(0);
input_dims.d[0] = input_batch;
execution_context->setBindingDimensions(0, input_dims);
float* bindings[] = {input_data_device, output_data_device};
bool success = execution_context->enqueueV2((void**)bindings, stream, nullptr);
checkRuntime(cudaMemcpyAsync(output_data_host, output_data_device, sizeof(output_data_host), cudaMemcpyDeviceToHost, stream));
checkRuntime(cudaStreamSynchronize(stream));
float* prob = output_data_host;
int predict_label = max_element(prob, prob + num_classes) - prob;
float conf = prob[predict_label];
printf("test_image: %s, max_idx: %d, probability: %f", image_path.c_str(), predict_label, conf);
checkRuntime(cudaStreamDestroy(stream));
checkRuntime(cudaFreeHost(input_data_host));
checkRuntime(cudaFree(input_data_device));
checkRuntime(cudaFree(output_data_device));
最终得到输出:
test_image: test.jpg, max_idx: 971, probability: 0.994527
与之前 pytorch 和 onnx 推理的结果基本一致,模型转换成功。
给出完整的参考代码:https://github.com/Adenialzz/Hello-AIDeployment/tree/master/HAID/tensorrt/resnet
首先,无论是python还是
C++,我们都要写一个自己的plugin,一般的不支持op网上都有参考的版本,写plugin的参考教程:如何写好一个op
C++实现和使用
过程:
下载
TensorRT官网源码, 进入plugin可以看到许多已经定义好的插件可以参考,照着写就行,以ScatterND为例。
先写好自己的plugin,如名为:myplugin
注意:此处plugin代码里面不能包含REGISTER_
TENSORRT_PLUGIN(MyPluginCreator)代码,不然会导致重复注册的问题。
一文掌握Pytorch-onnx-tensorrt模型转换pytorch转onnx
pytorch转onnx
对于实际部署的需求,很多时候pytorch是不满足的,所以需要转成其他模型格式来加快推理。常用的就是onnx,onnx天然支持很多框架模型的转换,
如Pytorch,tf,darknet,caffe等。而pytorch也给我们提供了对应的接口,就是torch.onnx.export。下面具体到每一步。
首先,环境和依赖:onnx包,cuda和cudnn,我用的版本号分别是1.7.0, 10.1
TensorRT是NVIDIA推出的一款高效
深度学习模型推理框架,其包括了
深度学习推理优化器和运行时,能够让
深度学习推理应用拥有低时延和高吞吐的优点。
本质上来讲,就是通过采用对
模型中的部分算子进行融合、对特定尺寸的算子选用更好的
实现方法,以及使用混合精度等方式,最终加速整个网络的
推理速度。
在使用
PyTorch训练得到网络
模型后,我们希望在
模型部署时通过
TensorRT加速
模型推理,那么可以先将
PyTorch模型转为
ONNX,然后再讲
ONNX转为
TensorRT的engine。
实现步骤
RuntimeError: [enforce fail at inline_container.cc:145] . PytorchStreamReader failed reading zip arc
13585