📅 创建时间:2026-06-03 🏷️ 标签:#NPU #TPU #SystolicArray #昇腾 #DaVinci #寒武纪 #QualcommSNPE #AppleANE #EdgeAI #Delegate 📚 前置知识:[[13-codegen-architecture]](代码生成架构) 📚 相关知识:[[15-backend-cuda]](CUDA 后端) [[26-quantization]](量化)
NPU 后端:脉动阵列与端侧 AI 生态 / NPU Backends, Systolic Arrays, and Edge AI Ecosystems
┌──────────────────────────────────────────────────────────────────────────────┐ │ 情 境 描 述 │ ├──────────────────────────────────────────────────────────────────────────────┤ │ 你需要在华为昇腾 910B NPU 上部署模型。文档说支持"主流 AI 框架",但实际: │ │ - PyTorch 模型需要用 MindSpore 重新训练 │ │ - TensorFlow 模型需要 ONNX 转换再 lower 到 HiAI backend │ │ - INT8 量化需要用华为自研的 QAT 工具,否则精度掉 10% │ │ │ │ 每一步都有人为的生态壁垒。NPU 编译器生态为什么这么碎片化? │ └──────────────────────────────────────────────────────────────────────────────┘
第1节:NPU 的特殊性——专用硬件的设计哲学
1.1 为什么需要 NPU
GPU 虽然通用,但并非最优:
┌─────────────────────────────────────────────────────────────────────────────┐
│ GPU vs NPU:通用 vs 专用的权衡 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ GPU (通用): │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ✓ 编程简单(CUDA/Triton) │ │
│ │ ✓ 生态完善(cuDNN, cuBLAS, PyTorch 原生支持) │ │
│ │ ✓ 算子灵活(任何自定义 op 都可实现) │ │
│ │ ✗ 能效低(通用计算浪费在图形渲染上) │ │
│ │ ✗ 面积效率低(大量晶体管用于渲染管线) │ │
│ │ ✗ 价格贵(H100 A100 成本高) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ NPU (专用): │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ✓ 能效极高(专用硬件做专用计算) │ │
│ │ ✓ 面积效率高(脉动阵列等密集矩阵计算单元) │ │
│ │ ✓ 推理延迟低(硬件优化过的算子) │ │
│ │ ✗ 编程复杂(厂商 SDK, DSL, 限制多) │ │
│ │ ✗ 生态碎片(每家 SDK 不同) │ │
│ │ ✗ 算子限制(只支持预定义的算子) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘1.2 NPU 的分类
| 类型 | 架构 | 代表 | 特点 |
|---|---|---|---|
| 云端训练 | 脉动阵列 | TPU v2/v3, 昇腾 910 | 高 TFLOPS,支持 training |
| 云端推理 | 脉动阵列/向量 | TPU v1, 昆仑芯 | 强调 throughput |
| 边缘推理 | VLIW/DSP/NN accel | 寒武纪 MLU, Hexagon | 低功耗,INT8 为主 |
| 移动端 | NN accelerator | Apple ANE, DSP | 超低功耗,always-on |
1.3 NPU 的共同特征
class NPUCommonCharacteristics:
"""
NPU 的共同特征
"""
# 1. 固定形状的矩阵计算单元
# 不支持动态 shape,必须是编译时确定的固定大小
matrix_unit_shape = {
'TPU v2': '128×128', # 每单元
'TPU v3': '128×128',
'昇腾 910': '16×16×16', # Cube 计算单元
'寒武纪 MLU220': '16×16',
'Hexagon HVX': '1024 (vector)'
}
# 2. 本地 SRAM 代替 HBM
# NPU 通常有较小的本地内存,带宽高但容量小
local_sram = {
'TPU v2': '28 MB', # Unified Buffer
'TPU v3': '32 MB',
'昇腾 910': '16 MB',
'寒武纪 MLU220': '8 MB'
}
# 3. 量化原生支持
# NPU 设计时就考虑了 INT8/INT4/FP16
# 硬件直接支持量化计算
native_quant = ['INT8', 'INT4', 'FP16', 'BF16']
# 4. 固定的数据流
# 数据流 (Dataflow) 是编译时确定的
# 输入 → 累加器 → 输出,不能随意排列
dataflow = ['固定数据流', '行稳态数据流', '权重平稳态数据流']第2节:脉动阵列——TPU 的核心架构
2.1 脉动阵列原理
脉动阵列 (Systolic Array) 是 NPU 最常见的架构:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 脉动阵列架构 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 2D 脉动阵列示意图 (以 4×4 为例): │
│ │
│ W(0,0) W(0,1) W(0,2) W(0,3) │
│ ↓ ↓ ↓ ↓ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ← 权重输入 │
│ │ PE │ │ PE │ │ PE │ │ PE │ │
│ I(0) → │(0,0)│ │(0,1)│ │(0,2)│ │(0,3)│→ Y(0,0) Y(0,1) Y(0,2) Y(0,3) │
│ └──┬────┘ └──┬────┘ └──┬────┘ └──┬────┘ │
│ ↓ ↓ ↓ ↓ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ PE │ │ PE │ │ PE │ │ PE │ │
│ I(1) → │(1,0)│ │(1,1)│ │(1,2)│ │(1,3)│→ ... │
│ └──┬────┘ └──┬────┘ └──┬────┘ └──┬────┘ │
│ ↓ ↓ ↓ ↓ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ PE │ │ PE │ │ PE │ │ PE │ │
│ I(2) → │(2,0)│ │(2,1)│ │(2,2)│ │(2,3)│→ ... │
│ └──┬────┘ └──┬────┘ └──┬────┘ └──┬────┘ │
│ ↓ ↓ ↓ ↓ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ PE │ │ PE │ │ PE │ │ PE │ │
│ I(3) → │(3,0)│ │(3,1)│ │(3,2)│ │(3,3)│→ Y(3,0) Y(3,1) Y(3,2) Y(3,3) │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │
│ 每个 PE: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 输入数据 → [Register] → [Multiply] → [Accumulator] → 输出数据 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 脉动的工作方式: │
│ - 权重从左向右流动 (W 寄存器) │
│ - 输入从上向下流动 (I 寄存器) │
│ - 每个 PE 做一次乘法和一次累加 │
│ - 结果从右下角流出 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘2.2 脉动阵列的计算过程
def systolic_array_computation():
"""
脉动阵列计算 GEMM: Y = I × W
假设 4×4 阵列,W 是 4×4,I 是 4×N
"""
# 初始化
# PE[i][j] 的权重寄存器初始化为 W[i][j]
# PE[i][j] 的累加器初始化为 0
# 计算过程
# 每个时间步:
# 1. PE[i][j] 的 I_register 接收来自 PE[i-1][j] 的数据(或输入 I[i][t])
# 2. PE[i][j] 的 W_register 接收来自 PE[i][j-1] 的数据(或权重 W[i][j])
# 3. PE[i][j] 计算: accumulator += I_register * W_register
# 时间步 t=0:
# PE[0][*] 接收 I[0][0], I[1][0], I[2][0], I[3][0]
# PE[*][0] 接收 W[0][0], W[1][0], W[2][0], W[3][0]
# PE[0][0]: acc = I[0][0] * W[0][0]
# 时间步 t=1:
# PE[0][*] 接收 I[0][1], I[1][1], ...
# PE[1][0] 接收 W[1][0](从 PE[0][0] 流来)
# PE[0][0]: acc += I[0][1] * W[0][0]
# PE[1][0]: acc = I[1][0] * W[1][0]
# 时间步 t=4 (第一个输出):
# PE[3][3] 输出 Y[0][0] = sum_k(I[0][k] * W[k][0])
print("脉动阵列的计算延迟 = 2N-1 个周期")
print("每个周期完成 N 个 MAC 操作")
print("理论吞吐量: N×N 个 MAC/周期")
def tpu_vs_gpu_efficiency():
"""
TPU vs GPU 效率对比
"""
# TPU (脉动阵列):
# - 每周期 MAC 数 = 阵列大小 = 128×128 = 16384
# - 无需寄存器文件访问,每个 MAC 直接从相邻 PE 获取数据
# - 能效极高
# GPU (CUDA Core):
# - 每 SM 每周期: 2×FP32 FMA = 2 MAC (Ampere)
# - 108 SM (A100): 108 × 2 = 216 MAC/周期
# - 需要从寄存器文件读取操作数
tpu_mac_per_cycle = 128 * 128 # = 16384
gpu_mac_per_cycle = 108 * 2 # A100 = 216
print(f"TPU MAC/cycle: {tpu_mac_per_cycle}")
print(f"GPU MAC/cycle: {gpu_mac_per_cycle}")
print(f"TPU 优势: {tpu_mac_per_cycle / gpu_mac_per_cycle:.0f}x")第3节:主流 NPU 生态详解
3.1 Google TPU
class TPU:
"""
Google TPU 架构
"""
# TPU v1 (2016): 推理专用
v1 = {
'matrix_unit': '256×256 脉动阵列',
'precision': 'INT8 (推断), FP16 (训练)',
'memory': '8 GB HBM',
'bandwidth': '34 GB/s',
'tflops': 92, # INT8
'backend': 'XLA'
}
# TPU v2 (2017): 训练+推理
v2 = {
'matrix_unit': '128×128 脉动阵列 × 2',
'precision': 'FP16, INT8',
'memory': '64 GB HBM (16 GB per chip)',
'bandwidth': '700 GB/s (per chip)',
'tflops': 45, # FP16
'interconnect': 'Custom interconnect, 2D torus'
}
# TPU v3 (2018)
v3 = {
'matrix_unit': '128×128 脉动阵列 × 2',
'precision': 'FP16, INT8, BFLOAT16',
'memory': '128 GB HBM',
'bandwidth': '900 GB/s',
'tflops': 123, # BF16
'pods': '1024 chips, 100+ PFLOPS'
}
# TPU v4 (2020)
v4 = {
'matrix_unit': '128×128 脉动阵列 × 2',
'precision': 'FP16, INT8, BFLOAT16',
'memory': '32 GB HBM per chip',
'interconnect': 'Optical interconnect, 3D torus',
'tflops': 275, # BF16 per chip
'pods': '4096 chips, 1 exaflop'
}
# XLA 编译流程
def xla_compilation():
"""
TensorFlow → XLA → TPU Binary
"""
# 1. TensorFlow 图 → XLA HLO
# 2. XLA 优化 pass (fusion, layout, scheduling)
# 3. TPU 特定 lower (HLO → TPU IR)
# 4. TPU 代码生成 (TPU binary)
pass3.2 华为昇腾 (DaVinci)
class Ascend:
"""
华为昇腾 NPU
"""
# 昇腾 910 (云端训练/推理)
ascend_910 = {
'architecture': 'Da Vinci',
'compute': '512 TB-FLOPS (FP16) / 256 TFLOPS (FP32)',
'cubes': '32 个 AI Core (类似 Tensor Core)',
'memory': '32 GB HBM2',
'bandwidth': '1.2 TB/s',
'process': '7nm + CoWoS',
'sdk': 'CANN (Compute Architecture for Neural Networks)',
'framework': 'MindSpore, PyTorch (via CANN), TensorFlow (via CANN)'
}
# 昇腾 310 (边缘推理)
ascend_310 = {
'compute': '22 TOPS (INT8) / 11 TFLOPS (FP16)',
'power': '8W TDP',
'process': '12nm',
'sdk': 'CANN Lite'
}
def cann_workflow():
"""
CANN 工作流程
"""
# 昇腾 CANN 编译流程:
# 1. 模型转换: PyTorch/TensorFlow → ONNX → AhmModel (昇腾模型格式)
# 2. 图优化: 算子融合, shape 推断
# 3. 算子编译: 算子 → TBE (Tensor Boost Engine) 生成的代码
# 4. 离线模型: AhmModel → .om 模型文件
workflow = """
PyTorch Model
↓ (torch.onnx.export)
ONNX Model
↓ (atc converter)
AhmModel
↓ (optimizer)
Optimized AhmModel
↓ (builder)
.om (Offline Model)
"""
print(workflow)3.3 寒武纪 MLU
class Cambricon:
"""
寒武纪 MLU (Machine Learning Unit)
"""
# MLU220 (边缘推理)
mlu220 = {
'process': '16nm',
'compute': '16 TOPS (INT8) @ 8W',
'memory': '4 GB LPDDR4',
'bandwidth': '25.6 GB/s',
'sdk': 'BangC (基于 GCC 扩展)'
}
# MLU290 (云端)
mlu290 = {
'process': '7nm',
'compute': '256 TOPS (INT8) / 256 TFLOPS (FP16)',
'memory': '32 GB HBM2',
'bandwidth': '1 TB/s',
'sdk': 'BangC'
}
# BangC 编程模型
def bangc_kernel():
"""
BangC 是类 C 的 DSL
"""
code = """
// BangC kernel 示例
__mlu_entry__ void gemm_kernel(...) {
// 分配本地内存到 MLU 片上 SRAM
__mlu_shared__ float As[BLOCK_M][BLOCK_K];
__mlu_shared__ float Bs[BLOCK_K][BLOCK_N];
// 加载数据
__memcpy(As, A, sizeof(float) * M * K, GDRAM2L1);
// 计算
for (int k = 0; k < K; k += BLOCK_K) {
// 矩阵乘累加
// __bang_fma: fused multiply-add
__bang_fma(As, As, Bs, BLOCK_M * BLOCK_K);
}
// 写回
__memcpy(C, Cs, sizeof(float) * M * N, L1GDRAM);
}
"""
print(code)3.4 高通 Hexagon (SNPE)
class QualcommHexagon:
"""
高通 Hexagon DSP + NPU
"""
# Hexagon V65/V66 (Snapdragon 865/888)
hexagon_v66 = {
'type': 'Hexagon DSP + Adreno GPU + Kryo CPU',
'nn_engine': 'SNPE (Snapdragon Neural Processing Engine)',
'compute': '15 TOPS (combined)',
'precision': 'INT8, INT16, FP16',
'sdk': 'QNN (Qualcomm Neural Network)',
'framework': 'TFLite, ONNX, PyTorch (via DLC)'
}
# SNPE 工作流程
def snpe_workflow():
"""
Qualcomm SNPE 工作流程
"""
workflow = """
PyTorch/TF Model
↓
Framework → ONNX → DLC (Deep Learning Container)
↓
SNPE Runtime
↓
目标: Hexagon DSP / Adreno GPU / Kryo CPU
"""
print(workflow)3.5 Apple Neural Engine
class AppleANE:
"""
Apple Neural Engine (ANE)
"""
# A14/A15/A16/M1/M2
ane_specs = {
'A14 Bionic': '11 TOPS',
'A15 Bionic': '15.8 TOPS',
'A16 Bionic': '17 TOPS',
'M1': '11 TOPS',
'M2': '15.8 TOPS',
'precision': 'FP16, INT8 (ANE 原生)',
'sdk': 'CoreML, Metal Performance Shaders'
}
# CoreML 流程
def coreml_workflow():
"""
Apple CoreML 流程
"""
# 1. 模型转换: PyTorch/TF → .mlmodel
# 2. 编译: .mlmodel → .mlmodelc (加速)
# 3. 执行: ANE 自动调度算子
workflow = """
PyTorch Model
↓ (coremltools)
.mlmodel (CoreML format)
↓ (compiler)
.mlmodelc (compiled)
↓
ANE / GPU / CPU (自动选择)
"""
print(workflow)第4节:主流 NPU 架构对比
| 特性 | Google TPU | 华为昇腾 910 | 寒武纪 MLU290 | 高通 Hexagon | Apple ANE |
|---|---|---|---|---|---|
| 架构 | 脉动阵列 | Cube+Vector | 自研 MLU Core | VLIW+DSP | 自研 |
| 精度 | BF16/FP16/INT8 | FP16/INT8 | FP16/INT8 | FP16/INT8 | FP16 |
| 内存 | HBM 32GB | HBM2 32GB | HBM2 32GB | LPDDR5 | 统一内存 |
| 带宽 | 900 GB/s | 1.2 TB/s | 1 TB/s | ~50 GB/s | 共享 |
| SDK | XLA/JAX | CANN | BangC | QNN/SNPE | CoreML |
| 框架 | TF/JAX | MindSpore | 自有框架 | TFLite | 自有生态 |
| 适用 | 云端训练 | 云端训练 | 云端推理 | 边缘 | 移动端 |
第5节:Delegate 模式——TFLite 的扩展机制
5.1 Delegate 原理
class TFLiteDelegate:
"""
TFLite Delegate 模式
允许将部分图 lower 到加速器执行
"""
def __init__(self, delegate_library):
self.delegate = tflite.load_delegate(delegate_library)
def interpret(self, model_path):
interpreter = tflite.Interpreter(
model_path,
experimental_delegates=[self.delegate]
)
return interpreter
# 使用 GPU Delegate
interpreter = tflite.Interpreter(
model_path='model.tflite',
experimental_delegates=[tflite.load_delegate('libtensorflowlite_gpu_delegate.so')]
)
# 使用 NPU Delegate (Android)
interpreter = tflite.Interpreter(
model_path='model.tflite',
experimental_delegates=[tflite.load_delegate('libnnapi_delegate.so')]
)5.2 实现自定义 Delegate
// 实现自定义 Delegate
#include <tensorflow/lite/delegates/utils.h>
// 1. 定义 Delegate Options
TfLiteDelegate* CreateMyDelegate() {
TfLiteDelegate* delegate = TfLiteDelegateCreate();
delegate->flags = kTfLiteDelegateFlagsNone;
// 指定哪些节点由 Delegate 处理
delegate->Prepare = [](TfLiteContext* context, TfLiteDelegate* delegate) {
// 图遍历,设置 node->builtin_data = (void*)kTfLiteDelegate
// 表示这些节点由 Delegate 处理
};
return delegate;
}
// 2. 实现 Delegate 的 Eval
// 遍历 Delegate 处理的节点
// 调用加速器 API 执行
delegate->Eval = [](TfLiteContext* context, TfLiteDelegate* delegate) {
// 找到所有标记为 Delegate 的节点
// 按拓扑序执行
for (auto node : delegate_nodes) {
// 调用加速器执行
accelerator.Execute(node->inputs, node->outputs);
}
};第6节:NPU 编译的特殊挑战
6.1 内存层次不同于 GPU
class NPUMemoryChallenge:
"""
NPU 内存层次挑战
"""
# GPU: HBM → L2 → L1 → Register
gpu_hierarchy = """
HBM (800 GB/s, 80 GB)
↓
L2 Cache (A100: 40 MB)
↓
L1/Shared Memory (128 KB)
↓
Register (~1 MB)
"""
# NPU: 通常没有 Cache,本地 SRAM 直接和 HBM 交互
npu_hierarchy = """
HBM (400 GB/s, 32 GB)
↓
Local SRAM (16 MB) ← 没有中间层 Cache!
↓
脉动阵列 (MAC)
"""
# 挑战:
# 1. Local SRAM 很小(16 MB vs GPU L2 40 MB)
# 2. 需要精确的数据放置策略
# 3. 编译器必须知道数据何时在 SRAM 中
# 4. 无法依赖硬件自动 Cache
def memory_placement_strategy():
"""
NPU 内存放置策略
"""
strategy = """
1. 确定哪些数据必须放在 SRAM:
- 频繁访问的小张量
- 权重(如果能放下)
2. 确定哪些数据直接从 HBM 读取:
- 只读一次的大张量
- 中间结果
3. 计算数据流:
- 确定每个算子的输入输出
- 最小化 HBM ↔ SRAM 传输
4. 调度:
- 计算和数据传输重叠
- Double Buffering
"""
print(strategy)6.2 算子支持不完整
class OperatorSupportChallenge:
"""
NPU 算子支持挑战
"""
# 常见问题:
issues = [
"自定义算子: NPU 通常只支持预定义的算子",
"动态 shape: NPU 需要固定形状,动态 shape 需要特殊处理",
"精度限制: INT8 量化可能导致精度损失",
"数值范围: NPU 的 INT8 范围可能和 PyTorch 不同"
]
# 解决方案:
solutions = {
'fallback_to_cpu': '不支持的算子回退到 CPU',
'kernel_fusion': '多个小算子融合成支持的大算子',
'拆解重组': '复杂算子拆解成多个简单算子'
}6.3 量化校准的特殊性
class NPUQuantizationChallenge:
"""
NPU 量化校准的特殊挑战
"""
# 问题:
# 1. NPU 的 INT8 乘法器是定点,乘加结果需要截断
# 2. 不同 NPU 的量化参数计算方式不同
# 3. 需要在目标 NPU 上进行 calibration
def npu_quantization_flow():
"""
NPU 量化流程
"""
flow = """
1. FP32 模型训练
2. Calibration (目标 NPU 上运行):
- 使用代表性数据集
- 收集激活值范围
- 计算 scale/zero_point
3. QAT (可选,但华为等要求):
- 在训练时模拟量化
- 端到端训练量化参数
4. 模型转换:
- PyTorch → ONNX → NPU 格式
- 内嵌量化参数
5. 验证精度:
- 如果精度损失 > 阈值,回到步骤 1 或 3
"""
print(flow)第7节:跨 NPU 移植策略——MLIR 作为统一底层
7.1 为什么需要统一 IR
class UnifiedIRChallenge:
"""
NPU 生态碎片化的痛点
"""
# 每个 NPU 都有自己的:
# - 模型格式 (ONNX, MindSpore, DLC, .mlmodel)
# - SDK (CANN, BangC, QNN, SNPE)
# - 工具链
# - 优化方式
# 开发者需要为每个 NPU 学习:
# - 模型转换工具
# - SDK API
# - 调试方法
# - 性能优化
pain_points = [
"重复工作: 每个 NPU 都要重新部署模型",
"学习成本: 文档质量参差不齐",
"调试困难: 厂商工具封闭",
"升级风险: NPU 升级可能导致不兼容"
]
class MLIRAsUnifiedIR:
"""
MLIR 作为统一底层
"""
# MLIR 的优势:
# 1. 可扩展的 Dialect 系统
# 2. 每家厂商可以定义自己的 Dialect
# 3. 统一的 lowering 路径
def mlir_pipeline():
"""
MLIR 多后端编译流程
"""
pipeline = """
Frontend (PyTorch/TF) Frontend (PyTorch/TF)
↓ ↓
Torch MLIR TF MLIR
↓ ↓
─────────────────────────────────────────
↓
Linalg Dialect
(通用算子表示)
↓
┌────────────────┼────────────────┐
↓ ↓ ↓
GPU Dialect CPU Dialect NPU Dialect
↓ ↓ ↓
CUDA/ROCm LLVM-IR 厂商 Dialect
↓ ↓ ↓
SASS native code NPU Binary
↓ ↓ ↓
GPU CPU NPU
"""
print(pipeline)升华
┌─────────────────────────────────────────────────────────────────────────────────┐ │ NPU 生态的核心洞察 │ ├─────────────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. 专用硬件的代价是碎片化:没有 CUDA 这样的统一生态 │ │ │ │ 2. 脉动阵列是云端 NPU 的主流:专用硬件做矩阵乘,通用硬件处理控制流 │ │ │ │ 3. 量化是 NPU 的核心竞争力:INT8/INT4 的极致能效 │ │ │ │ 4. MLIR 可能是统一 NPU 生态 的希望:但需要时间成熟 │ │ │ │ 5. 实际部署要接受妥协:每个 NPU 都有自己的限制和癖好 │ │ │ └─────────────────────────────────────────────────────────────────────────────────┘
"AI 可查 vs 必须理解"清单
必须理解(不理解就等于不会):
- 🔴 脉动阵列的工作原理——NPU 的核心架构,不知道就无法理解为什么叫"脉动"
- 🔴 NPU 和 GPU 的本质区别——专用 vs 通用,能效 vs 灵活
- 🔴 量化校准的必要性——NPU 原生支持 INT8,但需要校准才能保证精度
- 🔴 Delegate 模式——TFLite 如何扩展到 NPU
AI 可查(知道去哪查就行):
- ✅ 具体 NPU 的 SDK API——每个厂商都不同,需要时查官方文档
- ✅ 特定 NPU 的算子支持列表——厂商会提供,但经常变化
- ✅ 量化参数的具体计算方式——INT8 的 scale/zero_point
- ✅ 厂商特定的优化技巧——通常是经验积累,需要交流
学习状态:🟡 开始学习