使用 XNNPACK 加速量化推理
2021 年 9 月 9 日

发布者 Marat Dukhan 和 Frank Barchard,软件工程师

量化是加速 CPU 上神经网络推理最常用的方法之一。一年前,TensorFlow Lite 通过集成 XNNPACK 后端,提高了浮点模型的性能。今天,我们将 XNNPACK 后端扩展到量化模型,在计算机视觉模型的平均性能上,在 ARM64 移动电话上速度提高了 30%,在 x86-64 笔记本电脑和台式机系统上速度提高了 5 倍,在使用 WebAssembly SIMD 的浏览器内推理速度提高了 20 倍,与默认的 TensorFlow Lite 量化内核相比。

XNNPACK 中的量化推理针对 对称量化模式 进行了优化,该模式由 TensorFlow 模型优化工具包 使用。XNNPACK 支持 传统的每张量量化模式 和更新的精度优化 模式,该模式使用权重的每个通道量化和激活的每张量量化。此外,XNNPACK 支持非对称量化模式,但效率降低。

性能改进

我们评估了在多个边缘设备和神经网络架构上加速的 XNNPACK 量化推理。下面,我们在涵盖常见计算机视觉任务的四个公开模型和两个内部量化模型上展示了基准测试。

  1. EfficientNet-Lite0 图像分类 [下载]
  2. EfficientDet-Lite0 对象检测 [下载]
  3. DeepLab v3 分割,使用 MobileNet v2 特征提取器 [下载]
  4. CartoonGAN 图像风格转换 [下载]
  5. 量化版本的 Face Mesh 地标
  6. 量化版本的 视频分割
Speedup from XNNPACK on single-threaded inference of quantized computer vision models on Android/ARM64 mobile phones.
XNNPACK 在 Android/ARM64 移动电话上对量化计算机视觉模型的单线程推理带来的加速。

在六款 Android ARM64 移动设备上,XNNPACK 的平均速度比默认的 TensorFlow Lite 量化内核快 30%。

Speedup from XNNPACK on single-threaded inference of quantized computer vision models on x86-64 laptop and desktop systems.
XNNPACK 在 x86-64 笔记本电脑和台式机系统上对量化计算机视觉模型的单线程推理带来的加速。

XNNPACK 在使用 x86 处理器的笔记本电脑和台式机系统上提供了更大的改进。在我们基准测试的 5 个 x86 处理器上,XNNPACK 平均将推理速度提高了 5 倍。值得注意的是,不支持 AVX 指令的低端和老式处理器在将量化推理切换到 XNNPACK 后,速度提高了 20 倍以上:之前的 TensorFlow Lite 推理后端只为 AVX、AVX2 和 AVX512 指令集优化了实现,而 XNNPACK 为所有 x86-64 处理器提供了优化的实现。

Speedup from XNNPACK on single-threaded WebAssembly SIMD inference of quantized computer vision models on mobile phones, laptops, and desktops when running through V8.
XNNPACK 在通过 V8 运行时,在移动电话、笔记本电脑和台式机上对量化计算机视觉模型的单线程 WebAssembly SIMD 推理带来的加速。

除了传统的移动设备和笔记本电脑/台式机平台之外,XNNPACK 还通过 TensorFlow Lite Web API 为 Web 平台带来了加速的量化推理。上面的图表显示了在 3 个 x86-64 和 2 个 ARM64 系统上通过 V8 JavaScript 引擎运行 WebAssembly SIMD 基准测试时,与默认的 TensorFlow Lite 实现相比,几何平均速度提高了 20 倍。

两年的优化

XNNPACK 最初是 QNNPACK 库 的一个分支,但由于 XNNPACK 的第一个版本专注于浮点推理,而 QNNPACK 专注于量化推理,因此无法比较两者。现在 XNNPACK 引入了对量化推理的支持,我们可以直接评估并归因于这两年来的性能优化。

Graph showing xxnpack speedup over qnnpack

