当前位置: 首页 > news >正文

CANN / ge 内存约束文档

GE 内存约束文档

【免费下载链接】geGE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力,并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge

静态内存复用

代码位置:compiler/graph/build/memory/

约束1:图编译模块内存复用处理阶段禁止改图

精确边界:

  • 禁止改图的范围:BlockMemAssigner::AssignMemoryWithReuse实现及其触发的所有函数
  • 多线程入口:HybridMemAssigner::Assign启动多线程,并发调用AssignMemoryWithReuse
  • 明确禁止的:对ComputeGraph上的Node增加、修改、删除属性
  • 安全的操作:读取属性/OpDesc是安全的(系统在遍历时大量读取OpDesc来判断内存分配策略)

约束2:动态多batch场景影响分析

  • 代码实体:DynamicBatchMemAssignerdynamic_batch_mem_assigner.h
  • 含义:系统通过batch_label_(由用户或GE上层框架设置)标识不同batch,支持不同batch间的内存复用策略
  • 与静态内存复用的矛盾点:
    • 连续输入的内存在不同batch中会被合并成一个大块进行对齐
    • batch内外没有复用,batch间有对齐策略,导致内存使用效率可能降低
    • 最大拆分大小限制:kMaxSplitSizeForDynamicBatch = 400MBdynamic_batch_mem_assigner.h

约束3:静态图内存新增特性需要考虑的场景

