深度学习框架太抽象?其实不外乎这五大核心组件

由于此前的大部分实现都是基于高级语言的(如Java、Python、Lua等),而即使是执行最简单的操作,高级语言也会比低级语言消耗更多的CPU周期,更何况是结构复杂的深度神经网络,因此运算缓慢就成了高级语言的一个天然的缺陷。

目前针对这一问题有两种解决方案。

第一种方法是模拟传统的编译器。就好像传统编译器会把高级语言编译成特定平台的汇编语言实现高效运行一样,这种方法将高级语言转换为C语言,然后在C语言基础上编译、执行。为了实现这种转换,每一种张量操作的实现代码都会预先加入C语言的转换部分,然后由编译器在编译阶段将这些由C语言实现的张量操作综合在一起。目前pyCUDA和Cython等编译器都已经实现了这一功能。

第二种方法就是前文提到的,利用脚本语言实现前端建模,用低级语言如C++实现后端运行,这意味着高级语言和低级语言之间的交互都发生在框架内部,因此每次的后端变动都不需要修改前端,也不需要完整编译(只需要通过修改编译参数进行部分编译),因此整体速度也就更快。

除此之外,由于低级语言的最优化编程难度很高,而且大部分的基础操作其实也都有公开的最优解决方案,因此另一个显著的加速手段就是利用现成的扩展包。例如最初用Fortran实现的BLAS(基础线性代数子程序),就是一个非常优秀的基本矩阵(张量)运算库,此外还有英特尔的MKL(Math Kernel Library)等,开发者可以根据个人喜好灵活选择。

深度学习框架太抽象?其实不外乎这五大核心组件

值得一提的是,一般的BLAS库只是针对普通的CPU场景进行了优化,但目前大部分的深度学习模型都已经开始采用并行GPU的运算模式,因此利用诸如NVIDIA推出的针对GPU优化的cuBLAS和cuDNN等更据针对性的库可能是更好的选择。

运算速度对于深度学习框架来说至关重要,例如同样训练一个神经网络,不加速需要4天的时间,加速的话可能只要4小时。在快速发展的人工智能领域,特别是对那些成立不久的人工智能初创公司而言,这种差别可能就会决定谁是先驱者,而谁是追随者。

总结

原文作者在文末指出:为了向开发者提供尽量简单的接口,大部分深度学习框架通常都会将普通的概念抽象化,这可能是造成许多用户感知不到上述五点核心组件的重要原因。

而这也正是作者写本文的初衷:他希望开发者能够通过了解不同框架之间的一些相似特性,更好地认识和使用一个深度学习框架。另一方面,对于那些不仅对学会使用深度学习框架感兴趣,还打算亲手搭建一个深度框架的朋友,作者认为了解各框架的内部组成和一些共性的特征也是迈向成功的重要一步。他真诚地相信,一个优秀的工程师不仅应该“知其然”,更应该“知其所以然”。