google/XNNPACK · 上手攻略

  • 仓库:google/XNNPACK
  • 链接:https://github.com/google/XNNPACK
  • 分类:llm-infra / 端侧推理算子库
  • 作者:spark
  • 更新:2026-07-27

是什么

XNNPACK 是 Google 官方维护的 神经网络推理算子库(C11 / C++17 / Python 3),专为 ARM、x86、WebAssembly、RISC-V、Hexagon 等 CPU 类硬件优化浮点(FP16 / FP32)以及量化(INT8 / per-channel、per-row)推理。仓库明说「not intended for direct use by deep learning practitioners」——它是给上层框架做后端加速用的,一般用户不会直接 import,而是通过 TensorFlow Lite、TensorFlow.js、PyTorch Mobile / ExecuTorch、ONNX Runtime、MediaPipe、阿里 HALO、三星 ONE 等框架透明地吃到加速。

算子覆盖 2D 卷积(含 grouped / depthwise / deconv)、2D 各种 pooling / unpooling / bilinear resize / depth-to-space、各种 elementwise(add/sub/mul/div/max/min/squared-diff)、global average pooling、channel shuffle、fully connected、activation(ReLU/ReLU6/ELU/HardSwish/Leaky ReLU/Sigmoid/Softmax/Clamp/PReLU 等)、Convert(含定点 ↔ 半精度量化 ↔ FP32 互转)、ArgMax Pooling、Transpose 等等。所有算子原生 NHWC layout,且允许在 channel 维度上做 stride 切片,从而实现零成本的 channel split / concat。

它脱胎于 Facebook 的 QNNPACK,过去几年与 QNNPACK 渐行渐远,API 已经不兼容。

解决什么问题

  • 移动端 / 嵌入式 / 浏览器 跑 CNN、ViT、TTS、语音增强、LLaMA.cpp 之外的中小模型时,没有 GPU、不能用 CUDA——XNNPACK 让 ARM NEON、AVX512、WASM SIMD 跑出几倍 CPU 提速。
  • 统一跨硬件 backend:一份 C 代码自动检测 ARM64 / ARMv7 / ARMv6 / x86 / x86-64 / WASM / RISC-V / Hexagon,运行时挑选当前 CPU 最优微内核(microkernel)。
  • 量化部署:内置 INT8 / FP16 kernel,per-channel quant schema 在 Raspberry Pi 上把 MobileNet v2 INT8 推到 17 ms / 张,FP32 也要 40+ ms。
  • 零成本 channel 切片:因为支持 channel stride,模型可以拆成多分支而不用真的 copy tensor。
  • 作为框架底座:自己写的 ML runtime / inference engine 可以直接 link XNNPACK,省去自己写 ARM NEON / AVX 优化。

快速安装

绝大多数人不需要直接装 XNNPACK,而是通过上层框架透明使用:

场景 用法
PyTorch Mobile / ExecuTorch torch / executorch,XNNPACK 是默认 CPU 后端之一
TensorFlow Lite tflite-runtime / tensorflow.tflite 模型自动走 XNNPACK delegate
TensorFlow.js WebAssembly backend 自动用 XNNPACK WASM 构建
ONNX Runtime 启用 XnnpackExecutionProvider
MediaPipe 自带 XNNPACK 后端

如果你要做框架集成或自研 inference:

# 直接用 CMake(推荐先试这个,编译产物在 build/local)
git clone https://github.com/google/XNNPACK.git
cd XNNPACK
./scripts/build-local.sh

# 指定编译器
scripts/build-local.sh -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_C_COMPILER=clang-19

# Android(需先设 ANDROID_NDK)
export ANDROID_NDK=/path/to/ndk
./scripts/build-android-armv7.sh      # 32-bit ARM
./scripts/build-android-arm64-v8.sh  # ARM64

# Bazel(适合跨平台大量 unit test)
bazel build -c opt //:XNNPACK
bazel test -c opt --local_test_jobs=HOST_CPUS //...