场景代码标记/依据对复用的影响
连续内存continuous_block_block_mem_assigner.h),ContinuousMemMngcontinuous_mem.cc支持连续输入节点的内存合并;不同batch的连续内存可以合并复用
atomic集中清零atomic_addr_clean_id_block_mem_assigner.h需要atomic清零的内存块不能被其他节点复用;如果节点没有相关属性则跳过清零
零拷贝is_zero_copy_block_mem_assigner.h),IsNodeAndPeerNodeTaskSupportZeroCopyblock_mem_assigner.cc零拷贝块可跨节点复用(IsRealSizeReuseBlock);零拷贝内存不能合并(多个用户输入地址可能不连续)
不可变地址输出is_fixed_addr_prior_block_mem_assigner.hconstant/const/variable/fileconstant/constplaceholder类型的算子output地址在编译期固定,固定地址优先的内存块可被复用但地址不可变
不支持地址刷新的算子HCOM/rtsStreamSwitchByIndex等这些算子的输入输出地址必须稳定,不能使用零拷贝
P2P内存类型RT_MEMORY_P2P_DDRblock_mem_assigner.ccP2P内存不能与其他内存类型合并清零(graph_mem_assigner.cc

约束4:HCOM算子的特殊性

  • "连续"的含义:逻辑连续而非物理连续。多个HCOM算子的输出在逻辑上形成连续内存区域,通过ContinuousMemMng管理器处理分配和复用。 —continuous_mem.cc
  • featureBaseRefreshable配置:
    • 获取方式:ge::GetContext().GetOption(ge::OPTION_FEATURE_BASE_REFRESHABLE, refreshable)block_mem_assigner.cc
    • 成员变量:is_feature_map_refreshable_block_mem_assigner.h
    • 默认值:false,配置值为"1"时设为true
    • 作用:控制特征图是否可刷新,影响IsNoNeedAssignMemory的判断

约束5:其他约束

  1. PreAssign/SetOpMemOffset非线程安全:只能由单线程调用,其他并发操作需要注意。 —block_mem_assigner.h

  2. 对齐策略差异:零拷贝内存使用32字节对齐,其他使用512字节对齐。 —graph_mem_assigner.h

  3. 子图NETOUTPUT特殊处理:子图中的NETOUTPUT节点不能进行零拷贝。 —block_mem_assigner.cc

  4. 多batch形状数据节点约束:多batch形状数据节点不支持零拷贝。 —block_mem_assigner.cc

  5. 悬挂内存块管理:悬挂的内存块(suspended block)会在下一个节点分配时被释放,生命周期通过life_time_begin_life_time_end_管理,一旦设置不能修改。 —block_mem_assigner.h

  6. 复用策略可配置:支持通过use_range_ascending_sort_reuse_first_release_memory_priority_mode_等参数动态配置。 —block_mem_assigner.h


动态内存复用

代码位置:

  • v2层:runtime/v2/kernel/memory/allocator/(ScalableAllocator、MemoryPool)
  • v1层:runtime/v1/graph/manager/active_memory_allocator.h(ActiveMemoryAllocator、ExpandableActiveMemoryAllocator、PhysicalMemoryAllocator)
  • 桥接层:runtime/v2/kernel/memory/device/device_allocator.h(DeviceAllocator)

约束1:ScalableAllocator不支持多线程并发

  • 代码位置:runtime/v2/kernel/memory/allocator/scalable_allocator.h
  • 无锁设计依据:类内部无std::mutexstd::recursive_mutex,仅有static std::atomic_size_t global_allocator_id_用于生成唯一ID(scalable_allocator.h
  • 安全性保证方式:aclmdlExecute的调用约束保证单线程调用(详见docs/graph_engine_api/aclmdlExecute.md),底层allocator通过recursive_mutex保证线程安全
  • 底层有锁保护:v1层的PhysicalMemoryAllocator使用std::recursive_mutexactive_memory_allocator.h),ExpandableActiveMemoryAllocatorImp同样使用std::recursive_mutexactive_memory_allocator.h

约束2:ActiveMemoryAllocator/ExpandableActiveMemoryAllocator/PhysicalMemoryAllocator支持多线程

  • 线程安全机制:使用std::recursive_mutex保护共享资源
  • 新增代码要求:必须在访问共享资源时加锁保护,遵循现有的锁使用模式

内存管理

代码位置:runtime/v2/kernel/memory/(不含allocator子目录)

约束1:device id正确性

  • 代码位置:memory_kernel.cc使用aclrtGetDevice获取device_id
  • 要求:调用rts接口时,device id必须显式传入正确值,避免使用缺省参数(默认为0),需要验证多device场景用例

约束2:内存释放时序

  • 顺序:先流同步 → 再释放内存 → 最后销毁device
  • 代码关联:caching_mem_allocator.ccAllocateWithTryRecycle方法确保同步后再释放

约束3:虚拟内存兼容性设计

  • rtReserveMemAddress用途:虚拟地址预留,用于动态shape预分配地址空间
  • 实际调用位置:runtime/v1/graph/manager/active_memory_allocator.cc
  • fallback路径:rtReserveMemAddress失败时,标记不支持虚拟地址预留,回退到物理地址分配模式。 —runtime/v1/graph/manager/active_memory_allocator.cc("Maybe not support rtReserveMemAddress.")
  • 要求:要确保业务流程正常,无ERROR日志

约束4:caching_mem_allocator进程退出时序

  • 代码位置:caching_mem_allocator.hstatic std::vector<CachingMemAllocator *> all_caching_mem_allocators_
  • 机制:全局变量保存所有allocator实例指针,GE finalize时主动调用所有allocator的finalize方法
  • 原因:allocator析构时如果还有内存未释放,会调用rts接口释放,但此时rts so可能已卸载,导致core dump
  • finalize入口:rts_caching_mem_allocator.cc遍历all_caching_mem_allocators_逐一finalize

约束5:单例内存池在模型卸载或者session析构时也要析构

举例SessionMemAllocator<ExpandableActiveMemoryAllocator>是单例,内部存储基于session id的对象。当用户创建新的session,或者调用aclmdl开头的接口进行离线推理时会产生新的session id,也就会产生新的对象,因此需要在下面两个地方调用SessionMemAllocator<ExpandableActiveMemoryAllocator>::Instance().RemoveAllocator释放对象内存,否则用户在创建多个session或者多次执行调用aclmdl开头的接口进行离线推理的场景下,无用的对象会多占用host内存或者device内存资源,造成“内存泄漏”现象。

  • GeExecutor::UnloadModelaclmdl离线推理场景卸载模型
  • InnerSession::Finalize InnerSession析构

CachingMemAllocator完整关系图

┌──────────────────────────────────────────────────────────────┐ │ CachingMemAllocator │ │ runtime/v2/kernel/memory/caching_mem_allocator.h │ │ - all_caching_mem_allocators_ (全局allocator注册表) │ │ - rts_mem_allocator_ (RtsFirstLevelPool) │ │ - memory_pool_ → ScalableAllocator │ │ - mutex_ (static, 保护allocator创建/销毁) │ ├──────────────────────────────────────────────────────────────┤ │ │ │ ┌── RtsCachingMemAllocator │ │ │ runtime/v2/kernel/memory/rts_caching_mem_allocator.h │ │ │ - device_id_to_allocators_ (device → allocator映射) │ │ │ - 负责finalize流程,遍历all_caching_mem_allocators_ │ │ │ │ │ └── ScalableAllocator (通过memory_pool_指针) │ │ runtime/v2/kernel/memory/allocator/scalable_allocator │ │ - 无锁设计,单线程调用 │ │ - 通过 DeviceAllocator 桥接到 v1 allocator │ │ │ │ └── DeviceAllocator │ │ runtime/v2/kernel/memory/device/device_allocator │ │ - active_memory_allocator_ (Expandable...Imp, v1) │ │ │ │ └── PhysicalMemoryAllocator (v1) │ │ runtime/v1/graph/manager/active_mem...h │ │ - recursive_mutex 保护 │ │ - 最终调用 rtMalloc / rtFree │ └──────────────────────────────────────────────────────────────┘

编译期内存排布冲突

代码位置:compiler/graph/optimize/mem_layout_conflict_optimize/

维测日志约束

  • 发现冲突:[MemConflict][Conflict] type: [%s, %s], anchor: [%s, %s], will insert %s %s
  • 插入Identity:[MemConflict][INSERT][NODE]
  • 日志使用[MemConflict]关键字,如果每张图只会打印一次,使用LOGI

跨模块约束汇总

以下约束跨越多个模块,修改时需同步考虑:

  1. 地址刷新能力(模块一 + 模块二):mem_layout_conflict_optimize中的冲突检测判定"不支持地址刷新"的算子列表,必须与静态内存复用中的处理逻辑保持一致。

  2. v1/v2 allocator边界(模块三 + 模块四):v2的ScalableAllocator通过DeviceAllocator桥接到v1的PhysicalMemoryAllocator。修改任何一层的接口都需要考虑对另一层的影响。

  3. caching_mem_allocator生命周期(模块三 + 模块四):CachingMemAllocator的finalize流程依赖all_caching_mem_allocators_全局注册表,新增allocator类型必须正确注册到此表中。

【免费下载链接】geGE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力,并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.jsqmd.com/news/784837/

相关文章:

  • 观察Taotoken在多模型间智能路由带来的调用成功率提升
  • 数字孪生安全架构深度剖析:从CPS到AI增强攻击的防御实战
  • CANN/pyasc高级算子API文档
  • C++14的[[deprecated]]属性:别再用旧函数了,手把手教你优雅地标记和替换
  • ComfyUI-VideoHelperSuite终极指南:掌握视频合成与工作流优化
  • AI赋能人工耳蜗:从噪声分离到个性化编码的听觉重建技术
  • Tool Calling、Agent、MCP全解析:AI工程三层结构,小白也能看懂大模型如何“干活”并收藏!
  • 别只盯着AT指令!用STM32驱动ESP8266上云的真实项目复盘:硬件选型、代码调试与资源打包
  • 2026最全CTF入门指南、CTF夺旗赛及刷题网站(建议收藏!)
  • CANN / ops-cv 量化介绍
  • 教育AI演进:从自动化工具到混合智能协同的实践路径
  • 阿里FunASR模型体验:Speech Seaco Paraformer ASR,单文件批量处理全支持
  • CANN/PTO-ISA自定义算子示例
  • Taotoken多模型聚合平台助力智能客服场景降本增效
  • CANN/AMCT API接口文档
  • 去中心化AI架构解析:从区块链信任到分布式AI协作网络
  • 在Nodejs后端服务中集成稳定可靠的大模型调用能力
  • CANN/cannbot-skills A5设备约束指南
  • 2026届必备的六大降AI率助手实测分析
  • 自监督学习、能量模型与JEPA:构建下一代AI世界模型的核心技术
  • CANN社区机器人能力列表
  • 多模态大模型赋能港口,从视频孪生迈向空间原生智能
  • Phi-4-Reasoning-Vision商业应用:电商商品图深度解析+卖点自动生成方案
  • AI优化疫苗接种干预:ADVISER框架在尼日利亚公共卫生最后一公里的实践
  • FireRedASR-AED-L入门必看:1.1B参数大模型本地化部署全流程
  • 如何快速掌握鼠标键盘自动化:KeymouseGo完整入门指南
  • 全面掌握Windows驱动管理:DriverStore Explorer实战指南
  • 3分钟掌握微信聊天记录解密:WechatDecrypt让你的数据重获自由
  • CAPL编程避坑指南:搞懂NetWork Node里的全局变量、文件包含与编译那些事儿
  • 律师上课记干货太吃力!2026年3款b站视频怎么转文字工具,1分钟导出整理办案笔记