第三章 环境搭建:Docker 容器化部署、CUDA/cuDNN 版本管理、conda 环境隔离
说实话,模型移植这件事,十次有八次的坑都出在环境上。
我见过太多团队,模型在 A 机器上跑得飞起,换到 B 机器直接报错。CUDA 版本不对、cuDNN 不兼容、Python 包冲突……这些破事能把人逼疯。
所以这一章,咱们就把环境搭建这件事彻底聊透。你想想看,如果连地基都不稳,上面盖的楼再漂亮也没用。
3.1 Docker 容器化部署:一次封装,到处运行
Docker 这东西,说白了就是把你的整个运行环境打包成一个「箱子」。你带着这个箱子去任何机器上,都能原样跑起来。
我个人习惯,每个项目都从 Dockerfile 开始写。这样团队新成员来了,直接 docker build 就完事,不用折腾半天环境。
核心思路: 把操作系统、CUDA、cuDNN、Python、依赖库全部写进 Dockerfile,生成镜像。以后部署就是拉镜像、跑容器。
下面是我常用的一个 Dockerfile 模板,专门给模型移植用的:
# 基础镜像选 nvidia 官方提供的,自带 CUDA 和 cuDNN
FROM nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04
# 设置非交互模式,避免安装时卡住
ENV DEBIAN_FRONTEND=noninteractive
# 安装系统依赖
RUN apt-get update && apt-get install -y \
python3.8 \
python3-pip \
wget \
git \
&& rm -rf /var/lib/apt/lists/*
# 设置 Python 软链接
RUN ln -s /usr/bin/python3.8 /usr/bin/python
# 安装 Python 包
COPY requirements.txt /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements.txt
# 设置工作目录
WORKDIR /workspace
# 默认命令
CMD ["/bin/bash"]
小技巧: 我建议把 requirements.txt 单独 COPY,而不是和代码一起 COPY。这样可以利用 Docker 的缓存机制——只要 requirements.txt 没变,就不会重新安装依赖包,能省不少时间。
构建和运行命令也很简单:
# 构建镜像
docker build -t model-porting:v1 .
# 运行容器,挂载当前目录到容器内
docker run --gpus all -it --rm \
-v $(pwd):/workspace \
model-porting:v1
这里有个坑,我踩过好几次——--gpus all 这个参数。老版本的 Docker 不支持,得装 nvidia-container-toolkit。我曾经在客户现场折腾了俩小时才发现是这个问题。
注意: 如果你用的是 Docker 19.03 之前的版本,需要手动安装 nvidia-docker2。新版本直接用 --gpus 参数就行。
3.2 CUDA/cuDNN 版本管理:别让版本坑了你
模型移植最头疼的事之一,就是 CUDA 版本不匹配。
你想想看,PyTorch 1.13 要求 CUDA 11.7,TensorRT 8.5 要求 CUDA 11.8,而你的机器上装的是 CUDA 12.0……这就很尴尬了。
我的做法是:用 conda 管理 CUDA 工具包,而不是装系统级的 CUDA。
具体来说,你可以通过 conda 安装指定版本的 CUDA 和 cuDNN:
# 创建环境并指定 CUDA 版本
conda create -n porting_env python=3.8
conda activate porting_env
# 安装 CUDA 工具包(注意不是驱动)
conda install cudatoolkit=11.8 -c nvidia
# 安装 cuDNN
conda install cudnn=8.6.0 -c nvidia
这样做的好处是:不同项目可以用不同的 CUDA 版本,互不干扰。
下面这张表是我整理的常见框架和 CUDA 版本的对应关系,你可以参考:
| 框架 | 推荐 CUDA 版本 | 推荐 cuDNN 版本 | 备注 |
|---|---|---|---|
| PyTorch 1.13 | 11.7 | 8.5 | 兼容 11.6-11.8 |
| PyTorch 2.0 | 11.8 | 8.7 | 推荐用 11.8 |
| TensorFlow 2.12 | 11.8 | 8.6 | 官方只支持 11.8 |
| TensorRT 8.5 | 11.8 | 8.6 | 必须匹配 |
| ONNX Runtime 1.15 | 11.8 | 8.6 | GPU 版本需要 |
重要提醒: 系统级的 NVIDIA 驱动版本必须 >= 你安装的 CUDA 工具包所需的最低驱动版本。比如 CUDA 11.8 需要驱动版本 >= 520.61.05。这个可以用 nvidia-smi 查看。
3.3 Conda 环境隔离:每个项目一个独立小世界
conda 这东西,我刚开始用的时候觉得麻烦,后来真香了。
为什么?因为 Python 的包依赖管理实在太乱了。A 项目要 numpy 1.21,B 项目要 numpy 1.24,没有 conda 的话,你只能二选一。
我的标准流程是这样的:
- 创建环境:每个项目一个独立环境,命名规则是
项目名_python版本 - 安装依赖:先用 conda 装,conda 没有的再用 pip
- 导出环境:项目完成后导出 environment.yml,方便别人复现
具体操作:
# 创建环境
conda create -n yolo_porting python=3.8
# 激活环境
conda activate yolo_porting
# 安装 PyTorch(用 conda 装,会自动处理 CUDA 依赖)
conda install pytorch=1.13.1 torchvision=0.14.1 cudatoolkit=11.7 -c pytorch
# 安装其他依赖
pip install onnx onnxruntime-gpu tensorrt
# 导出环境配置
conda env export > environment.yml
别人拿到你的 environment.yml 后,直接运行:
conda env create -f environment.yml
就能复现一模一样的运行环境。
个人经验: 我建议把 conda 和 pip 混用的情况降到最低。如果非要用 pip,记得在 conda 装完所有能装的包之后,再用 pip 装剩下的。顺序搞反了容易出问题。
3.4 三剑客组合:Docker + Conda + CUDA 版本管理
你可能会问:这三者到底怎么配合?
我的做法是:Docker 管操作系统和驱动层,conda 管 Python 和框架层。
具体来说:
- Docker 镜像里装好系统级的 CUDA 驱动和 cuDNN
- 容器启动后,在容器内部用 conda 创建项目环境
- 每个项目用不同的 conda 环境,互不干扰
这样即使同一个 Docker 镜像,也能跑多个不同依赖的项目。
我曾经在一个项目里,需要同时跑 PyTorch 1.13 和 TensorFlow 2.12 的模型。如果没有 conda 隔离,这两个框架的依赖包会打得不可开交。有了 conda,各玩各的,相安无事。
避坑指南: 注意 conda 环境不要和系统 Python 混用。我见过有人直接在 base 环境里装包,结果把系统搞崩了。记住:永远不要在 base 环境里装项目依赖。
3.5 实战:从零搭建一个模型移植环境
好了,理论说完了,咱们来点实际的。
假设你现在要移植一个 YOLOv8 模型到 TensorRT,环境搭建的完整流程如下:
# 第一步:拉取基础镜像
docker pull nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04
# 第二步:运行容器
docker run --gpus all -it --rm \
-v /path/to/your/project:/workspace \
nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04
# 第三步:在容器内安装 miniconda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda
export PATH=/opt/conda/bin:$PATH
# 第四步:创建项目环境
conda create -n yolo_tensorrt python=3.8 -y
conda activate yolo_tensorrt
# 第五步:安装依赖
conda install pytorch=1.13.1 torchvision=0.14.1 cudatoolkit=11.7 -c pytorch -y
pip install ultralytics onnx onnxruntime-gpu tensorrt
# 第六步:验证环境
python -c "import torch; print(torch.cuda.is_available())"
# 输出 True 就说明环境没问题
整个过程下来,你的环境就是完全可复现的。换台机器,重复上面六步,结果一模一样。
总结一下: Docker 保证操作系统层一致,conda 保证 Python 层一致,CUDA 版本管理保证 GPU 计算层一致。三层隔离,稳如老狗。
嗯,环境搭建这部分就聊到这儿。下一章咱们开始讲模型格式转换,那才是真正有意思的部分。