如何查看MindSpore的IR图

1、为什么需要IR图

中间表示(Intermediate Representation)是编译器用于表示源代码的数据结构或代码,通常深度学习框架中都会有IR这种表达,用于将用户脚本语言翻译成底层语言,介于源语言和目标语言之间的程序表示。相当于IR定义了一套从脚本到机器语言的翻译逻辑,便于编译器进行程序分析与优化。好的中间表示有利于AI模型的编译优化和执行,是AI框架进行高效训练和推理的基础。

MindSpore作为2020年3月华为正式开源的一套全场景AI计算框架,同样提供一种基于图表示的函数式中间表示,即:MindIR。通过统一的算子IR定义,消除不同后端的模型差异。MindIR是基于图表示的函数式表达,接近于ANF函数式的语义。

2、IR图目前有哪些类型

从训练的角度看,目前业界的AI框架有三种执行模式:Eager执行模式、图执行模式和Staging(混合)执行模式,其中高性能模式下(Graph执行模式和Staging执行模式)都要基于图层IR。

MindIR更偏向于图执行模式,根据Python脚本的AST进行构图。将AST语义转换成ANF语义。可以覆盖控制流等复杂网络的各种语法表达,同时兼顾到编译性能。由于ANF是一种函数式语言,所以会存在副作用的问题。目前MindSpore在图模式下也已支持消除副作用。

MindIR具有以下特点:

(1)是基于图的。MindSpore框架同时支持静态图和动态图。其中IR的表示主要是针对图模式。其中的函数是可以被递归调用,也可以被当做参数传到其他的函数中,或者从其他函数中返回,使得MindSpore可以表达一系列的控制流结构。

(2)是纯函数的。纯函数是指函数的结果只依赖函数的参数。若函数依赖或影响外部的状态,比如,函数会修改外部全局变量,或者函数的结果依赖全局变量的值,则称函数具有副作用。若使用了带有副作用的函数,代码的执行顺序必须得到严格的保证,否则可能会得到错误的结果,比如对全局变量的先写后读变成了先读后写。值得说明的是,MindSpore图模式已支持副作用的表达,能够将副作用的表达转换为纯函数的表达,从而在保持ANF函数式语义不变的同时,确保执行顺序的正确性,从而实现自由度更高的自动微分。对比Jaxpr IR来说,它是一种强类型、纯函数的中间表示,其输入、输出都带有类型信息,函数输出只依赖输入,不依赖全局变量。所以Jax的静态模式下并不支持副作用的表达,即有全局变量使用的限制。

(3)是支持闭包表示的。反向模式的自动微分,需要存储基本操作的中间结果到闭包中,然后再去进行组合连接。所以有一个自然的闭包表示尤为重要。闭包是指代码块和作用域环境的结合,在MindIR中,代码块是以函数图呈现的,而作用域环境可以理解为该函数被调用时的上下文环境。

(4)是强类型的。每个节点需要有一个具体的类型,这个对于性能最大化很重要。在机器学习应用中,因为算子可能很耗费时间,所以越早捕获错误越好。因为需要支持函数调用和高阶函数,相比于TensorFlow的数据流图,MindIR的类型和形状推导更加复杂且强大。

3、如何得到一段脚本对应的IR图,如何查看IR图

通过context.set_context(save_graphs=True)来保存各个编译阶段的中间代码。被保存的中间代码有两种格式,一个是后缀名为.ir的文本格式,一个是后缀名为.dot的图形化格式。当网络规模不大时,建议使用更直观的图形化格式来查看,当网络规模较大时建议使用更高效的文本格式来查看。

DOT文件可以通过graphviz转换为图片格式来查看,例如将dot转换为png的命令是dot -Tpng *.dot -o *.png

下面通过一个用例来生成和查看IR图。新建一个test.py的Python文件,如下。

from mindspore import Tensor, context, Parameter, ms_function
import mindspore as ms
import mindspore.nn as nn
import numpy as np
from mindspore.ops import functional as F


context.set_context(mode=context.GRAPH_MODE, save_graphs=True)

def test():
  class TestNet(nn.Cell):
    def __init__(self):
      super(TestNet, self).__init__()
      self.weight = Parameter(Tensor(np.array(0), ms.int32), name="param")

    def construct(self, x):
      out = 0
      i = 0
      while i < 3:
        F.assign(self.weight, i)
        out = x * self.weight + out
        i = i + 1
      return out

  net = TestNet()
  input_x = Tensor(np.array(1), ms.int32)
  res = net(input_x)
  print("res:", res)

设置了保存IR图的命令后(即:save_graphs=True),执行脚本:pytest -s test.py

可以在当前路径下得到多个以.ir为后缀的文件。不同阶段会有不同的IR图对应,从而便于框架开发者和用户了解具体每一步的优化逻辑,便于问题定位。编译流程在前后端会存在更多的优化流程,这些优化流程以现有IR为输入,又以新生成的IR为输出,被称为优化器。优化器负责分析并改进中间表示,极大程度的提高了编译流程的可拓展性,也降低了优化流程对前端和后端的破坏。

对应初级开发者来说,将得到的IR图信息即dot文件,转换成图片格式更便于理解。

首先我们需要了解MindSpore中的ANF文法。MindIR中的ANode对应于ANF的原子表达式,ValueNode用于表示常数值,ParameterNode用于表示函数的形参,CNode则对应于ANF的复合表达式,表示函数调用。

<ANode> ::= <ValueNode> | <ParameterNode>
<ParameterNode> ::= Parameter
<ValueNode> ::= Scalar | Named | Tensor | Type | Shape
               | Primitive | MetaFuncGraph | F
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值