互联网资讯 / 人工智能 · 2023年12月14日 0

深度学习编译器基础知识

关于深度学习编译器,这些知识你需要了解一下

近年来,深度学习的迅猛发展催生了众多算法开发框架。由于深度学习广泛的应用场景及对计算能力的高需求,我们需要将深度学习算法部署于各种通用和专用硬件上,例如不同类型的CPU、GPU、TPU和NPU等。这就导致了框架与硬件之间的组合问题,如图1所示。例如,若要让TensorFlow支持GPU计算,就必须为TensorFlow中的每个算子开发一个GPU版本;如果还需支持D芯片,则每个算子又需要一个D芯片的版本。这一过程无疑是非常耗时且费力的。

关于深度学习编译器,这些知识你需要了解一下

与此同时,当前有众多算法网络,例如YOLO、BERT、GPT等,这些网络由不同类型、形状及连接关系的算子构成。最终,它们都会在各类硬件上运行。这使得人工为每个场景开发和实现最佳算子的成本极高。举两个例子,如图2所示,算子融合是常用的性能优化方法。在融合之前,每个算子计算前后都需要将数据从内存读入缓存,再从缓存写回内存。而通过融合,则可以避免算子之间的内存读写,从而提升性能。传统方法依赖人工针对算子连接关系开发融合算子,但不同网络和算子之间的连接关系几乎不可能完全列举。另一个例子是算子调优,算子的实现过程涉及多个参数,这些参数会影响性能,而传统的人工开发方式往往难以有效表达和维护这些参数,调优过程也复杂且耗时。

关于深度学习编译器,这些知识你需要了解一下

深度学习编译器应运而生,旨在解决上述问题。它充当框架与硬件之间的公共组件与桥梁,最终目标是实现一次开发即可自动为任何设备生成最优代码。例如,为CPU开发的算子几乎可以直接用于GPU和D芯片,从而显著降低开发成本。

以下简要介绍深度学习编译器的组成部分与功能,如图3所示。首先,编译器的前端从不同框架获取计算图,并使用高层IR数据结构表示。此阶段会进行一系列图优化,如常量折叠、算子融合和等价替换等。例如,原有计算图可通过更改计算方式进行等价替换,结果不变而性能可能更优。接下来,对于计算图中的每个算子,使用领域特定语言(DSL)描述其计算过程并进行优化,如对算子进行tiling、多核和双缓冲等优化。由于算子通常用多重循环实现,例如矩阵乘法涉及三重循环,深度学习编译器能够轻松对循环进行各种变换并调优参数,从而实现不同形状和硬件的最佳算子实现。最后,基于低层IR为不同硬件生成具体代码。

关于深度学习编译器,这些知识你需要了解一下

最后,介绍一下现有的编译器项目。目前,生态系统最为完善且开源、框架无依赖的项目是TVM,已被多家公司采用。TVM的流程如图3a所示,可以导入各个框架的模型,例如TensorFlow pb、ONNX和TorchScript等,并统一用TVM称为Relay的高层IR表示。在IR中,每个算子采用Tensor expression的DSL进行计算描述和调度。该DSL使用EinstEin的标记法进行算子计算描述,算子计算通常体现为多重for循环。基于Halide思想,使用调度对这些多重for循环进行各种变换,例如循环合并、拆分和顺序变换等。最终,生成低层IR并输出具体设备代码以进行推理。

进一步介绍TVM如何生成最佳算子代码。算子需要进行计算描述,并对相应的多重for循环进行调度变换。TVM的算子生成与调优经历了三代发展。第一代TVM/AutoTVM,用户需编写算子的计算与调度,AutoTVM允许在调度中定义可变参数,并使用遗传算法进行调优,例如在某个循环切分为两段时,切分位置的优化。第二代AutoScheduler(AnsoR),用户仅需开发算子计算,AnsoR内部会根据规则自动进行调度变换。由于调度开发需熟悉TVM表达机制与底层硬件原理,通常难度较高,因此AnsoR显著降低了开发人员的工作量,但调优时间较长,通常需要1小时调优一个算子。以卷积网络为例,AnsoR在某些场景下能超越TensorFlow算子的性能,但与TensorRT仍有差距。第三代Meta Schedule(AutoTensorIR)尚处于起步阶段,预计将优化调优速度和性能,未来值得期待。

TVM的应用包括华为D芯片TBE算子开发工具,在TVM基础上增加了对D芯片代码生成的支持。TVM采用Halide计算与调度路线,另有采用多面体算法的编译器,如Tensor Comprehensions、TiRaMisu以及华为自研的AKG等。这些方法同样只需用户开发算子计算,无需开发调度,因此对用户较为友好,其中AKG已应用于MindSpore的图算融合中。其他的深度学习编译器还包括TensorFlow的XLA和TensorRT等,大家可能已经接触过。

总之,深度学习编译器具有诸多优势,如易于支持新硬件,避免重复开发,通过一系列自动优化替代人工优化,从而实现极高性价比。然而当前深度学习编译器亦存在一些不足,仍处于快速发展阶段。例如调优时间长,对于复杂算子无法有效生成,且深度学习编译器生成的算子在单个模型中超越库调用的比例较低,这些问题仍需不断投入和优化。