模型部署之NVIDIA AGX Xavier 配置和使用Torch,ONNX,TensorRT做模型推理

2023-05-16

Do not blindly trust anything I say, try to make your own judgement.


目录

1. 安装CUDA,cudnn,tensorrt

2. 配置Torch

3. 配置ONNX

4. 配置TensorRT

5. 三者性能对比

6. 其他

7.Reference


1. 安装CUDA,cudnn,tensorrt

参考这篇文章的做法,从百度网盘下载别人下载好的cuda,cudnn,python3.6和tensorrt。

  • 该网盘资源安装的CUDA 版本是10.2,一般情况都是够用的。
  • 安装的tensorrt需要对应py3.6,其他版本的python是识别不到所安装的tensorrt的。
  • 安装cudnn的时候会有多行类似的报错:“/sbin/ldconfig.real: /usr/local/cuda-10.2/targets/aarch64 linux /lib /libcudnn_adv_infer.so.8 is not a symbolic link”,对每一个库报错都要执行以下两行命令,以adv_infer报错为例:
    sudo ln -sf /usr/local/cuda-10.2/targets/aarch64-linux/lib/libcudnn_adv_infer.so.8.0.0              /usr/local/cuda-10.2/targets/aarch64-linux/lib/libcudnn_adv_infer.so.8
    
    sudo ln -sf /usr/local/cuda-10.2/targets/aarch64-linux/lib/libcudnn_adv_infer.so.8              /usr/local/cuda-10.2/targets/aarch64-linux/lib/libcudnn_adv_infer.so
  • 安装完CUDA记得要添加环境变量:
    export LD_LIBRARY_PATH=/usr/local/cuda/lib
    export PATH=$PATH:/usr/local/cuda/bin
  • 检查cudnn是否安装成功:

    cat /usr/include/cudnn_version.h | grep CUDNN_MAJOR -A 2
  • archiconda是适用于aarch64架构的conda,但并不太需要,因为如果要涉及用python3和ROS通信的话用conda也解决不了问题,最后还得用docker。但这里也给一个配置archiconda的教程:配置archiconda.

2. 配置Torch

先参考官方教程安装依赖: Install PyTorch on Jetson Nano - Q-engineering

 然后要下载适配aarch64架构的torch和torchvision。第一节配置CUDA和cudnn中提到的百度网盘里有对应py3.6的torch和torchvision,也可以从https://download.pytorch.org/whl/torch/ 这个网站里选择aarch64的torch离线包,还可以从https://torch.kmtea.eu/whl/stable-cn.html 这个网站里下载,这个里面把常用的pip包都自己编译打包成了适配aarch64的.whl文件,非常好用。

安装了CUDA和torch后,可以按yolov3测试CUDA和torch教程测试torch是否能调用GPU。

如果要安装OpenBLAS,可参考如下教程自己编译源码:源码编译OpenBLAS

3. 配置ONNX

pip install onnx
pip install onnxruntime

注意:直接pip install onnxruntime只能下载cpu版本的onnxruntime,如果要下载gpu版本的适配aarch64架构的要去官网下载,尤其注意下载的时候要注意对应python版本和CUDA版本。如果报错“the ort build has [‘’] enabled, you are required to explicitly set the providers parameter when instantiating inferencesession.”,说明CUDA版本对应错了,onnx和CUDA的版本对应关系在NVIDIA - CUDA | onnxruntime中查看。

安装好后,可以在python中调用onnxruntime查看是否能调用GPU。因为onnxruntime分为

>> import onnxruntime as rt
>> rt.get_device()
'GPU'
  • torch转onnx:可参考如下代码:
model = Net()
model_recover = torch.load(pt_model_path, map_location='cuda:0')
model.load_state_dict(model_recover)
model.eval() 
    
# Input to the model
x = torch.randn(1, 2, 3, 256, 341)

# Export the model
torch.onnx.export(model,                     # model being run
                  x,                         # model input 
                  output_onnx,               # where to save the model 
                  verbose=True,
                  export_params=True,        # store the trained parameter weights inside the model file
                  opset_version=10,          # the ONNX version to export the model to
                  do_constant_folding=True,  # whether to execute constant folding for optimization
                  input_names = ['input'],   # the model's input names
                  output_names = ['output'], # the model's output names
                  #dynamic_axes={'input' : {0 : 'batch_size'},    # variable batch size
                  #               'output_0' : {0 : 'batch_size'},
                  #               'output_1' : {0 : 'batch_size'}}
                  )

