MXNet设计和实现简介(论文笔记)

MXNet论文_2015年

Tensorflow慢一倍的原因:其使用的cuBLAS和cuDNN版本较低;

MXNet最大的优点:节省内存/显存

 

MXNet设计和实现简介

(跟其他框架相比,主要优点就是占用内存少)

 命令式编程声明式编程(有点儿函数式编程的意味)
如何执行 a=b+1需要b已经被赋值。立即执行加法,将结果保存在a中。返回对应的计算图(computation graph),延后执行:我们可以之后对b进行赋值,然后再执行加法运算
优点语义上容易理解,灵活,可以精确控制行为。通常可以无缝地和主语言交互,方便地利用主语言的各类算法,工具包,debug和性能调试器。在真正开始计算的时候已经拿到了整个计算图,所以我们可以做一系列优化来提升性能和内存使用率。实现辅助函数也容易,例如对任何计算图都提供forward和backward函数,对计算图进行可视化,将图保存到硬盘和从硬盘读取。
缺点实现统一的辅助函数和提供整体优化都很困难。很多主语言的特性都用不上。某些在主语言中实现简单,但在这里却经常麻烦,例如if-else语句 。debug也不容易,例如监视一个复杂的计算图中的某个节点的中间结果并不简单。

MXNet尝试将两种模式无缝的结合起来。在命令式编程上MXNet提供张量运算,而声明式编程中MXNet支持符号表达式。用户可以自由的混合它们来快速实现自己的想法。例如可以用声明式编程来描述神经网络,并利用系统提供的自动求导来训练模型。另一方便,模型的迭代训练和更新模型法则中可能涉及大量的控制逻辑,因此我们可以用命令式编程来实现。同时用它来进行方便地调式和与主语言交互数据

KVStore的push和pull跟NDArray一样使用了延后计算的技术。它们只是将对应的操作提交给后台引擎,而引擎则调度实际的数据交互。所以上述的实现跟我们使用纯符号实现的性能相差无几。

MXNet提供工具能将任意大小的样本压缩打包成单个或者数个文件来加速顺序和随机读取。通常数据存在本地磁盘或者远端的分布式文件系统上(例如HDFS或者Amazon S3),每次我们只需要将当前需要的数据读进内存。MXNet提供迭代器可以按块读取不同格式的文件。迭代器使用多线程来解码数据,并使用多线程预读取来隐藏文件读取的开销。

计算图优化

计算图优化已经在数据库等领域被研究多年,我们目前只探索了数个简单的方法。

  1. 注意到我们提前申明了哪些Output变量是需要的,这样我们只需要计算这些Output需要的操作。例如,在预测时不需要计算梯度,所以整个backward图都可以忽略。而在特征抽取中,可能只需要某些中间层的输出,从而可以忽略掉后面的计算。
  2. 可以合并操作。例如 a*b+1, 只需要一个blas或者cuda函数即可,而不需要将其表示成两个操作。
  3. 实现了一些“大”操作,例如一个卷积层就只需要一个操作子。这样我们可以大大减小计算图的大小,并且方便手动的对这个操作进行优化。

内存申请

计算图推断出所有变量的生存期,就是这个变量从创建到最后被使用的时间段,从而可以对两个不交叉的变量重复使用同一内存空间。这个问题在诸多领域,例如编译器的寄存器分配上,有过研究。然而最优的分配算法需要 O(n^2) 时间复杂度,这里n是图中变量的个数。MXNet提供了两个启发式的策略,每个策略都是线性的复杂度。(实验效果:占用内存大小,inplace>co-share>inplace&co-share)

  1. inplace(像引用计数):在这个策略里,我们模拟图的遍历过程,并为每个变量维护一个还有多少其他变量需要它的计数。当我们发现某个变量的计数变成0时,我们便回收其内存空间。
  2. co-share:我们允许两个变量使用同一段内存空间。这么做当然会使得这两个变量不能同时在写这段空间。所以我们只考虑对不能并行的变量进行co-share。每一次我们考虑图中的一条路(path),路上所有变量都有依赖关系所以不能被并行,然后我们对其进行内存分配并将它们从图中删掉。(我的理解:layerA和layerC,肯定不能并行计算,所以可以复用同一段内存,减少内存反复释放和申请的开销;可以提前规划好,运行时按这个执行就好)

