『MXNet』第六弹_Gluon性能提升 静态图 动态图 符号式编程 命令式编程
https://www.cnblogs.com/hellcat/p/9084894.html
一、符号式编程
1、命令式编程和符号式编程
命令式:
|
1
2
3
4
5
6
7
8
9
10
|
def add(a, b): return a + bdef fancy_func(a, b, c, d): e = add(a, b) f = add(c, d) g = add(e, f) return gfancy_func(1, 2, 3, 4) |
符号式:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
def add_str(): return '''def add(a, b): return a + b'''def fancy_func_str(): return '''def fancy_func(a, b, c, d): e = add(a, b) f = add(c, d) g = add(e, f) return g'''def evoke_str(): return add_str() + fancy_func_str() + '''print(fancy_func(1, 2, 3, 4))'''prog = evoke_str()print(prog)y = compile(prog, '', 'exec')exec(y) |
以上定义的三个函数都只是返回计算流程。最后,我们编译完整的计算流程并运行。
由于在编译时系统能够完整地看到整个程序,因此有更多空间优化计算。例如,编译的时候可以将程序改写成print((1 + 2) + (3 + 4)),甚至直接改写成print(10)。这样不仅减少了函数调用,还节省了内存。
2.MXNet的符号式编程
Sequential类 -> HybridSequential类
Block类 -> HybridBlock类
使用上面两个基于Hybrid的类构建的网络实例会具有.hybridize()方法,进行.hybridize()声明之后网络的第一次运行会生成编译好的C++代码,之后再运行网络实例不会运行python代码,而回转向C++代码,也就是"静态图",同样的,MXNet的静态结构决定了其对python的动态控制流程不支持(同TensorFlow),但是效率大大提升。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def get_net(): net = nn.HybridSequential() net.add( nn.Dense(256, activation="relu"), nn.Dense(128, activation="relu"), nn.Dense(2) ) net.initialize() return netx = nd.random.normal(shape=(1, 512))net = get_net()net(x) |
我们可以通过调用hybridize函数来编译和优化HybridSequential实例中串联的层的计算。模型的计算结果不变。
In [5]:
net.hybridize()
net(x)
Out[5]:
[[ 0.08827581 0.00505182]]
<NDArray 1x2 @cpu(0)>
需要注意的是,只有继承HybridBlock的层才会被优化。例如,HybridSequential类和Gluon提供的Dense类都是HybridBlock的子类,它们都会被优化计算。如果一个层只是继承自Block而不是HybridBlock类,那么它将不会被优化。我们接下会讨论如何使用HybridBlock类。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class HybridNet(nn.HybridBlock): def __init__(self, **kwargs): super(HybridNet, self).__init__(**kwargs) self.hidden = nn.Dense(10) self.output = nn.Dense(2) def hybrid_forward(self, F, x): print('F: ', F) print('x: ', x) x = F.relu(self.hidden(x)) print('hidden: ', x) return self.output(x) |
在继承HybridBlock类时,我们需要在hybrid_forward函数中添加额外的输入F。我们知道,MXNet既有基于命令式编程的NDArray类,又有基于符号式编程的Symbol类。由于这两个类的函数基本一致,MXNet会根据输入来决定F使用NDArray或Symbol。
In [12]:
net.hybridize()
net(x)F: <module 'mxnet.symbol' from '/var/lib/jenkins/miniconda3/envs/gluon_zh_docs/lib/python3.6/site-packages/mxnet/symbol/__init__.py'>
x: <Symbol data>
hidden: <Symbol hybridnet0_relu0>
Out[12]:
[[ 0.00370749 0.00134991]]
<NDArray 1x2 @cpu(0)>
可以看到,F变成了Symbol。而且,虽然输入数据还是NDArray,但hybrid_forward函数里,相同输入和中间输出全部变成了Symbol。
再运行一次看看。
In [13]:
net(x)
Out[13]:
[[ 0.00370749 0.00134991]]
<NDArray 1x2 @cpu(0)>
可以看到hybrid_forward函数里定义的三行打印语句都没有打印任何东西。这是因为上一次在调用hybridize函数后运行net(x)的时候,符号式程序已经得到。之后再运行net(x)的时候MXNet将不再访问Python代码,而是直接在C++后端执行符号式程序。这也是调用hybridize后模型计算性能会提升的一个原因。但它可能的问题是我们损失了写程序的灵活性。在上面这个例子中,如果我们希望使用那三行打印语句调试代码,执行符号式程序时会跳过它们无法打印。
此外,对于少数Symbol不支持的函数,例如asnumpy,我们是无法在hybrid_forward函数中使用并在调用hybridize函数后进行模型计算的(mxnet.sym类即为Symbol类,支持大部分Ndarray操作)。
二、惰性计算
可以使用不同的前端语言编写MXNet程序,像Python、R、Scala和C++。无论使用何种前端编程语言,MXNet程序的执行主要都发生在C++实现的后端。换句话说,用户写好的前端MXNet程序会传给后端执行计算。后端有自己的线程来不断收集任务,构造、优化并执行计算图。后端优化的方式有很多种,其中包括本章将介绍的惰性计算。
假设我们在前端调用以下四条语句。MXNet后端的线程会分析它们的依赖关系并构建出如下图所示的计算图。
In [3]:
a = nd.ones((1, 2))
b = nd.ones((1, 2))
c = a * b + 2
c
Out[3]:
[[ 3. 3.]]
<NDArray 1x2 @cpu(0)>
在惰性计算中,前端执行前三条语句的时候,仅仅是把任务放进后端的队列里就返回了。当最后一条语句需要打印计算结果时,前端会等待后端线程把c的结果计算完。此设计的一个好处是,这里的Python前端线程不需要做实际计算。因此,无论Python的性能如何,它对整个程序性能的影响会很小。只要C++后端足够高效,那么不管前端语言性能如何,MXNet都可以提供一致的高性能。
用同步函数实际计算出结果
print()
nd数组.wait_to_read()
nd.waitall()
由于asnumpy、asscalar(Python内置、numpy等数据结构并不支持惰性计算)和print函数会触发让前端等待后端计算结果的行为,我们通常把这类函数称作同步函数。
三、自动并行
在“惰性计算”里我们提到MXNet后端会自动构建计算图。通过计算图,系统可以知道所有计算的依赖关系,并可以选择将没有依赖关系的多个任务并行执行来获得性能的提升。以“惰性计算”一节中的计算图为例。其中a=nd.ones((1,2))和b=nd.ones((1,2))这两步计算之间并没有依赖关系。因此,系统可以选择并行执行它们。
通常一个运算符会用掉一个CPU/GPU上所有计算资源。例如,dot操作符会用到所有CPU(即使是有多个CPU)或单个GPU上所有线程。因此在单CPU/GPU上并行运行多个运算符可能效果并不明显。
MXNet通过自动并行计算提升计算性能,主要经由CPU和GPU的并行以及计算和通讯的并行实现,
『MXNet』第六弹_Gluon性能提升 静态图 动态图 符号式编程 命令式编程的更多相关文章
- 『MXNet』第六弹_Gluon性能提升
一.符号式编程 1.命令式编程和符号式编程 命令式: def add(a, b): return a + b def fancy_func(a, b, c, d): e = add(a, b) f = ...
- 『MXNet』第四弹_Gluon自定义层
一.不含参数层 通过继承Block自定义了一个将输入减掉均值的层:CenteredLayer类,并将层的计算放在forward函数里, from mxnet import nd, gluon from ...
- 『MXNet』第三弹_Gluon模型参数
MXNet中含有init包,它包含了多种模型初始化方法. from mxnet import init, nd from mxnet.gluon import nn net = nn.Sequenti ...
- 『MXNet』第十一弹_符号式编程初探
一.符号分类 符号对我们想要进行的计算进行了描述, 下图展示了符号如何对计算进行描述. 我们定义了符号变量A, 符号变量B, 生成了符号变量C, 其中, A, B为参数节点, C为内部节点! mxne ...
- 『MXNet』第八弹_数据处理API_下_Image IO专题
想学习MXNet的同学建议看一看这位博主的博客,受益良多. 在本节中,我们将学习如何在MXNet中预处理和加载图像数据. 在MXNet中加载图像数据有4种方式. 使用 mx.image.imdecod ...
- 『MXNet』第十弹_物体检测SSD
全流程地址 一.辅助API介绍 mxnet.image.ImageDetIter 图像检测迭代器, from mxnet import image from mxnet import nd data_ ...
- 『MXNet』第八弹_数据处理API_上
一.Gluon数据加载 下面的两个dataset处理类一般会成对出现,两个都可做预处理,但是由于后面还可能用到原始图片,.ImageFolderDataset不加预处理的话可以满足,所以建议在.Dat ...
- 『MXNet』第七弹_多GPU并行程序设计
资料原文 一.概述思路 假设一台机器上有个GPU.给定需要训练的模型,每个GPU将分别独立维护一份完整的模型参数. 在模型训练的任意一次迭代中,给定一个小批量,我们将该批量中的样本划分成份并分给每个G ...
- 『MXNet』第五弹_MXNet.image图像处理
简单处理API 读取图像: image.imdecode(open('../img/cat1.jpg', 'rb').read()) 图像类型转换: img.astype('float32') 图像增 ...
随机推荐
- SpringCloud学习心得—1.3—Eureka与REST API
SpringCloud学习心得—1.3—Eureka与REST API Eureka的REST API接口 API的基本访问 Eureka REST APIEureka 作为注册中心,其本质是存储 ...
- 使用wc -l 来统计代码行数
Linux使用wc来统计行数真的好用 如在当前路径下统计一共多少行代码 $ find ./ -name *.c |xargs wc -l #包括了空行 ##-l :lines 如果不包括空行 ¥fin ...
- python3 操作 hive 安装依赖包整理
安装依赖pip install saslpip install thriftpip install thrift-saslpip install PyHive windows安装sasl报错,解决方案 ...
- 如何利用AI识别未知——加入未知类(不太靠谱),检测待识别数据和已知样本数据的匹配程度(例如使用CNN降维,再用knn类似距离来实现),将问题转化为特征搜索问题而非决策问题,使用HTM算法(记忆+模式匹配预测就是智能),GAN异常检测,RBF
https://www.researchgate.net/post/How_to_determine_unknown_class_using_neural_network 里面有讨论,说是用rbf神经 ...
- 07 c++中的内联函数inline
文章链接: 问题描述:类中成员函数缺省默认是内联的,如果在类定义时就在类内给出函数定义,那当然最好.如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上 inline,否则就认为不是内联 ...
- 大数据之路week07--day06 (Sqoop 的使用)
Sqoop的使用一(将数据库中的表数据上传到HDFS) 首先我们先准备数据 1.没有主键的数据(下面介绍有主键和没有主键的使用区别) -- MySQL dump 10.13 Distrib 5.1.7 ...
- 《BUG创造队》作业8:软件测试与Alpha冲刺(第二天)
项目 内容 这个作业属于哪个课程 2016级软件工程 这个作业的要求在哪里 实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 BUG创造队 作业学习目标 (1)掌握软件测试基础技术.(2)学习 ...
- 【CSP-S 2019】【洛谷P5664】Emiya 家今天的饭【dp】
题目 题目链接:https://www.luogu.org/problem/P5664 Emiya 是个擅长做菜的高中生,他共掌握 \(n\) 种烹饪方法,且会使用 \(m\) 种主要食材做菜.为了方 ...
- asp.net大文件分块上传断点续传demo
IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...
- .net大文件分块上传断点续传demo
IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...