导出的onnx文件可以用netron查看其表示的模型结构,netron在线网址:Netron 

  • onnx inference:
import onnxruntime as ort

def to_numpy(tensor):
    return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()

model_recover_path = ''
provider = ['CUDAExecutionProvider'] if self.device == 'cuda' else ['CPUExecutionProvider']
ort_session = ort.InferenceSession(model_recover_path, providers=provider)
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(inputs)}
ort_outs = ort_session.run(None, ort_inputs)  # warm up
st = time.time()
ort_outs = ort_session.run(None, ort_inputs)
et = time.time()
print('onnx inference time:', et - st, ' use:', ort.get_device())
  •    还可以对比torch模型和onnx模型推理的精度差别,没有输出说明对比结果能满足rtol相对误差容忍度和atol绝对误差容忍度。
# load torch model and set model to .eval() first
torch_out = torch_model(inputs)

ort_session = ort.InferenceSession(onnx_model_path, providers=['CUDAExecutionProvider'])  
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(inputs)}
ort_outs = ort_session.run(None, ort_inputs)

np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol=1e-03, atol=1e-05)

4.配置TensorRT

  • 需要先安装pycuda,但pip install pycuda的包没法适配aamd64架构,需要自己去pypi搜pycuda然后下载源码并编译,以下命令参考自教程 Jetson Nano 安装pycuda。
    # 从pypi网站下载pycuda源码
    tar zxvf pycuda-2019.1.2.tar.gz    
    cd pycuda-2019.1.2/  
    python3 configure.py --cuda-root=/usr/local/cuda-10.2
    sudo python3 setup.py install
  • onnx转tensorrt:

    用tensorrt自带的trtexec转模型

/usr/src/tensorrt/bin/trtexec --onnx=mymodel.onnx --saveEngine=mymodel.trt --workspace=4000

报错1:onnx2trt_utils.cpp:220: Your ONNX model has been generated with INT64 weights, while TensorRT does not natively support INT64. Attempting to cast down to INT32.

    解决:不影响执行,可以不用管。如果要解决可以用onnx-simplifier将onnx文件再做一次简化。

报错2:Some tactics do not have sufficient workspace memory to run. Increasing workspace size may increase performance, please check verbose output.

     解决:命令行设置较大的workspace如  --workspace=4000

报错3:若使用python时出现“illegal instruction core dumped”

     解决:修改~/.bashrc:  export OPENBLAS_CORETYPE=ARMV8

  • tensorrt inference
def do_tensorrt_inference(inputs, trt_model_path):
    BATCH_SIZE = 1          
    USE_FP16 = False            
    output_dim = 4                             
    target_dtype = np.float16 if USE_FP16 else np.float32  
    f = open(trt_model_path, "rb")                         
    runtime = trt.Runtime(trt.Logger(trt.Logger.WARNING))   
    engine = runtime.deserialize_cuda_engine(f.read())      
    context = engine.create_execution_context() 
    inputs_np = to_numpy(inputs)
    #input_batch = np.random.randn(*inputs_shape).astype(target_dtype)
    output = np.empty([BATCH_SIZE, output_dim], dtype = target_dtype)
    d_input = cuda.mem_alloc(BATCH_SIZE * inputs_np.nbytes)
    d_output = cuda.mem_alloc(BATCH_SIZE * output.nbytes)
    bindings = [int(d_input), int(d_output)]
    stream = cuda.Stream()
    def _predict(inputs): # result gets copied into output
        # transfer input data to device
        cuda.memcpy_htod_async(d_input, inputs, stream)
        # execute model
        context.execute_async_v2(bindings, stream.handle, None)  # async inference.if use sync inference, replace execute_async_v2 byexecute_v2
        # transfer predictions back
        cuda.memcpy_dtoh_async(output, d_output, stream)
        # syncronize threads
        stream.synchronize()
        return output
    output = _predict(inputs_np)  # warm up
    st = time.time()
    output = _predict(inputs_np)
    et = time.time()
    print('tensorrt inference time:', et - st)
    print('tensorrt pred:', output)

5. 三者性能对比

以我的经验来说,onnx对于精度的降低最多在0.00001级几乎没有损失,推理用时一般是torch用时的0.3到0.1倍;tensorrt的推理速度确实很猛,可以到只有onnx用时的十分之一,但精度丢失较多,相对于torch的预测结果精度丢失在0.01级,我这里还没用fp16的混合浮点模式,如果用了fp16则精度丢失应当会更多。因此如果对精度有要求的话,onnx其实就够用了。