引擎

在MXNet中,所有的任务,都会交由引擎来执行。首先,所有的资源单元,例如<NDArray,随机数生成器,和临时空间>,都会在引擎处注册一个唯一的标签。然后每个提交给引擎的任务<矩阵运算,数据通讯>都会标明它所需要的资源标签。引擎则会跟踪每个资源,如果某个任务所需要的资源到到位了,例如产生这个资源的上一个任务已经完成了,那么引擎会则调度和执行这个任务。

通常一个MXNet运行实例会使用多个硬件资源,包括CPU,GPU,PCIe通道,网络,和磁盘,所以引擎会使用多线程来调度,(每个硬件部件使用一个线程来调度任务),既任何两个没有资源依赖冲突的任务都可能会被并行执行,以求最大化资源利用。

通常的数据流引擎不同的是,MXNet的引擎允许一个任务修改现有的资源。为了保证调度正确性,提交任务时需要分开标明哪些资源是只读,哪些资源会被修改。这个附加的写依赖可以带来很多便利。例如我们可以方便实现在numpy以及其他张量库中常见的数组修改操作,同时也使得内存分配时更加容易,比如操作子可以修改其内部状态变量而不需要每次都重来内存。再次,假如我们要用同一个种子生成两个随机数,那么我们可以标注这两个操作会同时修改种子来使得引擎不会并行执行,从而使得代码的结果可以很好的被重复。(两个任务都会修改同一个资源,则这2个任务不会被调度到并行执行,否则会导致写冲突

数据通讯

KVStore的实现是基于参数服务器ps-lite。但它跟前面的工作有两个显著的区别。

1. 使用Engine来调度通信操作

2. 使用一个两层的通讯结构。第一层的服务器管理单机内部的多个设备之间的通讯。第二层服务器则管理机器之间通过网络的通讯。第一层的服务器在与第二层通讯前可能合并设备之间的数据来降低网络带宽消费。同时考虑到机器内和外通讯带宽和延时的不同性,我们可以对其使用不同的一致性模型。例如第一层(单机内部)用强的一致性模型,而第二层(多机之间)用弱的一致性模型来减少同步开销。 (如果使用dist_sync,一个sever首先会将所有的workers产生的梯度值聚合在一起,然后再执行更新,相当于batch增大好几倍。当使用dist_async时,server会在接收到任意worker传来的梯度值后立即更新)

可移植性

轻量和可移植性是MXNet的一个重要目标。MXNet核心使用C++实现,并提供C风格的头文件。因此方便系统移植,也使得其很容易被其他支持C FFI (forigen language interface )的语言调用。此外,我们也提供一个脚本将MXNet核心功能的代码连同所有依赖打包成一个单一的只有数万行的C++源文件,使得其在一些受限的平台,例如智能设备,方便编译和使用。

实验结果

1. 内存(or显存)占用量,明显比其他工具要少;in-place和co-share混合使用效果最好;

2. 同样迭代轮数,10台机器比1台机器的效果,开始差后来好,没解释什么原因。速度上是线性加速比,如果按照“达到同样的效果需要的计算时间”,则是超线性加速比

 

MXNet Python库操作简介

MXNet的Python库有三个基本的概念:

  • NDArray:提供矩阵和张量计算,可在CPU和GPU上进行,并自动化的平行。
  • Symbol:使定义神经网络变得非常简单,并提供自动化的微分。
  • KVStore:使数据在多GPU和多机器之间的同步变得简单。

小技巧:单机上有多个网卡时,可以设置使用哪块(比如用ib0还是用eth0)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值