MindSpore IR中的CNode节点解析
【摘要】 以 22_execute_0693.ir 里的19个cnodes为例,该IR文件通过MNIST数据集的推理过程产生。[mindspore@asc ir]$ grep "%[0-9]\+" 22_execute_0693.ir%0(CNode_256) = PrimFunc_Flatten(%para1_x) cnode_attrs: {checkpoint: Bool(1), is_dyna...
以 22_execute_0693.ir 里的19个cnodes为例,该IR文件通过MNIST数据集的推理过程产生。
[mindspore@asc ir]$ grep "%[0-9]\+" 22_execute_0693.ir
%0(CNode_256) = PrimFunc_Flatten(%para1_x) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%1(ValueNode_257$input_data$logits) = Load(%para2_dense_relu_sequential.0.weight, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%2(x) = PrimFunc_MatMul(%0, %1, Bool(0), Bool(1)) {instance name: matmul} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%3(ValueNode_258$input_data$logits) = Load(%para3_dense_relu_sequential.0.bias, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%4(x) = PrimFunc_BiasAdd(%2, %3, I64(0)) {instance name: bias_add} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%5(CNode_259$input_data$logits) = PrimFunc_ReLU(%4) {instance name: relu} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%6(ValueNode_260$input_data$logits) = Load(%para4_dense_relu_sequential.2.weight, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%7(x) = PrimFunc_MatMul(%5, %6, Bool(0), Bool(1)) {instance name: matmul} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%8(ValueNode_261$input_data$logits) = Load(%para5_dense_relu_sequential.2.bias, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%9(x) = PrimFunc_BiasAdd(%7, %8, I64(0)) {instance name: bias_add} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%10(CNode_262$input_data$logits) = PrimFunc_ReLU(%9) {instance name: relu} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%11(ValueNode_263$input_data$logits) = Load(%para6_dense_relu_sequential.4.weight, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%12(x) = PrimFunc_MatMul(%10, %11, Bool(0), Bool(1)) {instance name: matmul} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%13(ValueNode_264$input_data$logits) = Load(%para7_dense_relu_sequential.4.bias, UMonad[U]) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%14(x) = PrimFunc_BiasAdd(%12, %13, I64(0)) {instance name: bias_add} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%15(ValueNode_265) = MakeTuple(%11, %6, %1, %3, %8, %13) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%16(ValueNode_266) = UpdateState(UMonad[U], %15) cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
%17(CNode_267$logits) = Depend(%14, %16) primitive_attrs: {side_effect_propagate: I64(1)} cnode_attrs: {checkpoint: Bool(1), is_dynamic_len: Bool(0)}
Return(%17) primitive_attrs: {visited: Bool(1)} cnode_attrs: {checkpoint: Bool(1)}
Node(节点) 是 MindSpore 计算图中的一个基本单元。包括:
- CNode(计算节点)
- Parameter Node(参数节点)
- ValueNode(常量节点)
- Primitive Node(算子节点)
CNode(Compute Node,计算节点) 是 实际执行计算的节点,如算子调用、函数调用等。每个 CNode 包含:
- 输入(其他 Node)
- 算子(Primitive)
- 属性(attrs)
在 IR 中,CNode 通常以 CNode_xxx
或带别名的形式出现(如 %2(x)
)。19 个 CNode 的详细说明如下:
序号 | CNode 名称 | 算子/操作 | 输入 | 输出形状 | 说明 |
---|---|---|---|---|---|
1 | %0(CNode_256) |
PrimFunc_Flatten |
%para1_x |
(64, 784) |
将输入展平 |
2 | %1(ValueNode_257...) |
Load |
%para2_weight + UMonad |
(512, 784) |
加载权重1 |
3 | %2(x) |
PrimFunc_MatMul |
%0 , %1 , Bool(0) , Bool(1) |
(64, 512) |
第一层矩阵乘 |
4 | %3(ValueNode_258...) |
Load |
%para3_bias + UMonad |
(512) |
加载偏置1 |
5 | %4(x) |
PrimFunc_BiasAdd |
%2 , %3 , I64(0) |
(64, 512) |
加偏置1 |
6 | %5(CNode_259...) |
PrimFunc_ReLU |
%4 |
(64, 512) |
ReLU激活 |
7 | %6(ValueNode_260...) |
Load |
%para4_weight + UMonad |
(512, 512) |
加载权重2 |
8 | %7(x) |
PrimFunc_MatMul |
%5 , %6 , Bool(0) , Bool(1) |
(64, 512) |
第二层矩阵乘 |
9 | %8(ValueNode_261...) |
Load |
%para5_bias + UMonad |
(512) |
加载偏置2 |
10 | %9(x) |
PrimFunc_BiasAdd |
%7 , %8 , I64(0) |
(64, 512) |
加偏置2 |
11 | %10(CNode_262...) |
PrimFunc_ReLU |
%9 |
(64, 512) |
ReLU激活 |
12 | %11(ValueNode_263...) |
Load |
%para6_weight + UMonad |
(10, 512) |
加载权重3 |
13 | %12(x) |
PrimFunc_MatMul |
%10 , %11 , Bool(0) , Bool(1) |
(64, 10) |
输出层矩阵乘 |
14 | %13(ValueNode_264...) |
Load |
%para7_bias + UMonad |
(10) |
加载偏置3 |
15 | %14(x) |
PrimFunc_BiasAdd |
%12 , %13 , I64(0) |
(64, 10) |
加偏置3 |
16 | %15(ValueNode_265) |
MakeTuple |
%11 , %6 , %1 , %3 , %8 , %13 |
Tuple of 6 tensors | 打包所有参数 |
17 | %16(ValueNode_266) |
UpdateState |
UMonad , %15 |
UMonad |
更新状态 |
18 | %17(CNode_267$logits) |
Depend |
%14 , %16 |
(64, 10) |
依赖关系处理 |
19 | Return(%17) |
Return |
%17 |
- | 返回最终结果 |
本 IR 中,总 Node 数:39 ,总 CNode 数:19,其余 20 个 Node 可能是 ValueNode、Parameter、Primitive 等非计算节点。CNode类型统计如下:
CNode类型 | 个数 | 具体节点 |
---|---|---|
Load | 6 | %1, %3, %6, %8, %11, %13 |
MatMul | 3 | %2, %7, %12 |
BiasAdd | 3 | %4, %9, %14 |
ReLU | 2 | %5, %10 |
Flatten | 1 | %0 |
MakeTuple | 1 | %15 |
UpdateState | 1 | %16 |
Depend | 1 | %17 |
Return | 1 | Return(%17) |
其中,
- 参数操作: 6个Load
- 核心计算: 3个MatMul + 3个BiasAdd + 2个ReLU + 1个Flatten = 9个
- 图控制(状态管理): 1个MakeTuple + 1个UpdateState + 1个Depend + 1个Return = 4个
下面介绍最后几个依赖关系处理节点的作用:
1. %15(ValueNode_265) = MakeTuple(%11, %6, %1, %3, %8, %13)
# 把所有加载的参数打包成一个元组
参数元组 = (输出层权重, 隐藏层2权重, 隐藏层1权重,
隐藏层1偏置, 隐藏层2偏置, 输出层偏置)
收集所有通过Load
操作加载的参数,为后续的状态更新做准备
2. %16(ValueNode_266) = UpdateState(UMonad[U], %15)
# 更新计算图的状态
新状态 = UpdateState(当前状态, 参数元组)
UMonad:是一个"状态单子",用于跟踪副作用操作(如参数加载),告诉计算图"这些加载操作已经完成了"
3. %17(CNode_267$logits) = Depend(%14, %16)
# 建立依赖关系:确保计算 %14 之前先完成 %16
最终logits = Depend(原始计算结果, 状态更新)
强制计算顺序。“在返回最终logits之前,必须确保所有参数加载操作都已完成”
这些节点确保参数加载操作在计算之前完成,避免了潜在的竞态条件,保证了计算结果的正确性。
- 训练时:参数可能在不断更新,依赖关系很重要
- 推理时:参数是固定的,但MindSpore保持相同的计算图结构
- 一致性:确保训练和推理的计算逻辑一致
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)