0%

Nvidia Orin NX搭建Pytorch环境教程

1 前情提要

最近接到任务要把之前在寒武纪MLU220上部署的ERFNet网络重新部署到Nvidia Orin NX上去,因此记录一下环境搭建过程,以及在此过程中遇到的一些问题。

2 环境搭建过程

2.1 Anaconda安装

跑不同的CNN网络需要不同的环境,所以Anaconda基本是要首先安装的,这里的安装过程与x86端基本一致,只需要注意安装包需要选择Linux-aarch64版本的,这里附上Anaconda版本列表地址。具体安装过程不再赘述。

2.2 Cuda, cuDNN安装

由于本人拿到的Orin板子中已经安装好了Cuda和cuDNN,所以这个安装过程就无法展开来讲了,只会针对cuDNN的一些后续操作进行详细说明。

值得注意的是,参考该文章中的说法,千万不要直接安装Cuda官网上最新的Cuda-Jetson-12.0,这可能会导致机子黑屏,需要刷机才可解决。该文章推荐的方法是直接安装Jetpack:

  • Jetpack是Nvidia专为Jetson系列嵌入式AI和运算平台开发的软件开发工具包,包含了操作系统、CUDA工具包、深度学习、视觉库等组件,方便开发者能够高效地在Jetson设备上开发、部署和优化AI应用。

那么安装Jetson后就可以直接安装上适配的Cuda、cuDNN、TensorRT等软件。如果不确定本机是否安装了Jetson,可以通过jetson_release命令来查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ jetson_release
Software part of jetson-stats 4.3.0 - (c) 2024, Raffaello Bonghi
Model: NVIDIA Orin NX Developer Kit - Jetpack 5.1.4 [L4T 35.6.0]
NV Power Mode[3]: 25W
Serial Number: [XXX Show with: jetson_release -s XXX]
Hardware:
- P-Number: p3767-0000
- Module: NVIDIA Jetson Orin NX (16GB ram)
Platform:
- Distribution: Ubuntu 20.04 focal
- Release: 5.10.216-tegra
jtop:
- Version: 4.3.0
- Service: Active
Libraries:
- CUDA: 11.4.315
- cuDNN: 8.6.0.166
- TensorRT: 8.5.2.2
- VPI: 2.4.8
- Vulkan: 1.3.204
- OpenCV: 4.10.0 - with CUDA: NO

该命令在后续安装Pytorch时也需要使用,此处先mark一下。也可使用ncvv -V命令查看安装的Cuda版本信息:

1
2
3
4
5
6
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Sun_Oct_23_22:16:07_PDT_2022
Cuda compilation tools, release 11.4, V11.4.315
Build cuda_11.4.r11.4/compiler.31964100_0

可以看到本机安装的是cuda-11.4。虽然Cuda经测试是正常的,不过该机子之前应该没人搭建过CNN开发环境,所以对于cuDNN还需要进一步处理:将其对应的头文件、库文件放到Cuda目录。此处同样参考了该文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#复制文件到cuda目录下
cd /usr/include && sudo cp cudnn* /usr/local/cuda/include
cd /usr/lib/aarch64-linux-gnu && sudo cp libcudnn* /usr/local/cuda/lib64

#修改文件权限,修改复制完的头文件与库文件的权限,所有用户都可读,可写,可执行:
sudo chmod 777 /usr/local/cuda/include/cudnn.h
sudo chmod 777 /usr/local/cuda/lib64/libcudnn*

#重新软链接,这里的8.4.1和8对应安装的cudnn版本号和首数字
cd /usr/local/cuda/lib64

sudo ln -sf libcudnn.so.8.4.1 libcudnn.so.8

sudo ln -sf libcudnn_ops_train.so.8.4.1 libcudnn_ops_train.so.8
sudo ln -sf libcudnn_ops_infer.so.8.4.1 libcudnn_ops_infer.so.8

sudo ln -sf libcudnn_adv_train.so.8.4.1 libcudnn_adv_train.so.8
sudo ln -sf libcudnn_adv_infer.so.8.4.1 libcudnn_adv_infer.so.8

sudo ln -sf libcudnn_cnn_train.so.8.4.1 libcudnn_cnn_train.so.8
sudo ln -sf libcudnn_cnn_infer.so.8.4.1 libcudnn_cnn_infer.so.8

sudo ldconfig

完成之后即可对cuDNN进行测试:

1
2
3
4
5
sudo cp -r /usr/src/cudnn_samples_v8/ ~/
cd ~/cudnn_samples_v8/mnistCUDNN
sudo chmod 777 ~/cudnn_samples_v8
sudo make clean && sudo make
./mnistCUDNN

如果出现”Test passed!” 即表明安装成功。

2.3 Pytorch, torchvision安装

2.3.1 Pytorch

本人在安装Pytorch时遇到了问题(虽然是一个小问题,但还是卡住了好久才搞定……),此处记录一下。

同样地,Pytorch版本是需要根据机子环境进行确定的,刚才通过jetson_release命令查看了本机的Jetpack版本号是Jetpack 5.1.4 [L4T 35.6.0],根据Nvidia官方版本对应列表查找可以安装的版本,这里是第一个坑,也是导致自己后来无法准确定位错误原因的一个关键点:在官方列表中找不到Jetpack 5.1.4 [L4T 35.6.0]这个版本……

