资讯详情

资讯详情

NPU与TPU架构解析:从矩阵乘法到端侧部署的软硬协同实践

1. 从CPU的困境说起为什么我们需要NPU和TPU如果你最近两年关注过手机芯片或者云端服务器的发布会大概率会反复听到两个词NPU和TPU。厂商在PPT上把这两个缩写写得特别大旁边配一个“算力提升XX倍”的箭头但很少有人真正讲清楚——它们到底是什么跟CPU、GPU有什么区别为什么非要有这两种东西。我最早接触这类硬件加速单元是在做一个边缘端图像分类的小项目。当时用一块普通的开发板跑一个轻量级卷积网络单帧推理要接近200毫秒帧率连5都上不去。我第一反应是模型太大于是剪枝、量化折腾了一圈效果有限。后来换了一块带NPU的开发板同样的模型、同样的输入尺寸单帧直接掉到20毫秒以内。那一刻我才真正意识到不是模型的问题是计算架构的问题。CPU的设计哲学是“通用”。它要能跑操作系统、要能处理分支跳转、要能应付各种不确定的指令流所以它把大量晶体管花在了缓存、乱序执行、分支预测这些控制逻辑上。真正用来做算术的ALU算术逻辑单元占比其实很小。你让它去做神经网络里那种“海量乘加、结构规整、数据可预测”的计算就像让一个博士生去搬砖——能力够但效率极低。GPU稍微好一点它有成百上千个核心天生适合并行。但GPU的定位是图形渲染和通用并行计算它的调度粒度、内存层级、指令发射方式仍然是围绕“通用并行”设计的。跑神经网络能用但功耗和面积利用率依然有优化空间。NPU和TPU就是在这个背景下出现的。它们属于领域专用架构DSADomain-Specific Architecture——放弃通用性把晶体管全部砸在神经网络最核心的运算上。TPU是张量处理单元Tensor Processing UnitNPU是神经网络处理单元Neural Processing Unit名字不同本质思路一致用硬件电路直接实现矩阵乘加把能省的调度开销全砍掉。这篇文章我会从架构原理、数据流设计、量化支持、实际部署中的坑这几个角度把NPU/TPU这件事讲透。不管你是做端侧部署的工程师还是刚接触异构计算的学生看完应该能建立起一套完整的认知框架知道什么时候该用、怎么用、以及用的时候要注意什么。2. 拆开一颗NPU它内部到底在算什么2.1 从矩阵乘法到脉动阵列神经网络推理中超过90%的计算量来自卷积和全连接层而这两者本质上都是矩阵乘法。一个卷积层可以展开成im2col GEMM的形式全连接层本身就是GEMM。所以NPU/TPU的核心任务非常明确高效地做矩阵乘法。CPU做矩阵乘法是“取两个数、乘、加、存回去”循环往复。TPU的做法完全不同它用了一种叫脉动阵列Systolic Array的结构。你可以把它想象成一条流水线数据从左边和上边流入在每一个交叉节点上完成一次乘加结果向右下方流动。整个阵列像心脏搏动一样每个时钟周期都有数据在流动不需要频繁访问内存。举个例子一个256×256的脉动阵列每个周期可以完成256×25665536次乘加运算。假设主频是1GHz理论峰值算力就是65536×2×1e9 ≈ 131 TFLOPS乘加算两次操作。而一颗高端CPU用SIMD指令峰值可能只有几百GFLOPS到几TFLOPS。差距就是这么来的。脉动阵列的关键优势在于数据复用。权重从上方加载一次就可以和从左方流入的多个激活值反复相乘激活值从左边流入一次也可以和上方多个权重相乘。这种复用极大减少了对内存带宽的需求——而内存带宽恰恰是神经网络推理中最容易成为瓶颈的地方。2.2 权重 stationary 与激活 stationary数据流设计是NPU架构的核心差异点。主流方案分两种权重固定Weight Stationary和激活固定Activation Stationary。权重固定的思路是把卷积核的权重预先加载到PE阵列中然后让输入特征图激活值流过阵列。这样做的好处是权重只需要加载一次适合卷积层中权重复用的场景。但缺点是如果网络层与层之间权重变化频繁加载开销就上来了。激活固定的思路相反把输入激活值固定在PE中让不同的权重流过。这种方案在某些全连接层或者batch size较大的场景下更有优势。实际产品中很多NPU采用的是混合方案或者根据层类型动态切换。比如卷积层用权重固定全连接层用激活固定。作为开发者你通常不需要手动选择但理解这个机制有助于你明白为什么某些模型结构在NPU上跑得快某些就跑得慢。2.3 片上缓存与数据搬运NPU内部通常有一块专门的片上缓存SRAM用来存放权重、激活值和中间结果。这块缓存的容量和带宽直接决定了NPU的实际利用率。我见过不少项目模型理论算力需求不高但NPU利用率只有30%不到。排查下来往往是数据搬运成了瓶颈权重太大片上缓存放不下需要反复从外部DDR读取或者中间特征图太大频繁换入换出。这时候你优化模型结构比如减少通道数、用深度可分离卷积比换硬件更有效。提示评估一颗NPU时不要只看峰值算力TOPS。问清楚片上缓存大小、支持的数据类型、以及典型模型下的实测利用率这些比纸面参数重要得多。3. TPU与NPU的路线差异云端和端侧的不同取舍3.1 云端TPU为吞吐量而生云端TPU的设计目标很纯粹在数据中心里以最低的功耗和成本完成大规模推理或训练。它通常通过PCIe或专用互联接口挂在服务器上配合大容量HBM内存可以跑非常大的batch size。云端TPU的几个典型特征支持BF16甚至FP8等低精度格式脉动阵列规模大128×128到256×256甚至更大有专门的矩阵乘法单元和向量单元分工。它不关心单次推理延迟关心的是每秒能处理多少样本。这种设计导致云端TPU对模型结构有一定“偏好”。如果模型里全是标准卷积和全连接它能跑出接近峰值的利用率。但如果模型里有大量自定义算子、动态控制流、或者稀疏结构利用率就会明显下降。所以云端部署时模型往往需要先经过图优化和算子融合把能合并的合并、能静态化的静态化。3.2 端侧NPU为能效和延迟而生端侧NPU面对的是完全不同的约束功耗可能只有几百毫瓦到几瓦内存带宽有限散热条件差而且往往要求单帧延迟稳定。所以端侧NPU的阵列规模通常小得多但会在低精度量化和算子融合上做得更激进。很多端侧NPU支持INT8甚至INT4量化权重和激活值都用整数运算。整数乘加电路比浮点小得多功耗也低得多。配合通道级的量化缩放因子精度损失可以控制在可接受范围内。端侧NPU还有一个特点是与CPU/GPU的异构协同。不是所有算子都能在NPU上跑比如一些特殊的激活函数、自定义的归一化层可能还是要回退到CPU。所以端侧推理框架通常会把模型切成若干子图NPU能接的接过去接不了的留给CPU中间通过共享内存传递张量。3.3 一张表看清两者差异维度云端TPU端侧NPU设计目标高吞吐、低单位成本低功耗、低延迟阵列规模大128×128以上小32×32到64×64常见精度支持BF16/FP8/INT8INT8/INT4为主内存HBM带宽高LPDDR带宽受限算子覆盖偏标准算子需异构回退典型场景云端推理、训练加速手机、摄像头、车载理解这张表你就能明白为什么同一个模型在云端TPU上跑得好搬到端侧NPU上可能完全不是一回事。硬件形态决定了软件适配策略。4. 把模型塞进NPU量化、图优化与算子映射4.1 量化不是可选项是必选项如果你想让模型在NPU上跑出应有的性能量化几乎绕不开。原因很简单大多数端侧NPU的峰值算力是在INT8下测出来的用FP32跑可能只有几分之一甚至更低。量化的核心是把浮点权重和激活值映射到整数范围。最常用的是对称量化q round(x / scale)其中scale max(abs(x)) / 127INT8有符号。反量化就是x ≈ q * scale。但这里有个坑激活值的动态范围在不同输入下会变化。如果只用一组固定的scale遇到异常大的激活值就会截断遇到普遍偏小的激活值就会浪费精度。所以实际部署中通常需要校准Calibration用一批代表性数据跑一遍统计每层激活值的分布确定合适的scale。我自己的经验是校准集的选择比量化算法本身更重要。校准集要覆盖实际部署中可能出现的各种输入分布。如果校准集太单一量化后的模型在真实场景下精度掉点会很明显。4.2 图优化让NPU看到它喜欢的结构原始模型图往往包含很多NPU不擅长或者不支持的算子。图优化的任务就是在保持数学等价的前提下把图改写成NPU友好的形式。常见的优化包括算子融合把Conv BiasAdd ReLU融合成一个算子。这样中间结果不需要写回内存直接在NPU内部流水线里完成。常量折叠把可以在编译期算出来的子图提前算好减少运行时计算量。布局转换把NCHW转成NHWC或者NPU偏好的内部布局避免运行时反复转置。死代码消除去掉推理用不到的分支和节点。这些优化通常由推理框架如TensorRT、TFLite、ONNX Runtime等自动完成但你需要知道它们的存在。因为当优化失败时你得能定位是哪一步出了问题。4.3 算子映射哪些能跑哪些不能跑不是所有算子都有NPU实现。常见的支持情况大致如下算子类型NPU支持情况备注标准卷积完全支持核心算子深度可分离卷积完全支持端侧重点优化全连接完全支持本质是GEMMReLU/ReLU6完全支持通常融合进前一层Sigmoid/Tanh部分支持可能回退CPULayerNorm部分支持依赖具体硬件自定义算子通常不支持需手动实现或回退当你发现模型里有个别算子不被支持时最直接的办法是替换成等价的支持算子组合。比如某些NPU不支持HardSwish但可以用ReLU6和乘法组合近似。当然这需要验证精度是否可接受。5. 实测中的性能陷阱为什么你的NPU跑不满5.1 内存带宽最容易被忽视的瓶颈我做过一个实验同一个MobileNetV2模型在同一颗NPU上输入尺寸从224×224降到160×160理论算力需求降了一半但实测延迟只降了不到30%。原因就是内存带宽成了瓶颈。输入尺寸小了但权重还是要完整加载中间特征图的搬运次数也没少多少。这个现象在端侧尤其明显。端侧NPU的片上缓存通常只有几百KB到几MB而一个稍微大点的模型权重就有几十MB。权重必须存在外部DDR里每次推理都要从DDR搬到片上缓存。如果DDR带宽不够NPU算得再快也得等着。应对策略有几个一是权重压缩用量化把FP32压成INT8带宽需求直接降到四分之一二是层融合减少中间结果的写回和读取三是模型剪枝去掉冗余通道从根源上减少数据量。5.2 算子融合的边界条件算子融合不是万能的。有些融合在数学上等价但在数值上可能引入误差。比如把Conv BatchNorm融合时如果BatchNorm的方差很小融合后的缩放因子可能非常大导致量化时动态范围爆炸。我踩过的一个坑是某个模型在融合前精度正常融合后掉了好几个点。排查发现是某一层的BatchNorm统计量在校准集上方差极小融合后权重被放大量化时截断严重。解决办法是对这一层跳过融合或者用更高的位宽单独处理。注意融合后的模型一定要用真实数据验证精度不要只看理论等价性。5.3 多核调度与任务切分高端NPU往往有多个计算核心。推理框架会把模型的不同层分配到不同核心上并行执行。但调度策略的好坏直接影响利用率。如果切分粒度太细核心间同步开销会吃掉并行收益如果切分太粗又可能出现负载不均。实际中框架通常会根据层的计算量和依赖关系做自动切分但你可以通过调整模型结构来帮助它。比如把计算量相近的层放在相邻位置减少跨核数据传递。5.4 温度与降频端侧设备散热条件有限NPU长时间高负载运行会触发降频。我见过一个车载项目常温下NPU能跑满但夏天车内温度上来后推理延迟直接翻倍。后来通过限制连续推理的占空比和优化模型降低平均功耗才解决。这个坑在实验室里很难发现因为实验室通常空调开得很足。做端侧部署时一定要在接近真实环境的温度条件下做压力测试。6. 从选型到落地一套可复用的实践思路6.1 先看模型再看硬件很多人选硬件的顺序是反的先看哪颗NPU算力高然后想办法把模型塞进去。更合理的做法是先分析模型的计算特征主要算子是卷积还是全连接通道数分布如何有没有大量小算子对量化敏感不敏感把这些搞清楚之后再去匹配NPU。比如模型以深度可分离卷积为主就选对深度卷积优化好的NPU模型以全连接为主就选脉动阵列大的。匹配度比绝对算力更重要。6.2 量化感知训练 vs 训练后量化如果模型对精度要求高训练后量化PTQ掉点太多可以考虑量化感知训练QAT。QAT在训练过程中模拟量化误差让模型权重去适应量化后的表示。代价是需要重新训练但精度通常比PTQ好很多。我的建议是先用PTQ跑一版看精度掉多少。如果掉点在可接受范围内比如1个点以内就直接用PTQ省时省力。如果掉点严重再上QAT。6.3 性能剖析的正确姿势不要凭感觉猜瓶颈。用工具拿到真实数据每层的执行时间、NPU利用率、DDR带宽占用、片上缓存命中率。这些数据能告诉你问题到底出在计算、搬运还是调度上。我通常会把模型按层拆开逐层测时间。如果某一层时间异常长再看它的算子类型、输入输出尺寸、是否被融合。很多时候优化一两个关键层就能带来整体性能的明显提升。6.4 留出回退路径NPU不是万能的。总会有一些算子或者模型结构在NPU上跑不了或者跑不好。设计系统时一定要留好CPU回退路径并且保证回退时的数据传递开销可控。一个实用的做法是在模型编译阶段就标记出哪些子图会回退评估回退对整体延迟的影响。如果回退部分占比太大就要考虑改模型结构或者换硬件方案了。7. 一些个人体会折腾NPU和TPU这几年最大的感受是硬件加速不是银弹它是一套需要软硬协同的系统工程。同一颗芯片不同的人用性能可能差好几倍。差距不在硬件本身而在对数据流、量化、图优化的理解深度。另一个体会是不要迷信峰值算力。厂商标的TOPS是在最理想条件下测出来的实际模型能跑到一半就算不错了。评估硬件时一定要用你自己的模型去实测看端到端延迟、看功耗、看精度保持。最后保持对新架构的关注。NPU和TPU的迭代速度很快今天的最佳实践可能明年就过时了。但底层的那些原理——数据复用、量化、算子融合、内存层级——是不太会变的。把这些吃透换什么硬件都能快速上手。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →