1. 前言
所谓劳心者治人,劳力者治于人(所以“劳力士”又叫“打工人”?)。小农经济下自己什么都干,虽然饿不死,但是生产效率也肯定非常低下;只有让专业的人做专业的事,才能最大限度发挥每个人的价值。同理,对于一个推理引擎而言,完成一次计算,可以有多种选择,从头到尾都让CPU做运算理论上也不是什么问题。但是除了结果正确之外,还有另外一项关键指标:时间!密集计算确实非CPU所长,因此他该做的是协调资源,脏活累活让GPU、DSP这些替他干。一个精诚合作的团队力量是非常强大的。那么,TensorFlow Lite是怎么利用设备上的硬件加速器做加速的呢?今天我们就来掰扯掰扯。
2. 正文
对于加速器的使用,不同的推理引擎实现的方法不一样,叫法也不统一:例如ONNX Runtime中称之为 Provider,而在TensorFlow Lite中则称之为 Delegate。当然,叫法其实不重要,下厨和烧菜本身都是指做东西吃,我们更关心的是制作的过程,万一哪天没外卖吃了要自己动手呢?
作为对比,我们可以简单回忆一下ONNX Runtime的做法(感兴趣的可以直接戳这里):ONNX Runtime默认的情况下会自动识别机器上可用的加速器,每个已识别的加速器都会声明其自身支持的算子,系统根根这些声明进行网络分片。对于多个加速器都声明支持的算子,则按照预设的加速器优先级来切分网络。
对于TensorFlow Lite,大致原理也差不离,只不过某些方面稍有不同。
首先,TensorFlow Lite默认情况下并不会去识别机器上所拥有的加速器,用户必须在代码中显式使用。下面我们将会以Hexagon Delegate为例,讲解Delegate的使用。
在TFLite中要想使用加速器,用户需要在加载网络模型、使用建造者模式获得Interpreter
的实例以后,必须调用与Hexagon 相关的API创建一个 Hexagon Delegate,之后,调用interpreter->ModifyGraphWithDelegate(delegate)
注册Hexagon Delegate。只有这样,TFLite在推理的过程中才会使用Hexagon极速器进行加速。示例代码如下所示。
#include "tensorflow/lite/delegates/hexagon/hexagon_delegate.h"
// Assuming shared libraries are under "/data/local/tmp/"
// If files are packaged with native lib in android App then it
// will typically be equivalent to the path provided by
// "getContext().getApplicationInfo().nativeLibraryDir"
const char