那就在这里面找几个试一下呗,然后就出现了问题:下载完wheel文件(或直接到该网址寻查对应版本文件链接),使用如下命令安装,然后就出现了报错:

1
2
$ pip install https://developer.download.nvidia.com/compute/redist/jp/v51/pytorch/torch-2.0.0a0+8aa34602.nv23.03-cp38-cp38-linux_aarch64.whl
ERROR: torch-2.0.0a0+8aa34602.nv23.03-cp38-cp38-linux_aarch64.whl is not a supported wheel on this platform.

把图中几个都试了一下都是同样的报错,本人脑子中第一个想法就是这个列表不完整,缺少Jetpack 5.1.4 [L4T 35.6.0]这个版本对应的文件。于是乎,找到Nvidia Jetson Pytorch官网教程,按照步骤一步步来,最后到该网址寻查对应版本文件链接:

那应该就是要使用v51中的版本了吧,同样的报错内容……

此时,开始停下来思考原因,之前在网上搜索相关报错内容,发现几乎没有相同的报错情况,根据Jetson平台的广泛应用情况,说明这应该不是一个通用的问题,那肯定是自己操作中的问题。突然想到Python版本信息;其实在Nvidia官方版本对应列表中已经注意到Python3.8的标示,但是根据之前在x86端的部署经验,Pytorch对于Python版本要求并不严格,所以刚才自己也没有注意。此时也是无计可施,那就重新创建一个Python3.8的版本试一下吧,结果一下子就顺利安装了……唉,卡了几个小时的问题就这么轻易解决了,问题竟然出在Python版本上了,不多说了,以后肯定老老实实按照各种版本信息来部署环境了,要不然浪费的时间成本有点高。

2.3.2 torchvision

相较于Pytorch的安装来说,torchvision安装过程就顺利得多了。安装所需的依赖软件、clone工程文件、编译安装即可:

1
2
3
4
5
6
7
sudo apt-get update
sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev libavcodec-dev libavformat-dev libswscale-dev

git clone --branch <version> https://github.com/pytorch/vision torchvision #<version>看下表选择,我的是v0.16.0
cd torchvision
export BUILD_VERSION=0.x.0 # where 0.x.0 is the torchvision version
python3 setup.py install --user

这里附上torchvision仓库,以及版本对照表:

编译安装时间会比较长,安装完之后进入python环境,import torchvision测试一下,缺少哪些软件使用pip或conda安装即可。这里顺带记录一下opencv安装时的问题,根据文章指出有两种安装方法:

1
2
3
sudo apt-get install python3-opencv
# or
conda install -n your-env-name opencv

本人测试后使用第二种方法有效。

3 问题记录

安装过程中的问题在上一节中已经记录了,这里记录一个在程序运行中遇到的问题。

3.1 undefined symbol: TIFFReadRGBATileExt, version LIBTIFF_4.0

搭建完环境后运行rospy程序时出现如下报错:

1
2
3
4
5
6
7
8
9
10
11
12
Traceback (most recent call last):
File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 750, in _invoke_callback
cb(msg)
File "main.py", line 133, in satelliteMapCallback
ground_image_array = bridge.imgmsg_to_cv2(ground_image_msg, "bgr8")
File "/opt/ros/noetic/lib/python3/dist-packages/cv_bridge/core.py", line 163, in imgmsg_to_cv2
dtype, n_channels = self.encoding_to_dtype_with_channels(img_msg.encoding)
File "/opt/ros/noetic/lib/python3/dist-packages/cv_bridge/core.py", line 99, in encoding_to_dtype_with_channels
return self.cvtype2_to_dtype_with_channels(self.encoding_to_cvtype2(encoding))
File "/opt/ros/noetic/lib/python3/dist-packages/cv_bridge/core.py", line 91, in encoding_to_cvtype2
from cv_bridge.boost.cv_bridge_boost import getCvType
ImportError: /lib/libgdal.so.26: undefined symbol: TIFFReadRGBATileExt, version LIBTIFF_4.0

参考该文章,报错原因可能是系统中存在多个libtiff.so.5库,但此处使用的libtiff.so.5库中没有LIBTIFF_4.0,可通过find命令查询libtiff.so.5库路径:

1
2
3
4
5
$ sudo find / -name "libtiff.so.5*" 2>/dev/null
/snap/gnome-42-2204/201/usr/lib/aarch64-linux-gnu/libtiff.so.5
...
/usr/lib/aarch64-linux-gnu/libtiff.so.5.5.0
/usr/lib/aarch64-linux-gnu/libtiff.so.5

可在程序执行前运行或在.bashrc中添加该命令:

1
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libtiff.so.5

3.2 Orin NX端语义分割性能下降问题

这是之前遇到过的老问题了,ROS通过cv_bridge接收到的图像是BGR格式的,而PIL默认使用RGB格式的,所以需要利用cv2.cvtColor转换一下颜色通道。

1
2
3
4
5
6
# 修改颜色空间转换顺序
cv_img = bridge.imgmsg_to_cv2(msg, "bgr8")
# OpenCV的BGR转为RGB
rgb_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
pil_img = PILImage.fromarray(rgb_img)
input_tensor = self.input_transform(pil_img).unsqueeze(0)

记录一下不同图片读取方式的色彩通道。

image-20250521125404575