IR和运行时的算子差异

举报
黄生 发表于 2025/10/05 19:25:13 2025/10/05
【摘要】 首先是命名差异。命名差异反映了MindSpore从前端算子到后端硬件指令的“翻译”和“封装”过程。IR文件中的 PrimFunc_MatMul 和 PrimFunc_BiasAdd 是计算图层面的高级、通用算子抽象。而在Profiling后mindstudio insight导出的 CSV中,我们看到的是 aclnnMm_MatMulCommon_MatMulV2 和 BiasAdd1。这里...

首先是命名差异。命名差异反映了MindSpore从前端算子到后端硬件指令的“翻译”和“封装”过程。IR文件中的 PrimFunc_MatMulPrimFunc_BiasAdd 是计算图层面的高级、通用算子抽象。而在Profiling后mindstudio insight导出的 CSV中,我们看到的是 aclnnMm_MatMulCommon_MatMulV2BiasAdd1。这里的 aclnn 前缀暗示了这是运行在昇腾(Ascend)平台上的内核函数实现。可以这样理解:PrimFunc_MatMul 是一个接口标准,而 aclnnMm_MatMulCommon_MatMulV2 则是针对昇腾芯片、经过高度优化的具体实现。同样,BiasAdd1 这个带数字后缀的名字也很常见于后端算子库,可能代表了某个特定版本的实现。这种差异是框架为了在不同硬件后端上获得极致性能而进行的正常映射。

然后是算子对应关系。我们发现IR文件中的一些算子在Profiling汇总CSV中“消失”了。最典型的就是第一个节点 PrimFunc_Flatten(展平操作)。它在按算子类型和输入形状分组的CSV中都找不到直接对应项。这背后可能的原因有几个层面:

  1. 算子融合:这是现代AI编译器最核心的优化手段之一。Flatten 操作可能并未作为一个独立的内核启动,而是被与前一个或后一个算子(例如数据搬运或第一个 MatMul)融合了。编译器通过将多个小操作合并成一个复合内核,极大地减少了内核启动次数和内存访问开销,从而提升性能。从Profiling数据看,第一个 MatMul 的输入形状是 "64,784",这恰恰是 Flatten 预期的输出,为融合提供了有力的间接证据。
  2. 实现方式的差异Flatten 在本质上是一个不涉及复杂计算的视图(View)操作或简单的数据重排。在昇腾硬件上,这类操作可能被实现为更底层的、不单独计时的内存操作指令,或者被归并到某个通用的数据准备阶段(甚至可能与 MemSet 这样的内存初始化操作有关),因此在面向计算核心的Profiling数据中无法被直接观测到。
  3. Profiling的粒度:性能分析工具通常有选择性地聚焦于计算密集型或已知的性能关键算子。像MakeTupleUpdateStateDepend 这类在IR中存在的管理性、控制流算子,它们主要负责组织计算图依赖和内存管理,本身计算开销极低,因此不被纳入核心算子的性能分析也是合理的。

Profiling中有一个“不请自来”的算子——MemSet。它在IR蓝图中没有直接体现,却在性能数据中占据了可观的时间(总耗时22.56us)。这说明了运行时环境与纯计算图的区别。MemSet 是底层系统为输出张量分配内存并进行初始化的操作。它的存在提醒我们,模型的实际推理时间并不仅仅包含“计算”,还包含了不可或缺的“内存管理”开销。

最后,我们做一下MemSet 和 IR 中的 Load 算子的关联分析。Load (IR层面) 是一个 “数据搬运” 操作。它的功能是将模型权重(如 dense_relu_sequential.0.weight)从存储它的常量内存或全局内存中,搬运到计算核心(AI Core/Vector Core)能够高速访问的本地缓冲区中。MemSet (Profiling层面) 是一个 “内存初始化” 操作。它的核心任务是在计算开始前,为输出张量分配一块内存区域并将其初始化为一个已知的状态(通常是零)。

一个典型的计算单元(如 MatMul)的执行流程可以分解为:

  • 阶段一:输出缓冲区准备 -> 由 MemSet 完成。系统为即将到来的矩阵乘法结果(例如 [64, 512] 的张量)准备好“空容器”。
  • 阶段二:输入数据就位 -> 由 Load 操作完成。将计算所需的权重数据(例如 [512, 784] 的矩阵)从慢速存储(可能在host侧)搬运到计算核心附近的快速内存中。输入数据 x 可能也已通过其他方式就绪。
  • 阶段三:核心计算 -> 由 MatMul 内核执行。计算核心从快速内存中读取输入(Load 的结果),进行计算,并将结果写入已初始化的内存(MemSet 准备的缓冲区)。

从这个流程看,MemSetLoad 是计算内核执行前两个并行的、必不可少的内存准备步骤。在 Profiling CSV 中,我们看到 MemSet 被明确记录和计时,但 IR 中的 Load 却没有对应的独立条目。这可能是因为性能分析工具通常会更侧重于标记计算密集型操作和显式的内存初始化操作。像 Load 这种纯粹的数据搬运,如果其执行单元(如DMA)的活动被工具以独立事件捕获,但可能并不被看做算子,因此并没有出现在算子列表中。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。