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