做征程6开发,Docker环境是绕不开的。官方提供了带工具链的Docker镜像,但配置过程中踩的坑不少。这篇从镜像拉取、环境配置、常见问题排查到最佳实践,完整记录一下我搭建征程6 Docker开发环境的过程。
一、镜像拉取与版本选择
地平线官方Docker镜像仓库:
```bash
# 查看最新可用版本
docker pull openexplorer/horizon_j6_open:latest
# 或者拉指定版本(推荐,确保和板端OE包版本一致)
docker pull openexplorer/horizon_j6_open:v3.7.0
```
版本对照表:
板端OE版本 Docker镜像版本 march参数
3.6.x v3.6.0 nash-e
3.7.0 v3.7.0 nash-e
坑:
拉latest标签不能保证和板端版本一致。我一开始拉了latest,板端是3.7.0,结果编译出来的hbm在板端报HB_DNN_LAYOUT_MISMATCH,排查了一下午发现是版本不匹配。
建议: 先查板端版本再拉镜像:
```bash
# 板端执行
cat /opt/horizon/version
# 输出:3.7.0-20250815
# Docker里拉对应版本
docker pull openexplorer/horizon_j6_open:v3.7.0
```
二、容器启动与配置
```bash
# 启动容器,挂载本地目录
docker run -it --rm \
--gpus all \
-v /home/user/project:/workspace \
-v /data/datasets:/data \
openexplorer/horizon_j6_open:v3.7.0 \
/bin/bash
```
参数说明:
· --gpus all:让容器使用宿主机的GPU(量化校准需要CUDA)
· -v:挂载本地目录到容器内
· --rm:容器退出后自动删除
坑: 如果不加--gpus all,hb_mapper在做量化的时候会找不到CUDA设备,报错CUDA driver version is insufficient。这个错误信息很misleading,实际不是驱动版本问题,而是容器没挂载GPU。
三、容器内环境验证
进入容器后,先验证工具链是否正常工作:
```bash
# 检查版本
hb_mapper --version
# 输出:3.7.0-release
# 检查CUDA
nvidia-smi
# 应该能看到GPU信息
# 检查Python环境
python3 -c "import torch; print(torch.__version__)"
# 应该输出PyTorch版本
# 检查hbdk(x86仿真库)
python3 -c "import hbdk; print(hbdk.__version__)"
```
如果以上任何一步报错,说明环境有问题,需要排查。
四、常见问题排查
问题1:容器内找不到hb_mapper
现象: hb_mapper: command not found
原因: 环境变量没配置好。地平线工具链安装后需要source环境变量脚本。
解决:
```bash
source /opt/horizon/bin/env.sh
# 或者把上面这行加到~/.bashrc里
```
问题2:CUDA版本不匹配
现象: CUDA driver version is insufficient for runtime version
原因: 容器内的CUDA版本和宿主机驱动版本不匹配。
解决:
```bash
# 查看宿主机CUDA驱动版本
nvidia-smi
# 看右上角Driver Version
# 查看容器内CUDA runtime版本
nvcc --version
# 如果容器内CUDA版本高于宿主机驱动支持的版本,需要换用低版本CUDA的镜像
# 或者升级宿主机驱动
```
坑: 很多开发者看到"driver version is insufficient"就以为是驱动太旧,实际上是容器内的CUDA runtime版本太高。征程6的Docker镜像默认带的是CUDA 11.8,如果宿主机驱动是470.x(只支持到CUDA 11.4),就会报这个错。
问题3:内存不足导致量化失败
现象: 量化过程中进程被kill,或者报Killed/Out of memory
原因: 模型太大,校准数据太多,内存不够。
解决:
```bash
# 限制并发数
export OMP_NUM_THREADS=4
# 减少校准数据量
# 在quant_config.yaml里调小batch_size
# 或者给Docker容器分配更多内存
docker run -it --rm --memory=32g \
openexplorer/horizon_j6_open:v3.7.0
```
问题4:模型编译时找不到依赖库
现象: libxxx.so: cannot open shared object file
原因: 容器内缺少某些系统库。
解决:
```bash
# 先找缺什么库
ldd /opt/horizon/bin/hb_mapper
# 看哪些库显示"not found"
# 安装缺失的库
apt-get update
apt-get install -y libglib2.0-0 libsm6 libxext6 libxrender-dev
```
问题5:中文路径或文件名导致报错
现象: 各种奇怪的路径相关错误
原因: 工具链某些脚本对中文编码支持不好。
解决:
所有路径和文件名用英文,不要用中文。包括模型文件名、校准数据目录名、配置文件名等。
五、最佳实践
1. 使用docker-compose管理环境
```yaml
# docker-compose.yml
version: '3.8'
services:
horizon-dev:
image: openexplorer/horizon_j6_open:v3.7.0
runtime: nvidia
volumes:
- ./project:/workspace
- ./data:/data
environment:
- CUDA_VISIBLE_DEVICES=0
working_dir: /workspace
command: /bin/bash
```
```bash
docker-compose up -d
docker-compose exec horizon-dev bash
```
2. 保存工作状态的镜像
配置好环境后,把当前容器保存成新镜像,下次直接用这个镜像,不用重新配环境:
```bash
# 在容器外执行,把当前容器保存为新镜像
docker commit my-horizon-dev:v1.0
# 下次直接用这个镜像
docker run -it --rm my-horizon-dev:v1.0
```
3. 数据持久化
不要把数据放在容器内部(容器删除后数据就没了),一定要挂载外部目录:
```bash
docker run -it --rm \
-v $(pwd)/models:/workspace/models \
-v $(pwd)/data:/workspace/data \
-v $(pwd)/output:/workspace/output \
openexplorer/horizon_j6_open:v3.7.0
```
4. GPU资源共享
如果宿主机有多块GPU,可以指定容器用哪一块:
```bash
docker run -it --rm \
--gpus '"device=0"' \
openexplorer/horizon_j6_open:v3.7.0
# 或者两块都用
docker run -it --rm \
--gpus '"device=0,1"' \
openexplorer/horizon_j6_open:v3.7.0
```
六、容器内开发工作流
我的标准工作流:
```bash
# 1. 进入容器
docker-compose exec horizon-dev bash
# 2. 导出ONNX
python export.py --weights best.pt --img 640 --include onnx
# 3. 生成校准数据
python gen_cal_data.py --images /data/cal --output ./calibration
# 4. 量化
hb_mapper makertbin --config quant.yaml --model model.onnx --output_dir ./quant
# 5. 编译
hb_mapper makehbm --config compile.yaml --model quant/model.onnx --output model.hbm
# 6. x86仿真验证
python test_x86.py --model model.hbm --input test_input.bin
# 7. 拷贝hbm到板端测试
scp model.hbm root@board_ip:/opt/horizon/
```
七、注意事项总结
1. 版本对齐:Docker镜像版本必须和板端OE包版本一致。
2. 加--gpus all:容器必须挂载GPU,否则量化找不到CUDA设备。
3. source env.sh:进入容器后先source环境变量脚本。
4. 路径用英文:工具链对中文路径支持不好。
5. 内存限制:大模型量化需要足够内存,用--memory参数或OMP_NUM_THREADS限制并发。
6. 保存镜像:配置好环境后commit成新镜像,避免重复配置。
7. 数据挂载:所有数据放在挂载的外部目录,不要放在容器内部。
8. CUDA版本匹配:容器内CUDA版本不能超过宿主机驱动支持的版本。