仓库近期主分支默认切到 CMake(CI 也是 CMake),老的 Bazel / GN 路径仍保留但不再是首选;详细配置见仓库 BUILD.md

CMake 直接 install:

cmake -S . -B build -DXNNPACK_BUILD_TESTS=ON -DXNNPACK_BUILD_BENCHMARKS=ON
cmake --build build -j
ctest --test-dir build

核心用法

1. 作为框架用户(最常见)

  • PyTorch Mobile / ExecuTorch

python import torch model = torch.jit.load("mobilenet_v2.pt") # 已经 trace 好的模型 model.eval() model_opt = torch.utils.mobile_optimizer.optimize_for_mobile(model) out = model_opt(input_tensor) # CPU 上自动用 XNNPACK

ExecuTorch 路径:导出时用 XNNPACKExecutor 后端即可。

  • TensorFlow Lite

python import tensorflow as tf interpreter = tf.lite.Interpreter(model_path="model.tflite", experimental_delegates=[tf.lite.experimental.load_delegate("libxnnpack_delegate.so")]) interpreter.allocate_tensors()

Android / iOS 上 tflite 默认就启用 XNNPACK delegate,无需额外配置。

  • ONNX Runtime

python import onnxruntime as ort so = ort.SessionOptions() so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL sess = ort.InferenceSession("model.onnx", sess_options=so, providers=["XnnpackExecutionProvider"])

  • TensorFlow.js(浏览器 WASM)

js import * as tf from "@tensorflow/tfjs-backend-wasm"; await tf.setBackend("wasm"); await tf.ready(); // WASM 构建底层就是 XNNPACK

2. 作为框架作者(C API)

XNNPACK 提供 microkernel 级别的 operator API(不展开伪代码,列出关键调用层级):

#include <xnnpack.h>

// 1) 初始化全局
xnn_initialize(/*allocator=*/NULL);

// 2) 定义 subgraph
xnn_subgraph_t subgraph;
xnn_create_subgraph(/*external_value_ids=*/2, /*flags=*/0, &subgraph);

// 3) 定义 input/output / 内部 tensor (NHWC 布局)
uint32_t input_id  = 0, output_id = 1;
size_t input_shape[]  = {1, 224, 224, 3};
size_t output_shape[] = {1, 1001};
xnn_define_tensor_value(..., &input_id,  input_shape,  ...);
xnn_define_tensor_value(..., &output_id, output_shape, ...);

// 4) 加算子(Conv / FullyConnected / Softmax / Clamp 等)
xnn_define_convolution_2d(...);
xnn_define_fully_connected(...);
xnn_define_clamp(...);   // activation

// 5) runtime 跑
xnn_runtime_t runtime;
xnn_create_runtime(subgraph, &runtime);
xnn_setup_runtime(runtime);

float* input  = ...;   // NHWC 排布
float* output = ...;
xnn_invoke_runtime(runtime);

仓库的 examples/bench/test/ 子目录有完整最小工程可参考。注意:channel-stride 让算子能直接消费「整个 tensor 的 channel 切片」,对 ResNet 那种 block 拼装非常友好。

3. 跑 benchmark 自测

bazel build -c opt //bench:end2end-bench
./bazel-bin/bench/end2end-bench --benchmark_min_time=5 \
    --benchmark_filter='*MobileNet*'

README 上的「MobileNet v1/v2/v3 Large/Small 在 Pixel / Raspberry Pi 各种延迟表」就是用 end2end-bench --benchmark_min_time=5 测出来的。

典型适用场景

  • 端侧视觉/语音模型部署:手机端 TFLite / ExecuTorch 应用,吃 XNNPACK 后端即可。
  • 浏览器内 ML:TensorFlow.js WASM / Transformers.js / MediaPipe 在 Web 上做实时分割、超分、降噪、CV 演示。
  • 树莓派 / 嵌入式 Linux 板:唯一可用的 CPU 加速之一。仓库 README 直接给了 RPi Zero W 到 RPi 4 的延迟表。
  • Cross-compile 工具链:CI 拉一份 XNNPACK,用 CMake cross-compile 出 Android ARM64 / iOS arm64 / RISC-V 静态库,喂给自家 SDK。
  • 自研 inference engine:不想手写 NEON / AVX 的小团队直接 link。
  • 训练后量化加速:PTQ 后用 INT8 kernel,per-channel quant schema 是 XNNPACK 的甜区。

