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

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

文章目录

      • 昇思MindSpore入门学习补档
          • 1、基于Mindspore的静态图加速
            • 动态图模式
            • 静态图模式
          • 2、静态图模式的使用场景
            • 静态图模式开启方式
            • 基于装饰器的开启方式
            • 基于context的开启方式
          • 3、 静态图的语法约束
            • JitConfig配置选项
            • 静态图高级编程技巧
      • Reference

昇思MindSpore入门学习补档

本系列文章主要用于记录昇思25天学习打卡营的学习心得。

1、基于Mindspore的静态图加速

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

动态图模式

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

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

import numpy as np
import mindspore as ms
from mindspore import nn, Tensor
ms.set_context(mode=ms.PYNATIVE_MODE)  # 使用set_context进行默认的动态图模式PYNATIVE_MODE的配置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)# print_log
[[ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ][ 0.17612235 -0.18199953  0.19589128 -0.16678973  0.00903675  0.249976290.08076952  0.02316903  0.18818295  0.0068727 ]]
静态图模式

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

在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进行运行静态图模式GRAPH_MODE的配置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)# print_log
[[ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065][ 0.06203532  0.16082796 -0.16709496 -0.13396177 -0.09940557  0.00221913-0.01732909  0.02681888 -0.03247008  0.01964065]]
2024-07-09 15:18:00 Wayn_Fan-sail
2、静态图模式的使用场景

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

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

静态图模式开启方式

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

基于装饰器的开启方式

用过Python的很多同学应该都见过“@xxx”这样的东东,没错,这就是修饰器的意思,修饰器(装饰器)在Python中可以让其他函数在不需要做任何代码变动的前提下增加额外功能,修饰器也叫装饰器,本身也是一个函数,是在原有的函数或者是方法上增添一些额外的功能。

Python内置了一些修饰器,如常见的:@property、@classmethod 和 @staticmethod

@property 装饰器用于将类的方法转换为属性,使得可以像访问属性一样访问方法。
使得访问方法像访问属性一样,代码更简洁。
可以在保持接口不变的情况下更改实现细节。
可以轻松添加对属性的验证和计算逻辑。

@classmethod 装饰器用于定义类方法。类方法的第一个参数必须是表示类本身的 cls,而不是实例。类方法通常用于创建类的工厂方法。
可以访问和修改类级别的属性。
常用于工厂方法,简化对象创建过程。
提供一种替代构造函数的方法来实例化对象。

@staticmethod 装饰器用于定义静态方法。静态方法不依赖于类或实例,它们类似于普通函数,但在类的命名空间中。静态方法通常用于实现逻辑上与类相关但不需要访问类或实例的功能。
逻辑上属于类,但不需要访问类或实例的状态。
不需要传递 self 或 cls 参数

@staticmethod 在很多深度学习网络的代码中经常出现,虽然初学者第一次见会觉得很模糊,但实际上@staticmethod 装饰器可以提高代码组织性,将相关函数放在一起。

言归正传,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)# print_log
[[-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ]...[-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ][-0.12126954  0.06986676 -0.2230821  -0.07087803 -0.01003947  0.010633920.10143848 -0.0200909  -0.09724037  0.0114444 ]]

当我们需要对神经网络的某部分进行加速时,可以直接在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)

除使用修饰器外,也可使用函数变换方式调用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)
基于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)
3、 静态图的语法约束

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

JitConfig配置选项

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

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

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

Reference

昇思大模型平台
昇思官方文档-静态图加速
Python【修饰器/装饰器】
python修饰符(装饰器)@property、@classmethod 和 @staticmethod

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Emacs 的优点及与 DE 的比较
  • 如何在抖音小程序上展示VR全景?
  • C#中的类
  • 代码随想录算法训练营第7天
  • Mybatis——增删改查
  • Django学习收尾
  • 7.9实验室总结 SceneBuilder的使用方法+使用javafx等
  • 【Linux】:程序替换
  • 这不是在搞技术,而是在玩心态~
  • JS进阶-深入对象
  • 音视频封装demo:将h264数据和aac数据封装(mux)成FLV文件(纯手工,不依赖第三方开源库)
  • 面试题007-Java-Spring
  • 华为机试真题--字符串变换最小字符串
  • 初识STM32:寄存器编程 × 库函数编程 × 开发环境
  • ubuntu下aarch64-linux-gnu(交叉编译) gdb/gdbserver
  • [笔记] php常见简单功能及函数
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • CAP 一致性协议及应用解析
  • ES10 特性的完整指南
  • Fundebug计费标准解释:事件数是如何定义的?
  • Node + FFmpeg 实现Canvas动画导出视频
  • PHP 的 SAPI 是个什么东西
  • redis学习笔记(三):列表、集合、有序集合
  • RxJS: 简单入门
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 简单易用的leetcode开发测试工具(npm)
  • 每天一个设计模式之命令模式
  • 使用parted解决大于2T的磁盘分区
  • 探索 JS 中的模块化
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 一个JAVA程序员成长之路分享
  • 一个完整Java Web项目背后的密码
  • 正则表达式
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • 组复制官方翻译九、Group Replication Technical Details
  • # Kafka_深入探秘者(2):kafka 生产者
  • #define用法
  • #if和#ifdef区别
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • $(selector).each()和$.each()的区别
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (20)docke容器
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (十一)手动添加用户和文件的特殊权限
  • (学习日记)2024.01.09
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (一)appium-desktop定位元素原理
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)h264中avc和flv数据的解析
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .NET Core 2.1路线图