放一张推理对比图感受一下区别:

6. 其他

python3环境下调用tf和cv_bridge ros包 / ROS1和python3兼容问题:

在ROS1环境中使用python3,可以通过指定用python3编译脚本,也可以通过创建conda虚拟环境来实现,但这两种方法仍然无法解决python3中import tf和cv_bridge这两个包;当然还有一种办法是装一个docker环境,在docker里安装ROS-noetic,因为noetic版本开始都是ROS2,是用python3编译的,而docker里的ROS2可以与docker外的ROS1自动通信,但这种方法需要装docker因此比较麻烦。tf和cv_bridge原本只在python2中可以用,而ROS1是python2编译的,如果要改到ROS2即python3中使用,则要下载源码自己编译(可参考解决python3无法使用ROS中tf的问题 - 知乎,其中如果遇到No module named em的报错,则尝试pip install empy, pip3 install empy, pip install python-empy, pip3 install python3-empy 这四个命令一定可以解决;cv_bridge的编译同理,找相似文章即可)。

但更简单的方法是去https://rospypi.github.io/simple/网址下载whl包,用pip的方式安装ros包,里面的pip包是同时支持py2,py3的,非常方便,很多包都不需要经过ros下载了。(该方法亲测只能在ROS2环境下安装tf和cv_bridge,在ROS1中安装使用仍会报错,解决办法还是得用上述python3源码编译。)

7. Reference

jetson agx xavier:从亮机到yolov5下tensorrt加速_Eva20150932的博客-CSDN博客_jetpack4.6 安装onnx-simplifier

xavier nx 安裝cuda, cudnn, tensorrt, opencv, 中文輸入法 - wangaolin - 博客园jetson agx xavier:从亮机到yolov5下tensorrt加速_Eva20150932的博客-CSDN博客_jetpack4.6 安装onnx-simplifierxavier nx 安裝cuda, cudnn, tensorrt, opencv, 中文輸入法 - wangaolin - 博客园

Jetson Xavier NX手动安装cuda和cudnn_All will be well的博客-CSDN博客_jetson cuda安装

英伟达Jetson xavier agx的GPU部署yolov5 - stacso - 博客园

TensorRT/onnx_to_tensorrt.py at master · NVIDIA/TensorRT · GitHub

ONNX简易部署教程_51CTO博客_lilishop部署教程

tensorRT踩坑日常之engine推理_静待有缘人的博客-CSDN博客

ubuntu18.04 安装OpenBLAS_Mountain Q的博客-CSDN博客_linux安装openblas

Jetson Nano安装pycuda(踩坑传)_doubleZ0108的博客-CSDN博客_nano pycuda

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模型部署之NVIDIA AGX Xavier 配置和使用Torch,ONNX,TensorRT做模型推理 的相关文章