坑与注意

  1. 不是通用 DL 框架:XNNPACK 只做 inference,且只覆盖 CNN/FC/常见 elementwise 类算子,没有 RNN/LSTM/Attention 之类的 primitive——LLM 想跑 CPU 推理应该用 llama.cpp / MNN / NCNN,而不是 XNNPACK。
  2. NHWC only:所有算子都按 NHWC 排布,NCHW 的 ONNX 模型进来要么转,要么用框架的 layout 转换 pass(PyTorch / TF / ORT 默认会处理)。
  3. 框架集成优于手写:自己用 C API 拼 subgraph 调试成本不低,多数情况下优化 PyTorch / TF 的 optimize_for_mobile / tflite_convert 路径比直接接 XNNPACK 更快出活。
  4. 算子覆盖≠支持组合:某些算子对 stride、对 padding、对 dilation 的支持有限,模型改造前要查 include/xnnpack.h 文档和 test/ 目录的合法组合。
  5. WASM Relaxed SIMD 是实验性:在浏览器里跑 WASM SIMD 路径要小心非主流浏览器支持度,生产建议先跑通 MVP。
  6. Hexagon / RISC-V 是后期加入:DSP/RISC-V 平台某些算子可能性能/精度不达预期,移植时先跑 benchmark。
  7. 缓存与 ISA 检测:XNNPACK 运行时检测 CPU 能力挑最优 microkernel,编译时若开 -march=native 等会绕开 dispatch logic,反而在别的机器上失效。
  8. 没有 GPU backend:XNNPACK 是纯 CPU;想做 GPU/ANE/Adreno 加速要去 TFLite GPU delegate / Core ML / Vulkan。
  9. QNNPACK 替代关系:如果还在维护基于 QNNPACK 的代码,迁过来需要重写 API,二者不兼容。

与同类对比

定位 与 XNNPACK 的差异
QNNPACK Facebook CPU 推理库 XNNPACK 的「前身」,现在 API 已分化;XNNPACK 覆盖算子更广、平台更多、性能更好。
NNAPI / Android NN HAL Android 系统级加速 NNAPI 在支持 XNNPACK 之外还会调度 GPU/DSP,XNNPACK 是 CPU 这一支的事实实现。
oneDNN (DNNL) Intel CPU 深度优化 偏向 x86 服务端,性能在 AVX512/AMX 上压 XNNPACK,但 ARM/WASM/移动端支持远不如 XNNPACK。
MNN / NCNN / TNN 国产端侧推理引擎 通常把 XNNPACK/oneDNN/Arm Compute Library 组合使用,自己加图优化 + GPU backend,端侧开箱即用。
Core ML / TFLite GPU delegate 厂商专有加速 绑 iOS / GPU,XNNPACK 是「跨平台 CPU」这层的标配。
llama.cpp LLM CPU 推理 不重叠:XNNPACK 是算子库,llama.cpp 是 LLM 专用 runtime,二者可以 link(社区已有相关 PR)。

一句话推荐

做端侧 / 浏览器 / 嵌入式推理,直接用 TFLite / PyTorch Mobile / ONNX Runtime / TF.js,让它们去集成 XNNPACK 即可——只有在做框架底座或自研 engine 时才需要直接 link。


参考来源:仓库 README 与 BUILD.md(github.com/google/XNNPACK,2026-07-27 抓取)、TFLite XNNPACK 集成博客(tensorflow.org 2020-07)、ONNX Runtime Xnnpack Execution Provider 文档、TensorFlow.js WASM 后端发布博客。性能表来源 end2end_bench 官方脚本,Pixel / Raspberry Pi 数据时效分别为 2020-03 / 2022-02;近期硬件(如 Pixel 8+、RPi 5)的延迟数据以自家 bench 为准。