diff --git a/model_examples/SparseDrive/README.md b/model_examples/SparseDrive/README.md index 299ecb7aa55f561f624dd2920ba9100f9739cece..ff472af399bdcb700c5dad4fb00068ba33065f90 100644 --- a/model_examples/SparseDrive/README.md +++ b/model_examples/SparseDrive/README.md @@ -1,188 +1,198 @@ -# SparseDrive - -# 目录 -- [SparseDrive](#sparsedrive) -- [目录](#目录) -- [简介](#简介) - - [模型介绍](#模型介绍) - - [支持任务列表](#支持任务列表) - - [代码实现](#代码实现) -- [准备训练环境](#准备训练环境) - - [安装昇腾环境](#安装昇腾环境) - - [安装模型环境](#安装模型环境) -- [准备数据集](#准备数据集) - - [预训练数据集](#预训练数据集) - - [获取预训练权重](#获取预训练权重) -- [快速开始](#快速开始) - - [训练模型](#训练模型) - - [训练结果](#训练结果) -- [版本说明](#版本说明) - - [变更](#变更) - - [FAQ](#faq) - - -# 简介 - -## 模型介绍 - -SparseDrive是一种基于稀疏化表征的端到端自动驾驶模型,基于Sparse4D的整体思路,模型通过稀疏化进行检测与构图,大大提高了模型的训推速度,并通过并行的轨迹预测与规划模块,将自车的运动状态纳入到场景理解中,提高了模型轨迹预测与规划能力。 - -## 支持任务列表 - -本仓已经支持以下模型任务类型 - -| 模型 | 任务列表 | 是否支持 | -| :------: | :------: | :------: | -| SparseDrive | 训练 | ✔ | - -## 代码实现 -- 参考实现: - - ``` - url=https://github.com/swc-17/SparseDrive - commit_id=52c4c05b6d446b710c8a12eb9fb19d698b33cb2b - ``` - -- 适配昇腾 AI 处理器的实现: - - ``` - url=https://gitee.com/ascend/DrivingSDK.git - code_path=model_examples/SparseDrive - ``` - -# 准备训练环境 - -## 安装昇腾环境 - -请参考昇腾社区中《[Pytorch框架训练环境准备](https://www.hiascend.com/document/detail/zh/ModelZoo/pytorchframework/ptes)》文档搭建昇腾环境。本仓已支持表1中软件版本。 - - **表 1** 昇腾软件版本支持表 - -| 软件类型 | 支持版本 | -| ----------------- |----------| -| FrameworkPTAdapter | 7.0.0 | -| CANN | 8.1.RC1 | - -## 安装模型环境 - - 当前模型支持的 PyTorch 版本和已知三方库依赖如下表所示。 - - **表 2** 版本支持表 - - | 三方库 | 支持版本 | - |:--------------:|:------:| - | PyTorch | 2.1 | - | Driving SDK | 7.1.0 | - | mmcv | 1.x | - | mmdet | 2.28.2 | - -- 安装Driving SDK - - 请参考昇腾[Driving SDK](https://gitee.com/ascend/DrivingSDK)代码仓说明编译安装Driving SDK - -- 安装基础依赖 - - 在模型源码包根目录下执行命令,安装模型需要的依赖。 - - ```shell - pip install -r requirements.txt - ``` - -- 源码安装geos - - shapely模块依赖于geos安装包,需要本地编译并将so文件复制到环境中 - - ```shell - sparsedrive_env_path=`pip3 show mx_driving | grep "Location" | awk -F "Location: " '{print $2}' | awk -F "python" '{print $1}'` - git clone https://github.com/libgeos/geos.git - cd geos - mkdir build - cd build - cmake ../ - make - cp lib/libgeos* ${sparsedrive_env_path} - ``` - -- 源码安装mmcv - - ```shell - git clone -b 1.x https://github.com/open-mmlab/mmcv.git - cd mmcv - MMCV_WITH_OPS=1 FORCE_NPU=1 python setup.py install - ``` - -- 模型代码Patch - ```shell - git clone https://github.com/swc-17/SparseDrive.git - cp -rf ./test/ SparseDrive - cp -rf ./tools/ SparseDrive - cp -rf SparseDrive.patch SparseDrive - cd SparseDrive - git checkout 52c4c05b6d446b710c8a12eb9fb19d698b33cb2b - git apply SparseDrive.patch - ``` - -# 准备数据集 - -## 预训练数据集 -用户自行获取*nuscenes*数据集,在源码目录创建软连接`data/nuscenes`指向解压后的nuscenes数据目录 - ```shell - sparsedrive_path="path/to/sparsedrive" - cd ${sparsedrive_path} - mkdir data - ln -s path/to/nuscenes ./data/nuscenes - ``` - -运行数据预处理脚本生成SparseDrive模型训练需要的pkl文件与初始锚框 - ```shell - sh test/preprocess.sh - ``` - -## 获取预训练权重 -下载backbone预训练权重 - ```shell - mkdir ckpt - wget https://download.pytorch.org/models/resnet50-19c8e357.pth -O ckpt/resnet50-19c8e357.pth - ``` - -# 快速开始 - -## 训练模型 - -开始训练与验证 -```shell - # train - bash test/train_8p_full.sh - - # (option) downloading the stage1 weights to test the stage2 performance - wget https://github.com/swc-17/SparseDrive/releases/download/v1.0/sparsedrive_stage1.pth --no-check-certificate -O ckpt/sparsedrive_stage1.pth - - # performance - bash test/train_8p_performance.sh - ``` - - -## 训练结果 - -**表 3** 训练结果展示表 - -| 阶段 | 芯片 | 卡数 | global batch size | FPS | 平均step耗时(s) | amota | L2 | -|:---------:|:---------------:|------|:------------------:|:----:|:--------------:|:---:|:---:| -| stage1 | 竞品A | 8p | 64 | 41.0 | 1.561 | 0.3764 | - | -| stage1 | Atlas 800T A2 | 8p | 64 | 46.3 | 1.382 | 0.3864 | - | -| stage2 | 竞品A | 8p | 48 | 35.2 | 1.363 | - | 0.6280 | -| stage2 | Atlas 800T A2 | 8p | 48 | 37.9 | 1.265 | - | 0.6069 | - - - -# 版本说明 -## 变更 -2025.04.27:首次发布。 - -2025.07.07:瓶颈算子优化,刷新性能数据 - -## FAQ -暂无。 - - - +# SparseDrive + +# 目录 +- [SparseDrive](#sparsedrive) +- [目录](#目录) +- [简介](#简介) + - [模型介绍](#模型介绍) + - [支持任务列表](#支持任务列表) + - [代码实现](#代码实现) +- [准备训练环境](#准备训练环境) + - [安装昇腾环境](#安装昇腾环境) + - [安装模型环境](#安装模型环境) +- [准备数据集](#准备数据集) + - [预训练数据集](#预训练数据集) + - [获取预训练权重](#获取预训练权重) +- [快速开始](#快速开始) + - [训练模型](#训练模型) + - [训练结果](#训练结果) +- [版本说明](#版本说明) + - [变更](#变更) + - [FAQ](#faq) + + +# 简介 + +## 模型介绍 + +SparseDrive是一种基于稀疏化表征的端到端自动驾驶模型,基于Sparse4D的整体思路,模型通过稀疏化进行检测与构图,大大提高了模型的训推速度,并通过并行的轨迹预测与规划模块,将自车的运动状态纳入到场景理解中,提高了模型轨迹预测与规划能力。 + +## 支持任务列表 + +本仓已经支持以下模型任务类型 + +| 模型 | 任务列表 | 是否支持 | +| :------: | :------: | :------: | +| SparseDrive | 训练 | ✔ | + +## 代码实现 +- 参考实现: + + ``` + url=https://github.com/swc-17/SparseDrive + commit_id=52c4c05b6d446b710c8a12eb9fb19d698b33cb2b + ``` + +- 适配昇腾 AI 处理器的实现: + + ``` + url=https://gitee.com/ascend/DrivingSDK.git + code_path=model_examples/SparseDrive + ``` + +# 准备训练环境 + +## 安装昇腾环境 + +请参考昇腾社区中《[Pytorch框架训练环境准备](https://www.hiascend.com/document/detail/zh/ModelZoo/pytorchframework/ptes)》文档搭建昇腾环境。本仓已支持表1中软件版本。 + + **表 1** 昇腾软件版本支持表 + +| 软件类型 | 支持版本 | +| ----------------- |----------| +| FrameworkPTAdapter | 7.0.0 | +| CANN | 8.1.RC1 | + +## 安装模型环境 + + 当前模型支持的 PyTorch 版本和已知三方库依赖如下表所示。 + + **表 2** 版本支持表 + + | 三方库 | 支持版本 | + |:--------------:|:------:| + | PyTorch | 2.1 | + | Driving SDK | 7.1.0 | + | mmcv | 1.x | + | mmdet | 2.28.2 | + +- 安装Driving SDK + + 请参考昇腾[Driving SDK](https://gitee.com/ascend/DrivingSDK)代码仓说明编译安装Driving SDK + +- 安装基础依赖 + + 在模型源码包根目录下执行命令,安装模型需要的依赖。 + + ```shell + pip install -r requirements.txt + ``` + +- 源码安装geos + + shapely模块依赖于geos安装包,需要本地编译并将so文件复制到环境中 + + ```shell + sparsedrive_env_path=`pip3 show mx_driving | grep "Location" | awk -F "Location: " '{print $2}' | awk -F "python" '{print $1}'` + git clone https://github.com/libgeos/geos.git + cd geos + mkdir build + cd build + cmake ../ + make + cp lib/libgeos* ${sparsedrive_env_path} + ``` + +- 源码安装mmcv + + ```shell + git clone -b 1.x https://github.com/open-mmlab/mmcv.git + cd mmcv + MMCV_WITH_OPS=1 FORCE_NPU=1 python setup.py install + ``` + +- 模型代码Patch + ```shell + git clone https://github.com/swc-17/SparseDrive.git + cp -rf ./test/ SparseDrive + cp -rf ./tools/ SparseDrive + cp -rf SparseDrive.patch SparseDrive + cd SparseDrive + git checkout 52c4c05b6d446b710c8a12eb9fb19d698b33cb2b + git apply SparseDrive.patch + ``` + +# 准备数据集 + +## 预训练数据集 +用户自行获取*nuscenes*数据集,在源码目录创建软连接`data/nuscenes`指向解压后的nuscenes数据目录 + ```shell + sparsedrive_path="path/to/sparsedrive" + cd ${sparsedrive_path} + mkdir data + ln -s path/to/nuscenes ./data/nuscenes + ``` + +运行数据预处理脚本生成SparseDrive模型训练需要的pkl文件与初始锚框 + ```shell + sh test/preprocess.sh + ``` + +## 获取预训练权重 +下载backbone预训练权重 + ```shell + mkdir ckpt + wget https://download.pytorch.org/models/resnet50-19c8e357.pth -O ckpt/resnet50-19c8e357.pth + ``` + +# 快速开始 + +## 训练模型 + +- 单机训练 + + 训练脚本支持命令行参数(支持默认值/关键字参数/位置参数) + - `--batch_node_size_stage1` : stage1的global_batch_size,默认值为64(单卡batch_size=global_batch_size/NPU卡数) + - `--batch_node_size_stage2` : stage2的global_batch_size,默认值为48 + - `--num_npu` : NPU卡数,默认值为8 + +- 单机多卡精度训练脚本 +```shell + #stage1默认训练100个epoch,stage2训练10个epoch + bash test/train_8p_full.sh + (option) bash test/train_8p_full.sh 64 48 8 + (option) bash test/train_8p_full.sh --batch_node_size_stage1=64 --batch_node_size_stage2=48 --num_npu=8 +``` +- 单机多卡性能测试脚本 +```shell + #stage1\stage2默认训练1000个step + bash test/train_8p_performance.sh + (option) bash test/train_8p_performance.sh 64 48 8 + (option) bash test/train_8p_performance.sh --batch_node_size_stage1=64 --batch_node_size_stage2=48 --num_npu=8 + + # (option)若没有进行全量精度训练,可使用如下命令下载stage1的权重以测试stage2的性能 + wget https://github.com/swc-17/SparseDrive/releases/download/v1.0/sparsedrive_stage1.pth --no-check-certificate -O ckpt/sparsedrive_stage1.pth +``` + +## 训练结果 + +**表 3** 训练结果展示表 + +| 阶段 | 芯片 | 卡数 | global batch size | FPS | 平均step耗时(s) | amota | L2 | +|:---------:|:---------------:|------|:------------------:|:----:|:--------------:|:---:|:---:| +| stage1 | 竞品A | 8p | 64 | 41.0 | 1.561 | 0.3764 | - | +| stage1 | Atlas 800T A2 | 8p | 64 | 46.3 | 1.382 | 0.3864 | - | +| stage2 | 竞品A | 8p | 48 | 35.2 | 1.363 | - | 0.6280 | +| stage2 | Atlas 800T A2 | 8p | 48 | 37.9 | 1.265 | - | 0.6069 | + + + +# 版本说明 +## 变更 +2025.04.27:首次发布。 + +2025.07.07:瓶颈算子优化,刷新性能数据 + +2025.08.25:训练脚本优化 +## FAQ +暂无。 diff --git a/model_examples/SparseDrive/test/parse_args.sh b/model_examples/SparseDrive/test/parse_args.sh new file mode 100644 index 0000000000000000000000000000000000000000..71a43f33c216826ee810af9361f4023a41217213 --- /dev/null +++ b/model_examples/SparseDrive/test/parse_args.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# ================================ +# 公共参数解析器(支持默认值 + 关键字 + 位置参数) +# ================================ + +# 用法:declare_required_params batch_size npus +declare_required_params() { + local params=("$@") + export REQUIRED_PARAMS=("${params[@]}") +} + +# 补全默认值 +setup_defaults() { + local param + for param in "${REQUIRED_PARAMS[@]}"; do + eval "$param=\${$param}" + done +} + +# 帮助函数 +show_help() { + cat << EOF +用法: $0 [参数] 或 $0 [选项] +示例: + a.sh 64 48 8 + a.sh --batch_node_size_stage1=64 --batch_node_size_stage2=48 --num_npu=8 +EOF +} + +# 解析命令行参数(支持 --key=value 和 位置参数) +parse_common_args() { + # Step 1: 确保 REQUIRED_PARAMS 已定义 + if [[ -z "${REQUIRED_PARAMS+set}" ]]; then + echo "错误:未调用 declare_required_params,请先声明所需参数!" >&2 + exit 1 + fi + + # Step 2: 补全默认值 + setup_defaults + + # Step 3: 提取命令行参数 + local args=("$@") + local pos_args=() + local key_value_args=() + + for arg in "${args[@]}"; do + if [[ "$arg" == --* ]]; then + key_value_args+=("$arg") # 提取长选项参数(-- 开头的) + else + pos_args+=("$arg") # 提取位置参数 + fi + done + + # Step 4: 处理位置参数(按 REQUIRED_PARAMS 顺序赋值) + local idx=0 + declare -A required_param_map + for param in "${REQUIRED_PARAMS[@]}"; do + opt_name="${param//_/-}" #替换_为-,统一格式 + required_param_map["$opt_name"]="$param" + if [[ $idx -lt ${#pos_args[@]} ]] && [[ -n "${pos_args[$idx]}" ]]; then + eval "$param=\"\${pos_args[$idx]}\"" + fi + ((idx++)) + done + + # Step 5: 处理长选项(所有 key_value_args 都是 --param=value 格式) + for arg in "${key_value_args[@]}"; do + # 跳过空值 + [[ -z "$arg" ]] && continue + + # 提取 --param=value 中的 param 和 value + local param_key="${arg#--}" # 去掉 -- + local param_name="${param_key%%=*}" # 如 batch-size + param_name="${param_name//_/-}" #替换_为-,统一格式 + local value="${param_key#*=}" # 如 8 + + # 查表:查找 param_name 是否在映射表中 + if [[ -n "${required_param_map[$param_name]}" ]]; then + local var_name="${required_param_map[$param_name]}" + eval "$var_name=\"\$value\"" + else + echo "未知参数: $arg" >&2 + show_help + exit 1 + fi + done + + # Step 6: 检查必填参数是否都提供了 + for param in "${REQUIRED_PARAMS[@]}"; do + if [[ -z "${!param}" ]]; then + echo "缺少必要参数: --${param//-/_}=" >&2 + show_help + exit 1 + fi + done + + # Step 7: 成功提示 + echo "参数解析成功!" + for param in "${REQUIRED_PARAMS[@]}"; do + local name=$(echo "$param" | cut -d'=' -f1) + echo "$name: ${!name}" + done + +} \ No newline at end of file diff --git a/model_examples/SparseDrive/test/train_8p_full.sh b/model_examples/SparseDrive/test/train_8p_full.sh index 3e077f7c1d46ce897937c1ba4ffc447674030c36..f08ef14989476181122257c648a4f0601fea8892 100644 --- a/model_examples/SparseDrive/test/train_8p_full.sh +++ b/model_examples/SparseDrive/test/train_8p_full.sh @@ -39,9 +39,54 @@ export CPU_AFFINITY_CONF=1 #减少显存占用 export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True" +#网络名称,同目录名称,需要模型审视修改 +Network='SparseDrive' +#stage1 batch_size batch_node_size_stage1=64 +#stage2 batch_size batch_node_size_stage2=48 -rank_size=8 +#分配的NPU数量 +num_npu=8 + +################################################################################## +# 解析参数 +source ./test/parse_args.sh +declare_required_params batch_node_size_stage1 batch_node_size_stage2 num_npu +parse_common_args "$@" + +#配置文件路径 +STAGE1_CONFIG_FILE='./projects/configs/sparsedrive_small_stage1.py' +STAGE2_CONFIG_FILE='./projects/configs/sparsedrive_small_stage2.py' + +#备份配置文件 +cp ${STAGE1_CONFIG_FILE} ${STAGE1_CONFIG_FILE}.bak +cp ${STAGE2_CONFIG_FILE} ${STAGE2_CONFIG_FILE}.bak + +#更新config文件里的参数 +sed -i "s|total_batch_size[[:space:]]*=[[:space:]]*[0-9]\{1,\}|total_batch_size = ${batch_node_size_stage1}|g" ${STAGE1_CONFIG_FILE} +sed -i "s|num_gpus[[:space:]]*=[[:space:]]*[0-9]\{1,\}|num_gpus = ${num_npu}|g" ${STAGE1_CONFIG_FILE} + +sed -i "s|total_batch_size[[:space:]]*=[[:space:]]*[0-9]\{1,\}|total_batch_size = ${batch_node_size_stage2}|g" ${STAGE2_CONFIG_FILE} +sed -i "s|num_gpus[[:space:]]*=[[:space:]]*[0-9]\{1,\}|num_gpus = ${num_npu}|g" ${STAGE2_CONFIG_FILE} + +#定义复原config文件的callback +restore_config() { + if [ -f "${STAGE1_CONFIG_FILE}.bak" ]; then + mv -f "${STAGE1_CONFIG_FILE}.bak" "${STAGE1_CONFIG_FILE}" + fi + if [ -f "${STAGE2_CONFIG_FILE}.bak" ]; then + mv -f "${STAGE2_CONFIG_FILE}.bak" "${STAGE2_CONFIG_FILE}" + fi +} + +#设置信号捕获,如果训练过程中: +# 正常退出(EXIT) +# 用户中断(SIGINT) +# kill中止请求(SIGTERM) +# 命令执行失败(ERR) +# 可以自动还原对config的修改 +trap restore_config EXIT SIGINT SIGTERM ERR +################################################################################## cur_path=`pwd` cur_path_last_diename=${cur_path##*/} @@ -76,7 +121,7 @@ echo $PORT ## stage1 nohup bash ./tools/dist_train.sh \ projects/configs/sparsedrive_small_stage1.py \ - ${rank_size} \ + ${num_npu} \ --deterministic > ${output_path_dir}/stage1_train_8p_full.log 2>&1 & wait @@ -86,7 +131,7 @@ cp -f work_dirs/sparsedrive_small_stage1/iter_43900.pth ckpt/sparsedrive_stage1. ## stage2 nohup bash ./tools/dist_train.sh \ projects/configs/sparsedrive_small_stage2.py \ - ${rank_size} \ + ${num_npu} \ --deterministic > ${output_path_dir}/stage2_train_8p_full.log 2>&1 & wait diff --git a/model_examples/SparseDrive/test/train_8p_performance.sh b/model_examples/SparseDrive/test/train_8p_performance.sh index 297a2ea814554995086d69a10b231675f65178e3..67a02fcc079157b435d0999c4a96209229819eb5 100644 --- a/model_examples/SparseDrive/test/train_8p_performance.sh +++ b/model_examples/SparseDrive/test/train_8p_performance.sh @@ -39,10 +39,58 @@ export CPU_AFFINITY_CONF=1 #减少显存占用 export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True" +#网络名称,同目录名称,需要模型审视修改 +Network='SparseDrive' +#stage1 batch_size batch_node_size_stage1=64 +#stage2 batch_size batch_node_size_stage2=48 -rank_size=8 +#分配的NPU数量 +num_npu=8 +# Performance-Testing mode +export SPARSE_DRIVE_PERFORMANCE_FLAG=1 + +################################################################################## +# 解析参数 +source ./test/parse_args.sh +declare_required_params batch_node_size_stage1 batch_node_size_stage2 num_npu +parse_common_args "$@" + +#配置文件路径 +STAGE1_CONFIG_FILE='./projects/configs/sparsedrive_small_stage1.py' +STAGE2_CONFIG_FILE='./projects/configs/sparsedrive_small_stage2.py' + +#备份配置文件 +cp ${STAGE1_CONFIG_FILE} ${STAGE1_CONFIG_FILE}.bak +cp ${STAGE2_CONFIG_FILE} ${STAGE2_CONFIG_FILE}.bak + +#更新config文件里的参数 +sed -i "s|total_batch_size[[:space:]]*=[[:space:]]*[0-9]\{1,\}|total_batch_size = ${batch_node_size_stage1}|g" ${STAGE1_CONFIG_FILE} +sed -i "s|num_gpus[[:space:]]*=[[:space:]]*[0-9]\{1,\}|num_gpus = ${num_npu}|g" ${STAGE1_CONFIG_FILE} + +sed -i "s|total_batch_size[[:space:]]*=[[:space:]]*[0-9]\{1,\}|total_batch_size = ${batch_node_size_stage2}|g" ${STAGE2_CONFIG_FILE} +sed -i "s|num_gpus[[:space:]]*=[[:space:]]*[0-9]\{1,\}|num_gpus = ${num_npu}|g" ${STAGE2_CONFIG_FILE} + +#定义复原config文件的callback +restore_config() { + if [ -f "${STAGE1_CONFIG_FILE}.bak" ]; then + mv -f "${STAGE1_CONFIG_FILE}.bak" "${STAGE1_CONFIG_FILE}" + fi + if [ -f "${STAGE2_CONFIG_FILE}.bak" ]; then + mv -f "${STAGE2_CONFIG_FILE}.bak" "${STAGE2_CONFIG_FILE}" + fi +} + +#设置信号捕获,如果训练过程中: +# 正常退出(EXIT) +# 用户中断(SIGINT) +# kill中止请求(SIGTERM) +# 命令执行失败(ERR) +# 可以自动还原对config的修改 +trap restore_config EXIT SIGINT SIGTERM ERR +################################################################################## +# cd到与test文件夹同层级目录下执行脚本,提高兼容性;test_path_dir为包含test文件夹的路径 cur_path=`pwd` cur_path_last_diename=${cur_path##*/} @@ -53,7 +101,9 @@ if [ x"${cur_path_last_diename}" == x"test" ];then else test_path_dir=${cur_path}/test fi + output_path_dir=${test_path_dir}/output + if [ -d ${output_path_dir} ]; then rm -rf ${output_path_dir} fi @@ -73,12 +123,11 @@ do done echo $PORT -export SPARSE_DRIVE_PERFORMANCE_FLAG=1 ## stage1 nohup bash ./tools/dist_train.sh \ projects/configs/sparsedrive_small_stage1.py \ - ${rank_size} \ + ${num_npu} \ --deterministic > ${output_path_dir}/stage1_train_8p_performance.log 2>&1 & wait @@ -86,7 +135,7 @@ wait ## stage2 nohup bash ./tools/dist_train.sh \ projects/configs/sparsedrive_small_stage2.py \ - ${rank_size} \ + ${num_npu} \ --deterministic > ${output_path_dir}/stage2_train_8p_performance.log 2>&1 & wait