CANN/GE动态分档特性介绍
动态分档Dynamic Gear特性介绍【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge1 概述1.1 解决什么问题在昇腾 NPU 推理场景中模型的输入 shape 可能会变化——比如 batch size 不同、图像分辨率不同、序列长度不同。如果每次变化都重新编译模型开销不可接受。GE 的动态分档特性解决了这个问题在编译期一次性枚举所有可能出现的输入 shape 组合称为档位/gear为每个档位生成独立的静态优化子图。运行时根据实际输入 shape 选择对应子图执行。这样每个档位都能享受静态 shape 的全部编译优化算子融合、内存规划、下沉调度同时保持了一定的动态灵活性。1.2 三种动态分档模式模式参数适用场景限制动态 Batch--dynamic_batch_size仅 batch 维度变化-1只能在第一维动态分辨率--dynamic_image_size仅 H/W 维度变化H 和 W 必须同时变任意维度动态ND--dynamic_dims任意多个维度变化最灵活但配置最复杂ND 模式可以覆盖前两种官方推荐档位数量为 3~4 个最多支持 100 个档位。1.3 整体架构2 用户场景与配置2.1 离线编译场景atc用户通过 atc 命令行工具指定档位信息编译生成.om文件# 动态 batch 示例 atc --input_shapedata:-1,3,224,224 \ --dynamic_batch_size1,8,16 # 任意维度动态示例 atc --input_shapedata:1,1,40,-1;label:1,-1;mask:-1,-1 \ --dynamic_dims20,20,1,1;40,40,2,2;80,60,4,4-1标记需要分档的维度dynamic_dims中每个分号分隔的一组值对应一个档位中所有-1维度的具体取值。2.2 在线编译场景Session API在在线模式下如 PyTorch 通过 TorchAir通过 Session 的AddGraph传入 optionsstd::mapstd::string, std::string options { {ge.inputShape, data:1,-1,40,-1;label:1,-1;mask:-1,-1}, {ge.dynamicDims, 20,20,1,1;40,40,2,2;80,60,4,4}, {ge.dynamicNodeType, 1}, // placeholder 输入 {ge.compileHybridMode, 1} // 开启混合编译模式 }; session-AddGraph(graph_id, graph, options);2.3 混合编译模式Hybrid Mode这是一个值得深入介绍的设计。当同时配置了以下四个条件时GE 进入混合编译模式ge.inputShape非空ge.dynamicDims非空ge.dynamicNodeType 1placeholder 模式ge.compileHybridMode 1代码入口api/session/session/user_hybrid_graph_manager.cc:76-86IsHybridMode()在混合模式下GE 将用户传入的一张图拆为两张图并行编译分档图gear graph携带inputShapedynamicDims选项编译出 Case N 子图的结构动态 shape 图dynamic shape graph去掉分档约束编译为真正的动态 shape 图执行时UserHybridGraphManager::SelectExecuteGraph()提取当前输入的动态维度值与已存储的档位逐一比对。匹配则走分档图否则走动态 shape 图。这是一个非常实用的渐进式降级策略——优先享受分档图的静态优化性能降级时仍能正确处理非预期 shape。代码入口api/session/session/user_hybrid_graph_manager.ccSelectExecuteGraph()3 编译期实现compiler/3.1 编译入口与 Pass 流程动态分档的编译核心位于compiler/graph/目录由三个 Pass 按序组成流程文件compiler/graph/preprocess/multi_batch_copy_graph.cc:156-164 ProcessMultiBatch(graph, session_id) → CreateSubGraphWithScopePass // 异构场景按 scope 创建子图 → SubgraphMultiDimsClonePass // 子图级GetShape → Concat → MapIndex → Case → MultiBatchClonePass // 根图级Data/GetDynamicDims → MapIndex → Case3.2 参数解析multi_batch_options动态类型分类// compiler/graph/preprocess/multi_batch_copy_graph.h:35-40 enum DynamicType { kDynamicBatch, // --dynamic_batch_size kDynamicImageSize, // --dynamic_image_size kDynamicDims, // --dynamic_dims kDynamicUnknown, };参数解析流程InitDynamicParams()(compiler/graph/preprocess/multi_batch_options.cc:485-522) 解析三种来源dynamic_batch_size1,2,4,8→batch_shapes_ [[1],[2],[4],[8]]dynamic_image_size224,224;448,448→batch_shapes_ [[224,224],[448,448]]dynamic_dims1,224;1,448;1,672→batch_shapes_ [[1,224],[1,448],[1,672]]ParserDataToDynamicInfo()(multi_batch_options.cc:531-575) 将每个档位拆分到各个 Data 节点上对每个 Data 节点统计其-1维度数量然后从每个档位中提取对应数量的值。3.3 核心图变换MultiBatchClonePass这是动态分档编译的核心——将一张动态图拆成Data/GetDynamicDims → MapIndex → Case的结构。执行流程文件compiler/graph/passes/multi_batch/multi_batch_clone_pass.cc:52-139 MultiBatchClonePass::Run(graph): 1. CheckSequenceOfOptions() → 校验用户配置与图 Data 节点匹配 2. InitDynamicParams() → 解析档位参数到 batch_shapes_ 3. CheckDynamicParams() → 校验 ≥2 档位、无负数、无重复 4. CollectIoNodes() → 收集 Data/Const/NetOutput 节点 5. CheckAndParseDynamicData() → 构建 data_to_dynamic_info_ 映射 6. UpdateDataShapeByUserInput()→ 应用用户 shape 到 Data 节点 7. SortDynamicDimsWithIndex() → 按 Data 节点索引排序 8. graph ↔ branch Swap → 原图变成 branch新图成为 root 9. CreateRootGraph() → 创建 Case MapIndex 输入/输出节点 10. CreateOriGraph(branch) → 处理 GetNext 分解 11. CreateSubgraphs(branch) → 克隆 N 份子图每份设置对应档位 shape 12. PruneDirectOutput() → 清理直连输出 13. UpdateSubgraphOutput() → 更新子图输出变换后的根图结构关键节点说明Const 节点档位查找表multi_batch_clone_pass.cc:527-576将所有档位展平为一维 int32 数组。例如batch_shapes_ [[1,224],[1,448],[1,672]]则 const data [1, 224, 1, 448, 1, 672]shape {6}。MapIndex 算子multi_batch_clone_pass.cc:584-649接收两个输入x来自 Data 或 GetDynamicDims 的运行时 gear_info动态维度值的向量data_seq来自 Const 的档位查找表输出branch_index0, 1, ..., N-1指示 Case 选择哪个子图分支。Data 节点 vs GetDynamicDims 节点multi_batch_clone_pass.cc:586-591非 GetNext sink 模式创建普通 Data 节点运行时由 host 直接写入动态维度值GetNext sink 模式创建GETDYNAMICDIMS算子节点其输入是各个 Data 的 shape输出是 gear_info 向量。在设备端自动从输入 shape 中提取动态维度Case 算子multi_batch_clone_pass.cc:389-466设置关键属性ATTR_NAME_BATCH_NUM档位数量ATTR_NAME_PRED_VALUE_0..N每个档位的 shape 值ATTR_USER_DESIGNEATE_SHAPE_ORDERData 节点名称顺序ATTR_INSERT_BY_MBATCH标记为分档插入ATTR_DYNAMIC_TYPE动态类型BATCH/IMAGE/DIMS子图创建multi_batch_clone_pass.cc:1504-1528对每个档位batch_shapes_[i]CloneComputeGraph(branch)克隆原始图重命名所有节点添加_ascend_mbatch_batch_N后缀将 Data 节点的 shape 更新为对应档位的具体值为所有节点设置ATTR_NAME_BATCH_LABEL Batch_N根图的 Data 节点 shape 设为最大档位multi_batch_clone_pass.cc:1126-1204因为内存分配需要覆盖所有档位。3.4 子图级分档SubgraphMultiDimsClonePass当图存在子图如 If/While 等控制流算子的子图且子图被标记了ATTR_NAME_SUBGRAPH_IS_MULTI_DIMS时SubgraphMultiDimsClonePass会在子图内部创建Data_0 → GetShape_0 ─┐ Data_1 → GetShape_1 ──→ Concat → MapIndex → Case → NetOutput ↑ Const (gear table) ───┘与根图的区别是使用GetShape从运行时输入提取 shape而非依赖外部传入。3.5 符号化 shape 泛化compiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_symbolizer.cc:225-265的SymbolizeMultiBatchSubGraph()对分档子图进行符号化 shape 推导。当图被标记了_enable_dynamic_batch时为每个子图的 Data 节点创建符号化 origin shape使后续优化 pass 能理解分档图的 shape 语义。4 对外 API 层api/ inc/4.1 ACL 公共接口接口作用文件aclmdlSetInputDynamicDims执行前设置当前推理的动态维度值inc/external/acl/acl_mdl.h:987aclmdlGetInputDynamicGearCount查询模型支持的档位数量inc/external/acl/acl_mdl.h:1200aclmdlGetInputDynamicDims查询模型各档位的具体维度值inc/external/acl/acl_mdl.h:12124.2 典型调用流程4.3 GeExecutor 关键接口接口作用文件SetDynamicDims()设置动态维度校验匹配后写入设备runtime/v1/executor/ge_executor.cc:502SetDynamicBatchSize()设置动态 batchruntime/v1/executor/ge_executor.cc:374SetDynamicImageSize()设置动态分辨率runtime/v1/executor/ge_executor.cc:430GetCurDynamicDims()从完整输入 shape 提取动态轴runtime/v1/executor/ge_executor.cc:570GetCombinedDynamicDims()获取所有档位组合inc/framework/executor/ge_executor.h:1525 运行时实现runtime/5.1 模型加载阶段DavinciModel在加载 OM 模型时初始化分档信息文件runtime/v1/graph/load/model_manager/davinci_model.cc:2896-2924 InitRealSizeAndShapeInfo(): all_gears_info_ run_context_.dynamic_shape_dims // 所有档位信息 is_online_infer_dynamic_ (!run_context_.dynamic_shape_dims.empty())然后为每个连接到 Case 的 NetOutput 构建映射表GetGearAndRealOutSizeInfo()(davinci_model.cc:2969-2989)遍历 Case 的各分支子图通过ATTR_NAME_BATCH_LABEL如Batch_3获取档位索引构建output_index → {gear_dims → output_size}映射GetGearAndRealOutShapeInfo()(davinci_model.cc:3055-3100)类似地构建output_index → {gear_dims → output_shape}映射5.2 执行阶段——档位匹配GeExecutor 层匹配ExecModel()(ge_executor.cc:1145-1184) 入口// 如果用户设置了动态参数 if (dynamic_batch_size || dynamic_image || dynamic_dims) { batch_info GetDynamicBatchInfo(model_id); if (!batch_info.empty()) { SetDynamicInputDataFlag(run_input_data, batch_info, input_data); // → 遍历 batch_info逐一比对 dynamic_dims / batch_size / image_size // → 匹配后设置 batch_label Batch_N } }DavinciModel 层匹配与校验HandleInputData()(davinci_model.cc:4658-4696) 在非 sink 模式下调用GetCurDynamicDims()从输入 shape 中提取动态维度值与run_context_.dynamic_shape_dims中的档位逐一比较必须精确匹配某个档位否则报错将匹配到的动态维度值作为额外的 Data buffer附加到输入数据中供 GetDynamicDims/Data 节点使用执行CopyInputDataWithMergeH2D()合并拷贝到设备5.3 GetNext Sink 模式在 GetNext sink 模式下档位信息不由 host 写入而是由设备端的GetDynamicDims算子在执行时自动从输入 shape 中提取。AssembleListenerOutput()(davinci_model.cc:5409-5435)if (is_getnext_sink_dynamic_) { cur_dynamic_dims_.resize(shape_of_cur_dynamic_dims_); aclrtMemcpy(cur_dynamic_dims_.data(), ..., netoutput_last_input_addr_, ..., DEVICE_TO_HOST); }执行完成后从设备内存读回档位信息用于后续的输出 shape 查表。5.4 输出 shape 解析执行完成后BuildOutputShapeInfo()(davinci_model.cc:5246-5285) 使用cur_dynamic_dims_作为 key从映射表中查找对应的输出大小和 shapeif (is_online_infer_dynamic_) { auto size_it merge_nodes_gear_and_real_out_size_info_[output_idx].find(cur_dynamic_dims_); auto shape_it merge_nodes_gear_and_real_out_shape_info_[output_idx].find(cur_dynamic_dims_); }6 关键数据结构结构体文件用途HybridDynamicDimsInfoapi/session/session/user_hybrid_graph_manager.h:23混合模式的档位信息OmeContextbase/common/context/ome_context.h:17编译上下文中的动态维度信息RunModelDatainc/framework/executor/ge_executor.h:34执行时的动态参数batch/分辨率/维度InputDatainc/graph_metadef/common/ge_common/ge_types.h:193输入数据 batch_labelaclmdlDescapi/acl/acl_model/model/model_desc_internal.h:36模型描述中的 dynamicBatch/dynamicHW/dynamicDimsaclmdlDatasetapi/acl/acl_model/model/model_desc_internal.h:104数据集中的运行时动态参数7 关键属性列表属性名设置对象用途ATTR_NAME_BATCH_NUMCase 节点档位/子图数量ATTR_NAME_PRED_VALUE_NCase 节点第 N 个档位的 shape 值ATTR_INSERT_BY_MBATCHCase/MapIndex标记为分档 pass 插入ATTR_DYNAMIC_TYPECase 节点动态类型ATTR_USER_DESIGNEATE_SHAPE_ORDERCase 节点Data 节点名称顺序ATTR_NAME_BATCH_LABEL子图所有节点Batch_0、Batch_1 等_enable_dynamic_batch根图启用符号化泛化ATTR_NAME_SUBGRAPH_IS_MULTI_DIMS子图标记子图需要多档处理_all_origin_gears_inputsData 节点所有档位 shape 字符串8 源码文件索引docs/ 文档文件关键内容docs/atc_shape_configuration_guide.mdatc shape 配置实践指南docs/graph_engine_api/options参数说明.mdge.inputShape / ge.dynamicDims 参数说明docs/graph_engine_api/aclgrphBuildModel支持的配置参数.md编译参数 DYNAMIC_DIMS / DYNAMIC_BATCH_SIZE / DYNAMIC_IMAGE_SIZEdocs/graph_engine_api/aclmdlGetInputDynamicGearCount.md查询档位数量 APIdocs/graph_engine_api/aclmdlGetInputDynamicDims.md查询各档位维度 APIdocs/graph_engine_api/aclmdlSetInputDynamicDims.md设置动态维度 APIdocs/architecture/modules/compiler/compiler.md:550架构文档中的动态分档描述api/ 接口层文件关键内容api/session/session/user_hybrid_graph_manager.h混合模式管理器定义api/session/session/user_hybrid_graph_manager.cc混合模式双图并行编译、执行选择api/session/session/inner_session.cc:165创建 HybridManager路由所有图操作api/session/jit_execution/user_graphs_manager.cc:68-94动态分档不支持 slice scheduleapi/acl/acl_model/model/model.cppACL 层动态维度设置/查询实现ParseBatchInfo()inc/external/acl/acl_mdl.h:987-1225ACL 公共 API 声明inc/framework/executor/ge_executor.h:34-157GeExecutor 接口定义compiler/ 编译层文件关键内容compiler/graph/preprocess/multi_batch_copy_graph.cc:156Pass 流程入口compiler/graph/preprocess/multi_batch_options.cc参数解析、校验compiler/graph/preprocess/multi_batch_options.h参数解析 API 声明compiler/graph/passes/multi_batch/multi_batch_clone_pass.cc核心根图 Case 拆分compiler/graph/passes/multi_batch/subgraph_multi_dims_clone_pass.cc子图级 Case 拆分compiler/graph/passes/multi_batch/create_subgraph_with_scope_pass.cc异构 scope 子图compiler/graph/passes/multi_batch/multi_batch_pass.cc后处理batch label 设置compiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_symbolizer.cc:225分档子图符号化runtime/ 运行时层文件关键内容runtime/v1/executor/ge_executor.cc:98-136SetDynamicInputDataFlag()档位匹配runtime/v1/executor/ge_executor.cc:374-568SetDynamicBatchSize / SetDynamicImageSize / SetDynamicDimsruntime/v1/executor/ge_executor.cc:570-621GetCurDynamicDims()提取动态轴runtime/v1/executor/ge_executor.cc:1145-1184ExecModel()执行入口runtime/v1/graph/load/model_manager/davinci_model.cc:2896-3100模型加载档位初始化、映射表构建runtime/v1/graph/load/model_manager/davinci_model.cc:4658-4696HandleInputData()非 sink 模式runtime/v1/graph/load/model_manager/davinci_model.cc:5246-5320输出 shape 查表runtime/v1/graph/load/model_manager/davinci_model.cc:8471-8521GetCurDynamicDims()模型级校验base/common/context/ome_context.h:17OmeContext结构体【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考