为了比较这两个量化推理后端,我们将随机化的 MobileNet v1MobileNet v2 模型从 XNNPACK API 移植到 QNNPACK API,并在两款 ARM64 Android 手机和两款 x86-64 系统上对其单线程性能进行了基准测试。上面的图表显示了结果,以及 XNNPACK 在两年中取得的显著进步。XNNPACK 在较旧的 Pixel 3a 手机上快了 50%,在更新的 Pixel 4a 手机上快了 4-5 倍,在 x86-64 笔记本电脑上快了 2.5 倍,在 x86-64 工作站上快了 3 倍以上。这些改进是 XNNPACK 在自 QNNPACK 分支后的两年中获得的多个优化的结果。

  • XNNPACK 保留了 QNNPACK 中的优化,例如 间接卷积算法 和特定于微体系结构的微内核选择,并进一步通过 间接反卷积算法 和更灵活的功能对其进行增强,例如在量化加法和量化乘法运算符中内置的类似 NumPy 的广播功能。
  • 卷积、反卷积和全连接运算符将 8 位激活和权重的乘积累积到一个 32 位数字中,最后需要将此数字转换回或重新量化为一个 8 位数字。重新量化有多种实现方法,但 QNNPACK 采用的是 GEMMLOWP 库 中的模式,该库率先为神经网络推理实现了量化计算。但是,后来发现 GEMMLOWP 重新量化模式在精度和性能方面都不理想,XNNPACK 用更高效和更准确的替代方案替换了它。
  • 虽然 QNNPACK 针对非对称量化模式,在该模式下激活和权重都 表示为具有零点和尺度量化参数的无符号整数,但 XNNPACK 的优化重点是对称量化,在该模式下激活和权重都是有符号整数,并且权重有额外的限制:权重的零点始终为零,量化权重元素限制在 [-127, 127] 范围内(即使 -128 可以表示为有符号 8 位整数,也将其排除在外)。对称量化提供了 XNNPACK 中利用的两个计算优势。首先,当滤波器权重是静态的时,将输入零点乘以滤波器权重的结果可以完全融合到卷积、反卷积和全连接运算符中的偏差项中。因此,零点参数完全不存在于推理计算中。其次,有符号 8 位输入元素与限制在 [-127, 127] 范围内的权重元素的乘积适合 15 位。这使得卷积、反卷积和全连接运算符的微内核能够在 16 位变量上执行一半的累积,而不是始终将乘积扩展到 32 位。
  • QNNPACK 微内核针对 ARM 上的 NEON SIMD 指令集和 x86 上的 SSE2 SIMD 指令集进行了优化,但 XNNPACK 支持更广泛的特定于指令集的优化。XNNPACK 中的大多数量化微内核都针对 x86/x86-64 上的 SSE2、SSE4.1、AVX、XOP、AVX2 和 AVX512 指令集,针对 ARM/ARM64 上的 NEON、NEON V8 和 NEON 点积指令集,以及针对 WebAssembly SIMD 指令集进行了优化。此外,XNNPACK 为 WebAssembly 1.0 和预 NEON ARM 处理器提供了标量实现。
  • QNNPACK 引入了为高端 ARM 和低端 ARM 内核提供专门的汇编微内核的概念,但 XNNPACK 将此概念更进一步。XNNPACK 不仅包含为 Cortex-A53、Cortex-A55 和具有和不具有 NEON 点积指令集的高端内核提供专门的专家调整的软件流水线汇编微内核,甚至还支持在运行时切换它们。当执行推理的线程从大内核迁移到小内核时,XNNPACK 会自动从使用针对大内核优化的微内核切换到针对小内核优化的微内核。
  • QNNPACK 主要关注多线程推理,并将计算组织为大量的小任务,每个任务计算输出张量的一个小块。XNNPACK 重构了并行化,并使任务更加灵活:它们可以是细粒度的或粗粒度的,具体取决于参与并行化的线程数量。通过动态调整任务粒度,XNNPACK 在单线程执行中实现了低开销,并在多线程推理中实现了高并行化效率。

这些优化共同使 XNNPACK 成为量化推理的最新技术,并将 TensorFlow Lite 变成了最通用的量化推理解决方案,涵盖从树莓派零到 Chromebook 到使用服务器级处理器的 workstations 的系统。

如何使用它?

量化 XNNPACK 推理在 TensorFlow Lite 的所有平台的 CMake 构建中默认启用,在 TensorFlow Lite Web 平台的 Bazel 构建中默认启用,并将作为 TensorFlow Lite Web API 的 2.7 版本发布。在其他平台的 Bazel 构建中,量化 XNNPACK 推理通过构建时选择机制启用。使用 Bazel 构建 TensorFlow Lite 时,添加 --define tflite_with_xnnpack=true --define xnn_enable_qs8=true,TensorFlow Lite 解释器将默认情况下使用 XNNPACK 后端,为使用对称量化的受支持的运算符提供支持。对使用非对称量化的运算符的支持有限,可以通过 Bazel 选项 --define xnn_enable_qu8=true 获得。

哪些操作得到了加速?

XNNPACK 后端目前支持量化 TensorFlow Lite 运算符的一个子集(有关详细信息和限制,请参阅 文档)。XNNPACK 支持通过训练后整数量化和量化感知训练生成的模型,但不支持训练后动态范围量化。

未来工作

这是 XNNPACK 集成到 TensorFlow Lite 的第三个版本,继 浮点实现的初始发布随后带来稀疏推理支持的版本 之后。在接下来的版本中,我们计划添加以下改进。

  • 在最近的 ARM 处理器上进行半精度推理。
  • 稀疏量化推理。
  • 更快稠密推理。

我们鼓励您在我们的 GitHubStackOverflow 页面上留下您的想法和评论,您可以在 discuss.tensorflow.org 上提问。

下一篇文章
Faster Quantized Inference with XNNPACK

作者:Marat Dukhan 和 Frank Barchard,软件工程师 量化是加速 CPU 上神经网络推理的最流行方法之一。一年前,TensorFlow Lite 通过集成 XNNPACK 后端 提高了浮点模型的性能。今天,我们将 XNNPACK 后端扩展到量化模型,在计算机视觉模型上的平均加速率为 30%,在 AR…