资讯动态

NPU与TPU架构解析:从CPU到端侧AI推理的算力跃迁

发布时间:2026/10/14 0:55:21 来源:尧图企业网站定制
1. 从CPU到NPU为什么通用算力突然不够用了如果你最近两年在折腾端侧AI部署大概率会遇到一个很尴尬的局面模型在服务器上跑得好好的一搬到手机、开发板或者边缘盒子上帧率直接掉到个位数功耗还高得吓人。我最早接触这类问题是在一个图像分类的小项目上当时用一块主流的ARM开发板跑一个轻量级卷积网络CPU单核推理一张224×224的图要接近200毫秒四核并行也就勉强压到60毫秒左右而且板子烫得能煎鸡蛋。后来换了一块带NPU的芯片同样的模型、同样的输入单帧推理直接降到8毫秒以内功耗还降了一大截。这个差距不是靠优化代码能追回来的本质上是计算架构的代际差异。要理解NPU和TPU为什么快得先看清楚CPU在AI推理这件事上到底“亏”在哪里。CPU的设计哲学是通用性它要处理分支跳转、中断响应、操作系统调度、各种类型的数据读写所以它的核心面积里有大量资源花在了缓存层级、乱序执行、分支预测这些机制上。真正用来做乘加运算的ALU单元占比其实很小。而神经网络推理的计算模式极其规整——绝大部分是矩阵乘法和卷积数据流是可预测的没有复杂分支。用CPU去跑这种负载就像开着越野车在高速公路上送快递能到但效率极低。NPUNeural Processing Unit和TPUTensor Processing Unit的思路就完全不同了。它们把芯片面积几乎全部砸在乘加阵列MAC Array上配合专门的数据搬运通路和片上缓存让数据像流水线一样灌进去、算完、流出来。一个典型的NPU可能包含几千甚至上万个MAC单元在同一个时钟周期内完成海量的乘加运算。这种设计叫领域专用架构DSA牺牲了通用性换来了在特定任务上几十倍甚至上百倍的能效比提升。这里有个数字可以帮你建立直观感受。假设一个NPU有4096个MAC单元运行频率1GHz理论上每秒能完成约8万亿次运算4096×2×1G。而一个主流CPU的SIMD单元可能只有16到32个通道频率3GHz左右峰值算力差了两个数量级。当然实际推理受限于内存带宽、数据复用率等因素跑不满理论峰值但即便打个三折差距依然悬殊。注意NPU的算力标称值TOPS通常指的是INT8精度下的峰值和FP32的算力不是一回事。看规格书的时候一定要确认精度前提否则很容易被数字误导。对于做端侧部署的人来说理解NPU的价值不只是“它快”而是要搞清楚什么样的模型能吃到NPU的红利什么样的模型在NPU上反而会翻车。这涉及到算子支持度、量化兼容性、内存布局要求等一系列工程细节后面会逐一展开。2. NPU和TPU的内部构造乘加阵列到底怎么工作的2.1 从单个MAC到脉动阵列要搞懂NPU为什么快得从最基本的计算单元说起。一个MAC单元做的事情很简单接收两个数相乘然后累加到寄存器里。公式就是acc a * b。CPU做这件事需要从寄存器取数、执行乘法、执行加法、写回结果一条指令流水线下来至少几个周期。而NPU里的MAC单元是硬连线的一个周期就能完成一次乘加。单个MAC当然不够看关键在于并行。NPU把成百上千个MAC排成二维阵列比如256×256的网格。每一行、每一列同时工作一个时钟周期就能完成65536次乘加。这就是所谓的空间并行——不是让一个单元跑得更快而是让几万个单元同时干活。但光有阵列还不够数据怎么喂进去是个大问题。如果每个MAC都要从外部内存单独取数那内存带宽立刻成为瓶颈阵列再大也白搭。Google在TPU里用的方案是脉动阵列Systolic Array这个设计非常巧妙数据像心跳一样在阵列中逐拍流动每个MAC算完的结果直接传给相邻的MAC不需要反复访问内存。权重数据预先加载到阵列中保持不动激活值从左侧流入、从下方流出整个数据流高度规整几乎没有控制开销。2.2 权重 stationary 与数据复用脉动阵列的核心思想是权重驻留Weight Stationary。在推理阶段模型的权重是固定的所以可以把权重预先加载到MAC阵列的寄存器里然后让输入数据一波一波地流过。每一波数据经过阵列时会和驻留的权重完成乘加输出部分和。这样权重的读取次数从“每个输入都要读一次”降到了“整个推理过程只读一次”内存带宽压力大幅降低。我用一个具体例子来说明数据复用的价值。假设做一个3×3卷积输入通道64输出通道128特征图大小56×56。如果不用任何复用策略每个输出像素需要读取3×3×64576个输入值和576×128个权重值计算量是576×128次乘加。但实际上相邻输出像素共享大量输入数据权重更是所有像素共享。NPU通过片上缓存和阵列结构把这些复用做到极致实际的内存访问量可能只有理论值的几十分之一。2.3 片上缓存与数据搬运的分层设计NPU内部通常有三级存储结构**寄存器文件Register File**离MAC最近速度最快但容量最小片上SRAM容量大一些用来缓存特征图和权重块外部DRAM容量最大但带宽有限、延迟高。推理过程中的数据搬运策略直接决定了实际性能。一个常见的优化手段是分块Tiling。把大的特征图和权重矩阵切成小块让每一块都能塞进片上SRAM算完一块再换下一块。分块大小需要根据SRAM容量、阵列尺寸、数据复用模式来综合决定。分得太小数据搬运次数多分得太大SRAM装不下只能频繁访问DRAM。这个平衡点找得好不好往往就是同一颗NPU在不同模型上表现差异巨大的原因。提示很多NPU厂商提供的编译器会自动做分块和调度但编译器不是万能的。如果你发现某个模型在NPU上跑得异常慢大概率是编译器选择了糟糕的分块策略或者某个算子根本不支持NPU加速被回退到了CPU。3. 什么样的模型能真正吃到NPU的红利3.1 算子支持度不是所有层都能加速NPU不是万能的它只对特定类型的算子有加速效果。常见的支持列表包括标准卷积1×1、3×3、5×5等、深度可分离卷积、全连接层、池化层、逐元素加法/乘法、ReLU类激活函数、批归一化通常融合进卷积。而像动态形状的算子、自定义的复杂激活函数、非标准的注意力机制、循环神经网络里的某些门控操作NPU往往不支持或者支持得很差。我踩过的一个典型坑是某个模型里用了一个自定义的Swish激活函数实现NPU编译器不认识这个算子直接把它丢回CPU执行。结果整个网络被切成了好几段NPU算一段、CPU算一段、再回NPU算一段中间还有数据在NPU和CPU之间来回拷贝的开销。最终推理速度比纯CPU还慢。后来把Swish换成了NPU原生支持的HardSwish整个网络重新变成一个完整的NPU子图速度立刻上来了。所以在模型设计阶段就要考虑NPU友好性。如果你是从头训练模型尽量用NPU厂商验证过的算子组合如果是移植已有模型先用工具链跑一遍算子支持度分析看看有多少层能落到NPU上。一般来说NPU覆盖率低于70%的模型加速效果会大打折扣因为CPU和NPU之间的切换开销会吃掉大部分收益。3.2 量化INT8是NPU的主场绝大多数NPU的峰值算力都是在INT8精度下测得的FP16通常只有一半甚至更低的吞吐。原因很简单INT8的乘法器面积和功耗远小于FP16同样的芯片面积能塞下更多的INT8 MAC单元。所以想让NPU跑出标称性能量化到INT8几乎是必经之路。量化的基本思路是把FP32的权重和激活值映射到INT8的整数范围。最常见的是对称量化q round(x / scale)其中scale是根据张量的最大绝对值算出来的。推理时用INT8做乘加累加器用INT32防止溢出最后再乘回scale还原到浮点。但量化不是没有代价的。有些层对精度特别敏感比如第一层卷积直接处理输入图像和最后一层全连接直接输出分类logits量化误差可能导致明显的精度下降。常见的做法是这几层保持FP16或FP32中间层用INT8。这种混合精度策略在精度和速度之间取得平衡。精度模式典型算力比精度损失适用场景FP321×无训练、精度敏感层FP162-4×极小对精度要求高的推理INT84-16×可控通常1%大多数推理场景INT48-32×较大极致压缩、容忍精度损失量化过程中还有一个容易被忽略的细节校准集的选择。scale的计算依赖于激活值的分布范围而这个范围是通过在校准集上跑前向传播统计出来的。如果校准集和实际推理数据的分布差异大量化后的精度就会崩。我一般会从实际业务数据里抽几百到几千张有代表性的样本做校准而不是随便拿训练集的一个子集凑数。3.3 内存布局与数据排布的影响NPU对输入数据的排布格式往往有特定要求。CPU上常见的NCHW格式批次、通道、高、宽在NPU上可能不是最优的很多NPU更偏好NHWC或者专用的分块格式。如果输入格式不匹配NPU要么需要额外的转换步骤要么直接拒绝加速。这个问题在部署时经常被忽视。比如你用某个推理框架加载了一个ONNX模型输入是NCHW但NPU编译器期望NHWC它可能会在模型前面插入一个转置操作。这个转置如果落在CPU上执行每帧都要多做一次全图数据重排开销不小。解决办法是在模型导出阶段就把格式转好或者在预处理流水线里直接输出NPU期望的格式。4. 把模型搬上NPU的完整实操链路4.1 工具链选型与模型转换不同厂商的NPU配套工具链差异很大但大体流程是相似的训练框架导出 → 中间格式转换 → NPU编译器优化 → 生成可执行文件。以常见的流程为例你可能有PyTorch或TensorFlow训练好的模型先导出成ONNX然后用NPU厂商提供的编译器把ONNX转成NPU能执行的格式。这个转换过程是整个链路里最容易出问题的环节。常见的问题包括算子版本不匹配ONNX的某个算子版本NPU编译器不支持、动态维度NPU通常要求静态shape、自定义算子丢失等。我的经验是尽量用ONNX的opset版本和NPU编译器文档里明确列出的版本对齐不要盲目追新。如果模型里有自定义算子提前写好对应的NPU实现或者找厂商要支持。转换完成后一定要用工具链自带的逐层对比功能验证精度。把原始模型和转换后模型在同一批输入上跑一遍逐层对比输出差异。如果某一层误差突然变大说明那一层的转换出了问题需要单独排查。4.2 量化校准的实操细节量化校准这一步值得单独拿出来讲因为它对最终精度的影响太大了。工具链通常提供两种模式训练后量化PTQ和量化感知训练QAT。PTQ不需要重新训练速度快适合快速验证QAT在训练阶段就模拟量化误差精度更好但需要重新训练模型。对于大多数场景我建议先用PTQ跑一版看看精度。如果精度掉得不多比如Top-1准确率下降不到1%直接用PTQ就行。如果掉得厉害再考虑QAT。QAT的训练成本不低而且需要修改训练代码插入伪量化节点不是所有团队都有条件做。校准集的准备有几个要点样本数量不用太多几百到一千张通常够了但分布要覆盖实际场景。比如做安防监控的模型校准集里就要包含白天、夜晚、逆光、遮挡等各种情况。另外校准集不需要标签只需要输入数据所以准备起来相对容易。注意有些工具链的量化校准是逐层独立进行的不考虑层与层之间的误差累积。这种情况下即使每层误差都很小累积到最后一层也可能变得不可接受。如果遇到这种情况可以尝试逐层量化敏感度分析把敏感层排除在量化之外。4.3 推理引擎的集成与调度模型转换和量化完成后最后一步是把NPU推理集成到实际应用里。这一步的核心工作是任务调度和内存管理。NPU通常是一个独立的硬件单元CPU需要通过驱动和运行时库来提交推理任务、等待完成、取回结果。如果调度不当CPU和NPU之间的同步开销可能吃掉不少性能。一个常见的优化手段是流水线并行。当NPU在处理第N帧的时候CPU可以同时做第N1帧的预处理和第N-1帧的后处理。这样CPU和NPU各干各的互不等待。实现上可以用双缓冲或者多缓冲队列配合异步提交接口。很多NPU运行时都提供了异步API但默认可能是同步模式需要手动开启。另一个容易忽略的点是内存对齐。NPU的DMA引擎通常要求输入输出缓冲区按特定字节对齐比如64字节或128字节不对齐会导致性能下降甚至报错。在分配缓冲区时要用对齐分配函数不要直接用malloc。5. 实测中遇到的典型问题与排查思路5.1 推理结果不对从量化误差到布局错位NPU推理结果和CPU不一致是最常见的问题排查起来需要耐心。我的排查顺序通常是这样的第一步确认输入数据一致。把同一份输入分别喂给CPU模型和NPU模型在模型入口处打印或保存输入张量的数值逐元素对比。如果输入就不一样那问题出在预处理阶段可能是归一化参数不同、颜色通道顺序不同、或者数据类型转换有误。第二步逐层对比中间输出。如果输入一致但最终输出不同就需要定位是哪一层开始出现偏差。工具链通常支持导出每层输出把CPU和NPU的中间结果逐层对比。第一层出现明显偏差的地方就是问题源头。第三步判断偏差类型。如果偏差很小比如1e-3量级大概率是量化误差或浮点累加顺序不同导致的属于正常范围。如果偏差很大比如输出完全乱了那可能是布局错位、算子实现错误、或者量化scale计算错误。我遇到过一次典型问题NPU上的卷积结果整体偏移了一个像素。排查后发现是padding模式不一致——CPU框架用的是SAME padding而NPU编译器默认用了VALID padding。这种问题在逐层对比时很容易看出来但如果不做逐层对比只看最终输出就会一头雾水。5.2 性能不达预期从算子回退到带宽瓶颈NPU跑得慢的原因通常有几类。算子回退是最常见的某些层不被NPU支持被丢回CPU执行导致NPU和CPU之间频繁切换。用工具链的profiling功能可以看到每层实际在哪个硬件上执行如果发现大量层落在CPU上就需要考虑替换算子或调整模型结构。带宽瓶颈是第二常见的原因。NPU算力再高如果数据喂不进去也是白搭。特别是当模型很大、片上SRAM装不下所有中间结果时特征图需要反复在DRAM和SRAM之间搬运。这时候可以尝试减小批次大小、降低输入分辨率、或者用更激进的量化来减少数据量。阵列利用率低是更深层的问题。如果模型的通道数太小比如只有8或16个通道而NPU的MAC阵列是256×256的那大部分MAC单元都在空转。这种情况下NPU的实际算力可能只有峰值的百分之几。解决办法是尽量用通道数较多的模型结构或者在部署时把多个小模型合并成一个大批次一起推理。5.3 功耗与散热的平衡NPU满负荷运行时的功耗不容忽视。特别是在手机或嵌入式设备上持续高负载推理会导致芯片温度快速上升触发降频保护实际性能反而下降。我实测过一块开发板NPU连续跑满5分钟后频率从1GHz降到了600MHz推理延迟直接翻倍。应对策略有几个方向控制推理频率不要每帧都跑根据业务需求适当跳帧动态调频在负载低的时候降频省电负载高的时候再升频散热设计加散热片或风扇保持芯片在合理温度范围内。如果是电池供电的设备还需要在性能和续航之间做权衡有时候用CPU跑一个轻量模型反而比NPU跑大模型更省电。6. 从项目经验里攒下来的几条实用建议6.1 模型设计阶段就要考虑NPU约束很多团队的做法是先训练一个精度最高的模型然后再想办法往NPU上搬。这个顺序往往导致大量返工。更合理的做法是在模型设计阶段就把NPU的约束纳入考量优先选择NPU原生支持的算子控制通道数为8的倍数对齐SIMD宽度避免动态shape尽量用标准卷积而不是各种变体。如果精度不够优先通过数据增强、更长的训练时间、知识蒸馏等手段来提升而不是引入NPU不友好的复杂结构。一个NPU覆盖率95%的中等模型实际推理速度往往比覆盖率60%的大模型快得多。6.2 建立自动化精度回归测试模型转换和量化过程中每次调整都可能影响精度。手动验证既费时又容易遗漏。建议搭建一套自动化回归测试准备一批固定输入和对应的CPU参考输出每次转换后自动跑一遍计算输出差异超过阈值就报警。这套机制能帮你在早期发现大部分转换问题避免把问题带到集成阶段。6.3 保留CPU回退路径无论NPU支持得多好总会有一些边缘情况需要CPU兜底。比如输入尺寸异常、模型加载失败、NPU驱动异常等。在架构设计时保留一条CPU推理路径作为降级方案。虽然CPU慢但至少能保证功能可用。我见过不少项目因为NPU初始化失败直接崩溃如果有CPU回退至少能优雅降级而不是直接挂掉。6.4 关注工具链版本更新NPU厂商的工具链迭代很快新版本往往修复了大量算子支持问题和性能bug。但升级工具链也可能引入新的兼容性问题。我的做法是锁定一个稳定版本用于生产同时用另一个环境跟踪最新版本定期评估是否值得升级。升级前一定要跑完整的精度和性能回归测试不要只看release note就贸然切换。6.5 实测数据比规格书靠谱规格书上的TOPS数字是在理想条件下测出来的实际性能受模型结构、内存带宽、编译器优化程度影响很大。选型阶段最好拿自己的实际模型去跑benchmark而不是只看纸面参数。同一颗NPU在不同模型上的表现可能差好几倍只有实测才能知道它适不适合你的场景。我在一个视频分析项目里对比过两颗标称算力相近的NPU一颗在卷积网络上表现很好另一颗在Transformer结构上明显更优。如果只看规格书根本看不出这个差异。后来了解到前者对3×3卷积有专门的硬件加速通路后者则对大矩阵乘法做了优化。所以匹配模型结构和NPU的硬件特性比单纯比较算力数字重要得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