随机推荐

  • C++中原生数组、STL的vector、STL的array的区别

    文章目录 一 数组一维数组一维数组初始化一维数组元素的引用 二 STL的arrayC 43 43 STL array随机访问迭代器 xff08 精讲版 xff09 begin end 和 cbegin cend rbegin rend 和
  • Docker 入门教程

    推荐两篇阮一峰老师的文章 xff0c 网上看了很多Docker教程 xff0c 发现还是这个让我理解了什么是Docker xff0c 怎么用Docker Docker 入门教程 Docker 微服务教程 再放一个比较全的Docker教程 x
  • 【C/C++服务器开发】中间件的含义及常用中间件介绍

    文章目录 一 中间件的定义中间件一词的由来中间件的定义什么不是中间件评判关键中间件的好处中间件分类常用基础中间件中间件云产品 二 中间件的开发什么是中间件开发 xff1f 中间件开发人员需要哪些素质 xff1f 如何成为中间件开发人员 xf
  • source insight查看函数调用关系(总结全网资料)

    有时候我们去查看一个项目的源代码时 xff0c 一般都会想先知道函数之间的调用关系 xff0c 之前一般都是自己在笔记本上画出来 xff0c 但这是一个效率很低的方法 xff0c source insight提供了查看函数调用关系的功能 因
  • C/C++字符串基础,类型,使用方法大全(字符,字符串,字符数组,字符串函数,C++ string)

    文章目录 一 前言二 C C 43 43 字符串1 字符字符的表示字符的输出字符与整数 2 字符和字符串编码源文件使用什么编码窄字符串使用什么编码总结 3 ASCII编码了解对控制字符的解释 4 C语言转义字符5 在C语言中使用中文字符中文
  • Redis基础,Linux下安装Redis和hredis,C++调用Redis,Redis中字符串设计

    文章目录 一 Redis是什么Redis架构Redis优势Redis应用场景 二 Linux下载安装Redis xff08 Ubuntu系统 xff09 了解Redis版本在线安装Redis启动Redis服务端启动Redis客户端验证是否成
  • Redis数据结构

    昨天刚写了一个Redis的文章之后 xff0c 后面发现了一个大佬写了一篇关于Redis数据结构的文章 推荐一些 xff1a 为了拿捏 Redis 数据结构 xff0c 我画了 20 张图
  • Redis配置项汇总(超级详细)

    文章目录 查看配置项更改配置项更改配置文件配置项说明基本配置主从服务配置安全配置限制配置AOF日志模式慢查询配置服务端命令客户端命令连接命令 在 Redis 的安装目录中有一个名为 redis windows conf 的配置文件 xff0
  • navicat查看保存的密码

    参考 xff1a 查看Navicat保存的密码 Micky233 博客园 cnblogs com https www cnblogs com geek233 p 16772618 html
  • Redis常用命令及C/C++调用Redis接口详解

    文章目录 一 Redis常用命令启动Redis服务端启动Redis客户端Redis常用命令详解键 xff08 Key xff09 命令Hash 命令String 命令List 命令Set 命令Zset 命令 二 C C 43 43 调用接口
  • Redis数据结构2

    继续放一下小林coding的文章 xff1a 为了拿捏 Redis 数据结构 xff0c 我画了 40 张图 xff08 完整版 xff09
  • Redis博客、教程学习资料汇总(持续更新)

    在这篇博客中 xff0c 总结一下写过的博客和一些好的学习资料 博客 xff1a Redis基础 xff0c Linux下安装Redis和hredis xff0c C 43 43 调用Redis xff0c Redis中字符串设计 Redi
  • memcached在linux上的安装,C/C++调用memcached,memcached与Redis的区别

    文章目录 一 memcached在linux上的安装安装 Memcached自动安装源代码安装 Memcached 运行 xff08 1 xff09 作为前台程序运行 xff1a xff08 2 xff09 作为后台服务程序运行 xff1a
  • 【C/C++服务器开发】事件驱动、事件驱动架构、事件驱动编程及设计模式

    文章目录 一 事件驱动二 事件驱动编程事件驱动和异步IO看图说话讲事件驱动模型 三 C C 43 43 实现事件驱动四 常用的C C 43 43 事件驱动库 一 事件驱动 首先我们来看看百度百科的介绍 所谓事件驱动 xff0c 简单地说就是
  • VxWorks消息队列详解

    文章目录 一 前言二 VxWorks消息队列模块详解三 代码实例 一 前言 最近看了点事件驱动编程 了解到在时间驱动编程中 xff0c 重要的是一个事件收集器 一个事件发送器和一个事件处理器 这让我联想到VxWorks中的消息队列 xff0
  • VxWorks/tornado中怎么调试及WindSh常用命令行详解

    一 调试 VxWorks5 5 tornado2 2作为一款极为远古的嵌入式实时操作系统和IDE xff0c 软件的界面和功能都是极为原始的 在这种情况下 xff0c 如果我们要对软件进行调试该怎么操作呢 xff1f tornado调试分为
  • 如何长期输出优质内容?我是如何做到的?

    分享一篇站长的文章 xff1a 如何长期输出优质内容 xff1f 我是如何做到的 xff1f 创业 7 年时间里 xff0c 我一直在运营C语言中文网 xff0c 创作和参与了 40 多套编程教材 xff0c 累计阅读人次超过 2000 万
  • Dev C++调试程序方法详解

    分享一篇站长的关于调试的文章 xff1a Dev C 43 43 调试程序方法详解 Dev C 43 43 算是兼容性很好使用很方便的IDE了 xff0c 记录一下调试方法 xff0c 以备不时之需 所谓调试程序 xff0c 就是控制编译器
  • 为什么看到这么多人不推荐C++?

    转一个回答 链接 xff1a https www zhihu com question 22853451 answer 2084675682 其实现在也越来越发现 xff0c C 43 43 老是在弄那些语言特性 xff0c 当然有一些好用
  • 模型部署之NVIDIA AGX Xavier 配置和使用Torch,ONNX,TensorRT做模型推理

    Do not blindly trust anything I say try to make your own judgement 目录 1 安装CUDA cudnn tensorrt 2 配置Torch 3 配置ONNX 4 配置Ten