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

昇思25天学习打卡营第6天|使用静态图加速

学AI还能赢奖品?每天30分钟,25天打通AI任督二脉 (qq.com)

背景介绍

AI编译框架分为两种运行模式,分别是动态图模式以及静态图模式。MindSpore默认情况下是以动态图模式运行,但也支持手工切换为静态图模式。两种运行模式的详细介绍如下:

动态图模式

动态图的特点是计算图的构建和计算同时发生(Define by run),其符合Python的解释执行方式,在计算图中定义一个Tensor时,其值就已经被计算且确定,因此在调试模型时较为方便,能够实时得到中间结果的值,但由于所有节点都需要被保存,导致难以对整个计算图进行优化。

在MindSpore中,动态图模式又被称为PyNative模式。由于动态图的解释执行特性,在脚本开发和网络流程调试过程中,推荐使用动态图模式进行调试。 如需要手动控制框架采用PyNative模式,可以通过以下代码进行网络构建:

%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
import numpy as np
import mindspore as ms
from mindspore import nn, Tensor
#ms.context.set_context(device_target="CPU")
ms.set_context(mode=ms.PYNATIVE_MODE)  # 使用set_context进行动态图模式的配置class Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsmodel = Network()
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))
output = model(input)
print(output)

动态图模式(PyNative):

动态图模式与Python的解释执行方式一致,适合于脚本开发和网络流程调试。

在此模式下,计算图的构建和计算同时发生,便于实时获取中间结果,便于调试。

动态图模式下,所有节点都需要保存,可能导致计算图优化困难。

静态图模式

相较于动态图而言,静态图的特点是将计算图的构建和实际计算分开(Define and run)。有关静态图模式的运行原理,可以参考静态图语法支持。

在MindSpore中,静态图模式又被称为Graph模式,在Graph模式下,基于图优化、计算图整图下沉等技术,编译器可以针对图进行全局的优化,获得较好的性能,因此比较适合网络固定且需要高性能的场景。

如需要手动控制框架采用静态图模式,可以通过以下代码进行网络构建:

import numpy as np
import mindspore as ms
from mindspore import nn, Tensor
ms.set_context(mode=ms.GRAPH_MODE)  # 使用set_context进行运行静态图模式的配置class Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsmodel = Network()
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))
output = model(input)
print(output)

静态图模式(Graph)

静态图模式将计算图的构建和计算分离,允许编译器进行全局优化,提高执行效率。

适用于网络结构固定且需要高性能的场景。

静态图模式下,需要先编译后执行,可能存在编译耗时。

静态图模式的使用场景

MindSpore编译器重点面向Tensor数据的计算以及其微分处理。因此使用MindSpore API以及基于Tensor对象的操作更适合使用静态图编译优化。其他操作虽然可以部分入图编译,但实际优化作用有限。另外,静态图模式先编译后执行的模式导致其存在编译耗时。因此,如果函数无需反复执行,那么使用静态图加速也可能没有价值。

有关使用静态图来进行网络编译的示例,请参考网络构建。

静态图模式开启方式

通常情况下,由于动态图的灵活性,我们会选择使用PyNative模式来进行自由的神经网络构建,以实现模型的创新和优化。但是当需要进行性能加速时,我们需要对神经网络部分或整体进行加速。MindSpore提供了两种切换为图模式的方式,分别是基于装饰器的开启方式以及基于全局context的开启方式。

基于装饰器的开启方式

MindSpore提供了jit装饰器,可以通过修饰Python函数或者Python类的成员函数使其被编译成计算图,通过图优化等技术提高运行速度。此时我们可以简单的对想要进行性能优化的模块进行图编译加速,而模型其他部分,仍旧使用解释执行方式,不丢失动态图的灵活性。无论全局context是设置成静态图模式还是动态图模式,被jit修饰的部分始终会以静态图模式进行运行。

在需要对Tensor的某些运算进行编译加速时,可以在其定义的函数上使用jit修饰器,在调用该函数时,该模块自动被编译为静态图。需要注意的是,jit装饰器只能用来修饰函数,无法对类进行修饰。jit的使用示例如下:

import numpy as np
import mindspore as ms
from mindspore import nn, Tensorclass Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsinput = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))@ms.jit  # 使用ms.jit装饰器,使被装饰的函数以静态图模式运行
def run(x):model = Network()return model(x)output = run(input)
print(output)

除使用修饰器外,也可使用函数变换方式调用jit方法,示例如下:

import numpy as np
import mindspore as ms
from mindspore import nn, Tensorclass Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsinput = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))def run(x):model = Network()return model(x)run_with_jit = ms.jit(run)  # 通过调用jit将函数转换为以静态图方式执行
output = run(input)
print(output)

当我们需要对神经网络的某部分进行加速时,可以直接在construct方法上使用jit修饰器,在调用实例化对象时,该模块自动被编译为静态图。示例如下:

import numpy as np
import mindspore as ms
from mindspore import nn, Tensorclass Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))@ms.jit  # 使用ms.jit装饰器,使被装饰的函数以静态图模式运行def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsinput = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))
model = Network()
output = model(input)
print(output)

基于context的开启方式

context模式是一种全局的设置模式。代码示例如下:

import numpy as np
import mindspore as ms
from mindspore import nn, Tensor
ms.set_context(mode=ms.GRAPH_MODE)  # 使用set_context进行运行静态图模式的配置class Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512),nn.ReLU(),nn.Dense(512, 512),nn.ReLU(),nn.Dense(512, 10))def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logitsmodel = Network()
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))
output = model(input)
print(output)

这段代码与背景介绍中的静态图模式示例代码相同。

开启方式有2种:

jit开启,可以部分进行加速。jit装饰器开启方式,只能用来修饰函数,无法对类进行修饰。除使用修饰器外,也可使用函数变换方式调用jit方法。

context开启。是一种全局的设置模式。

静态图的语法约束

在Graph模式下,Python代码并不是由Python解释器去执行,而是将代码编译成静态计算图,然后执行静态计算图。因此,编译器无法支持全量的Python语法。MindSpore的静态图编译器维护了Python常用语法子集,以支持神经网络的构建及训练。详情可参考静态图语法支持。

JitConfig配置选项

在图模式下,可以通过使用JitConfig配置选项来一定程度的自定义编译流程,目前JitConfig支持的配置参数如下:

  • jit_level: 用于控制优化等级。
  • exec_mode: 用于控制模型执行方式。
  • jit_syntax_level: 设置静态图语法支持级别,详细介绍请见静态图语法支持。

静态图高级编程技巧

使用静态图高级编程技巧可以有效地提高编译效率以及执行效率,并可以使程序运行的更加稳定。详情可参考静态图高级编程技巧。

MindSpore支持动态图模式和静态图模式两种运行模式。动态图模式便于调试,但所有节点都需要保存,难以优化;静态图模式则在执行前先编译计算图,适用于性能要求高的场景。

可以通过设置context或jit方式切换运行模式。使用jit可以对部分代码进行静态图模式的优化。context是全局的设置。

静态图模式下有语法限制,只支持Python的部分语法。

可以通过JitConfig配置选项自定义编译流程。

其他静态图高级编程技巧。

相关文章:

  • Django 模版转义
  • LeetCode 算法:二叉树的中序遍历 c++
  • qemu 安装ubuntu22.04虚拟机 -纯命令行-可ssh-带网络-编译安装 linux kernel-编译安装 kernel module
  • 打包体积分析和优化
  • JDK动态代理
  • SolidityFoundry 安全审计测试 Delegatecall漏洞2
  • 【Unity服务器01】之【AssetBundle上传加载u3d模型】
  • 前端 三维空间笔记
  • Java中的NIO编程实践精华
  • 程序的“通用性”和“过度设计”困境
  • zookeeper学习、配置文件参数详解
  • SSM旅游系统
  • WDF驱动开发-WDF总线枚举(一)
  • obsidian中用check list 打造待办清单
  • 在阿里云使用Docker部署MySQL服务,并且通过IDEA进行连接
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • C++11: atomic 头文件
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • HomeBrew常规使用教程
  • HTTP中的ETag在移动客户端的应用
  • Java程序员幽默爆笑锦集
  • learning koa2.x
  • npx命令介绍
  • Travix是如何部署应用程序到Kubernetes上的
  • Vim Clutch | 面向脚踏板编程……
  • 让你的分享飞起来——极光推出社会化分享组件
  • 什么软件可以剪辑音乐?
  • 使用putty远程连接linux
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • !!Dom4j 学习笔记
  • #define,static,const,三种常量的区别
  • #etcd#安装时出错
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (2)空速传感器
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (八十八)VFL语言初步 - 实现布局
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)python发送HTTP 请求的两种方式(get和post )
  • ******之网络***——物理***
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net core 连接数据库,通过数据库生成Modell
  • .NET Core 中插件式开发实现
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET单元测试
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .NET使用存储过程实现对数据库的增删改查
  • .NET正则基础之——正则委托
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • [8481302]博弈论 斯坦福game theory stanford week 1