mxnet的计算性能

计算性能的重要因子:命令式编程,符号式编程,惰性计算,自动并行计算,多GPU计算。

mxnet的命令式编程和符号式编程

命令式编程:一行一行一次执行,运行非常的慢。
符号式编程:计算流程完全定义好之后才被执行。(Theano,Tensorflow)
符号式编程步骤:1.定义计算流程。2.计算流编译成可执行的程序。3.给定输入,调用编译好的程序执行。

符号式编程Demo

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)

符号式编程优点:1.编译过程中能够看到全部程序,能够做到优化计算。如上列中优化程序:print((1 + 2) + (3 + 4))。2.高效移植,能够将程序变成一个与python无关的格式,能够在非python环境下运行。而命令式编程的优点是方便Debug。Theano,Tensorflow符号式编程。PyTorch使用命令编程。mxnet提倡命令式开发,符号式部署运行。

HybridBlock 和 HybridSequential

默认情况下是命令式编程方式,当调用hybridize函数后,Gluon会转换成符号式编程。

获取符号式程序

net.export(‘my_mlp’)来保存符号式程序和模型参数到硬盘。会生成json和params文件分别为符号式程序和模型参数。
MXNet中符号式程序类型是Symbol,还可以给一个Symbol输入量。形式和Tensorflow很相似。

1
2
x = sym.var('data')
net(x)

HybridBlock,HybridSequential,Sequential,Block,Dense之间的关系

Sequential是Block的子类,HybridSequential,Dense类是HybridBlock的子类。hybrid_forward代替forward函数。基于命令式编程的是NDArray类,基于符号式编程的是Symbol类。当函数调用hybridize函数时,运行net(x)会得到符号式程序,之后调用net(x)不会访问python代码,而是直接在c++后端执行符号式程序。

惰性计算

惰性计算的优点是:能够看到有关变量a的所有计算,从未有更多空间来做优化。例如下面print(a),采用惰性计算能够不计算前两句的赋值语句。
MXNet包含两个部分:用户交互的前端和用来执行的后端。前端语言可以用任意一种语言,MXNet程序执行主要发生在C++后端。主要工作流前端MXNet程序会传给后端执行计算,后端通过线程不断收集任务,构造,优化并执行计算图。

简单演示

1
2
3
4
a = nd.ones((1, 2))
b = nd.ones((1, 2))
c = a * b + 2
print(c)

前端执行前三个语句,把任务放进后端队列。需要打印时,前端等后端线程把c的结果计算完。可以理解为前端python不参与计算,计算都在后端c++来支持的。更好的一点是惰性计算大部分情况对用户是透明的,只要数据保存在NDArray里,而且使用MXNet提供的运算子,默认多行计算。

立即获取结果

1.nd.NDArray.wait_to_read等待特定结果完成。
2.nd.waitall()等待所有前面结果完成
3.任何方法将内容从NDArray搬运到其他不支持延迟执行的数据结构都会触发等待。asnumpy(),asscalar()可以理解为同步函数。

延迟操作会代开更多的内存开销。

多GPU训练

数据并行

数据并行是深度学习里面使用最广泛将任务划分到多设备的办法。原理:多个GPU,每个GPU维护模型参数的复制。将一个批量的样本划分成多块给多个GPU,每个GPU使用分到的数据计算梯度。然后将所有GPU上梯度相加得到这个批量上的整个梯度,用完整梯度对自己维护的模型进行更新。穷人,还没有GPU,想看怎么实现的这里

需要注意的地方是:数据的切分,梯度的累加,参数的更新。