资讯动态

NPU和TPU深度解析:AI专用加速芯片的架构原理与工程落地

发布时间:2026/10/16 18:42:25 来源:尧图企业网站定制
这两年做AI部署的人基本都绕不开NPU和TPU这两个缩写。日常聊天里很多人把NPU和TPU混着叫觉得都是“AI加速卡”可真到了写代码、调性能、处理算子兼容的时候两者差别非常明显。我先后在手头的几个项目里接触过云端的TPU和终端侧的NPU从一脸懵到能把模型真正跑顺中间踩了不少坑。这一章就当是系列学习笔记的第19篇重点聊聊NPU/TPU硬件加速到底是怎么运作的以及在工程落地时需要注意哪些细节。内容偏向实践适合正在做模型部署、推理优化或者刚准备把模型从GPU迁到专用加速器上的人参考。1. 为什么需要NPU、TPU这类专用加速芯片1.1 通用处理器在AI计算上的瓶颈先回到一个基础问题CPU不能跑AI吗当然能跑可就是太慢、太费电。CPU的设计目标是通用性要处理分支预测、乱序执行、大容量缓存、各种中断和操作系统调度芯片面积里有很大一部分被控制逻辑和缓存占了真正留给算术运算单元的比例反而没想象中那么高。一个卷积层就是一堆乘加操作输入特征图和卷积核逐位置相乘再累加。假设有256个输入通道、256个输出通道卷积核是3x3输出特征图是56x56那这一层要做多少次乘加呢算一下256 × 256 × 3 × 3 × 56 × 56大约18亿次乘加。CPU虽然主频高但一次周期内能做的乘加数量有限主频再高也扛不住这种规模。GPU靠几千个并行核心硬扛能解决一部分问题但GPU本质上是为图形渲染设计的线程调度、缓存体系、内存带宽都有一套复杂的逻辑放在数据中心里功耗也不低。如果计算模式特别固定比如深度学习里的矩阵乘法和卷积能不能把一整块芯片都做成算数单元不要那么多控制逻辑这就是NPU和TPU这类专用加速器出现的逻辑基础。1.2 深度学习计算模式的“可硬化”优势深度学习模型的计算有个特点高度规则化。卷积、矩阵乘、批量归一化、激活函数这些操作可以被拆成非常规整的数据流指令类型很少分支更少。芯片设计里最怕的就是“乱”一旦指令流不稳定控制逻辑就得做大量判断流水线要不断冲刷算力就上不去。规则的计算模式正好适合做成专用数据通路。拿矩阵乘法举例一个大的乘法可以拆成多个小的乘法累加每个小单元只做“读数、乘、加、传递”这几件事。如果把这些小单元排成阵列让数据在相邻单元间流动就能避免反复从内存读数据这就是后来TPU上常用的脉动阵列思路。NPU虽然面向终端场景设计上更碎片化但核心思想一致把宝贵芯片面积拿去做乘法器和累加器减少乱七八糟的调度开销。这种思路带来的收益非常直接同样做一次卷积专用加速器的能效比可以比CPU高一到两个数量级。用量化后的INT8计算时因为硬件单元更简单功耗还能再降一截。对手机、摄像头、路由器这些对功耗敏感的设备来说能效比往往是决定能不能用AI功能的关键。1.3 能效比才是硬指标聊AI芯片很多人第一反应是“每秒多少亿次运算”但真正部署的时候功耗比算力更重要。我在调试一块终端NPU时吃过这个亏模型在开发板上跑得飞快一放到目标设备上温度很快顶到上限性能直接降频最后实际速度比边上模式还慢。问题就出在没考虑持续功耗下的降频曲线。TPU这类云端加速卡同样要抠功耗。数据中心电费成本摆在那里机房散热也有上限所以云端加速器会追求单位功耗下的算力最高值。移动端NPU更是把“能效比优先”刻在骨子里厂商宣传的AI算力很漂亮但真实场景下能维持多少算力要看散热设计和内存带宽不能只看顶配指标。理解这一点才能理解为什么NPU、TPU内部架构长得那么“偏科”——表面上是硬件设计选择本质是在通用性、灵活性、功耗之间反复权衡的结果。2. NPU和TPU的架构差异拆解2.1 TPU把矩阵乘法变成数据流水线TPU的设计哲学很清晰既然深度学习训练和推理的主要计算量是矩阵乘那就把矩阵乘做到极致。早期TPU的每个核心里有大规模的脉动阵列权重数据从左侧流入输入数据从上方流入计算结果在阵列里不断累加并往下方传递。数据在相邻计算单元间直接传递不需要一遍遍回写内存这对内存带宽的节省非常明显。用一条流水线作业做类比一条装配线上每个工位只负责把零件装到半成品上装完就传给下一个工位不需要把所有半成品都搬回仓库再领出来。脉动阵列就是这种思路每个处理单元只和邻居交换数据大量减少访存次数。矩阵乘法恰恰是访存密集型的操作把这个瓶颈按住性能自然就上来了。TPU的指令集也比较精简更接近“专用协处理器”而非通用CPU整个芯片的控制逻辑占比很小。配合编译器的静态调度每一条指令发出后都知道什么时候执行完、结果放在哪不需要动态调度。这种设计牺牲了灵活性换来了极高的吞吐量和可预测的延迟。数据中心的模型训练负载相对可控用编译器做全局优化是划算的。2.2 NPU异构计算下的“三核协同”终端NPU面对的场景更杂不能像TPU那样专注矩阵乘。一个手机上可能有图像增强、语音识别、实时翻译、手势检测等各种模型形状、算子、精度要求都不同。所以现代NPU的架构普遍是异构多核结构一个标量单元处理控制流和标量运算一个向量单元处理逐元素运算一个矩阵单元处理矩阵乘卷积再加上专用的激活函数单元、池化单元等。实际跑一个模型时NPU要把计算图切成不同片段标量、向量、矩阵部分分别调度到对应单元。这就好比一个大厨房炒菜、切菜、煲汤各有专用灶台厨师长编译器要把菜谱拆开合理分配到不同灶台还要保证出锅顺序对得上。硬件本身再快调度不均衡一样拖慢整体速度这也是为什么NPU的驱动和编译器经常成了整机性能上不去的主要原因。2.3 一张表看懂差异对比维度云端TPU终端NPU主要场景大规模训练、云端推理端侧推理、低延迟实时任务计算重点大矩阵乘、高吞吐多样算子、低功耗平衡架构风格大型脉动阵列、精简指令标量向量矩阵异构多核灵活度依赖编译器适合场景有限相对灵活但受驱动约束关键指标每秒浮点/整数运算次数、显存带宽能效比、内存带宽、延迟编程方式通过XLA/上层框架接入厂商工具链转换算子适配这张表不用背只要记住“TPU是为了把一个算得快好NPU是为了把一堆算得杂但省电”就够了。后面所有优化手段其实都是围绕这两条主线展开的。3. 从零把模型跑上云端TPU和终端NPU的接入实操3.1 云端TPU的接入流程第一次接触云TPU时我对它的印象是“接入方式很像GPU但限制不少”。以某云服务商提供的TPU实例为例流程大致是创建一个TPU虚拟机或者直接在训练集群里挂载TPU资源然后在代码里通过分布式策略把训练或推理逻辑映射到TPU上。以主流训练框架为例只需要声明一个分布式策略实例然后把模型构建和训练步骤写进策略的作用域里框架会自动把操作分配到TPU设备上。跑一个简单的图像分类模型核心改动其实只有几行其余训练代码可以沿用原有逻辑。不过有两个细节需要注意第一个是TPU对输入的张量尺寸非常敏感训练时batch size任意变化可能导致重新编译第二个是模型里如果有非TPU支持的自定义算子框架会尝试把整段计算图拆开不支持的算子留在CPU上执行结果就是每步训练都要做一次TPU和CPU之间的数据拷贝当CPU算子占比高时整体性能会被拖到惨不忍睹。我在一个模拟项目X里跑语义分割模型时就因为自定义的采样算子没被支持训练速度比纯GPU方案慢了近3倍。后来查状态统计发现大量时间花在跨设备传输上。解决办法是把自定义算子改写成基本算子组合让整张图可以在加速器内完成。3.2 终端NPU的接入全流程终端NPU的接入路径完全不一样。以手机、开发板上的NPU为例流程一般是这样先在通用框架里训练出模型导出成通用的中间表示格式比如ONNX然后拿到NPU厂商提供的工具链里做解析和转换转换后的模型再通过厂商的运行时库加载执行。这个过程听着不复杂实际操作时坑很多。模型转换工具通常会输出一个转换报告上面会列出哪些算子已支持、哪些被替换、哪些不兼容。我的习惯是第一步先花时间把这份报告读一遍就像开长途前先看路况播报能省下后面大量排查时间。实际操作里我推荐按下面几个步骤来先导出通用格式模型并用原始框架做一次前向推理确认模型本身没问题、输出数值符合预期。开启工具链的离线量化功能准备好标定数据集一次性完成格式转换和量化。查看转换报告重点检查有没有算子被回退到CPU、有没有插入数据拷贝节点。在开发板上用NPU运行时跑一遍分别测精度和延时。如果精度掉得厉害优先检查量化敏感层比如检测头、归一化层尝试对这些层单独保持高精度格式。这一步花了很长时间排查一个模型精度从0.92掉到0.88的问题。检查来检查去最后定位到是最前面的归一化层在量化时被合并进卷积层数值分布被拉偏了。解决办法就是对这一层做特殊处理不让它参与融合精度立刻恢复到0.91。3.3 编译器在中间做了什么无论TPU还是NPU都离不开把模型计算图映射到硬件的编译器。云端TPU这边主要依赖静态编译器框架把计算图发到编译器编译器做算子融合、内存规划、数据布局转换然后生成加速器指令。整个编译过程可能持续几十秒甚至几分钟这期间如果发现某个算子不支持会直接报错或者回退。正因如此云端TPU对“计算图静态性”的要求特别高训练代码里一个依赖Python数值变化的动态shape都有可能让编译器放弃治疗。终端NPU的编译器虽然轻一些但同样要解决算子调度和内存复用的问题。转换模型时很多参数都影响最终性能例如输入尺寸是否固定、内存分配策略是多块小内存还是单块大内存、输出张量是否提前申请等。我建议刚开始时把怀疑对象收敛到尽量少所有参数先用默认值跑通后再逐个调节。否则变量太多一旦性能不对根本说不清是哪一步引入的。4. 性能优化静态Shape、量化与算子裁剪4.1 静态Shape为什么是命根子不少人在GPU上写惯了动态shape的代码迁移到NPU或TPU时第一个不适应的地方就是shape。GPU上的张量尺寸可以灵活变化很多框架的动态shape支持也做得不错但专用加速器不一样计算图编译时往往需要确定所有张量的形状才能做内存规划和调度。我遇到过一个很典型的案例一个检测模型输入图片的分辨率不固定代码里用了动态shape处理。在GPU上跑一点问题没有一上NPU编译时间暴增运行时报错内容还特别晦涩反复看文档才明白是动态shape导致的。后来把所有输入统一padding到固定尺寸模型总算能跑起来速度也稳定了。虽然Padding带来了一些多余计算但比起动态分支带来的开销这点浪费完全值得。如果你要写一个同时适配CPU/GPU和NPU/TPU的推理服务从第一天就写成静态shape后面能省非常多麻烦。对检测、分割这类输入尺寸天然不固定的任务工程上的常见做法是先做等比例缩放再补边到模型要求的尺寸同时记录缩放比例和补边偏移量后处理时再做逆变换。4.2 量化的门道和精度回退量化的收益很直观从FP32到INT8模型体积理论上缩到四分之一推理速度通常提升两到四倍功耗也明显降低。但量化不是简单把数值从浮点截断成整数核心是确定缩放系数的过程。以感知量化为例需要准备一些有代表性的输入数据统计每一层激活值的数值范围然后为权重和激活各自算出合适的缩放系数。数据集选取非常关键最好覆盖真实场景里的各种输入分布否则量化后可能在某个特定场景下出现精度突然跳水。实操中我会按这样的顺序排查精度问题先做全模型INT8量化测一遍精度。如果精度不达标找出精度掉得最严重的子网络尝试单独对该子网络保留更高精度格式比如FP16。如果还不行考虑对该模型采用量化感知训练让模型在训练阶段就适应量化噪声。重点盯归一化层和残差连接处的量化边界这些地方数值分布比较敏感。有些工具链还支持按通道量化权重而不是整层共用一个缩放系数精度通常会更好一些。代价是计算稍微复杂但很多NPU硬件本身支持这种模式开启它几乎不增加额外开销。我在一个图像生成的模拟项目里单靠切换成按通道量化权重精度就回升了不少几乎看不出差别。4.3 算子裁剪与代替是提升上限的硬功夫第三方模型往往包含大量通用算子其中有些在通用框架里很常见但在专用加速器上效率极低。常见的例子包括很大的逐元素乘法、动态索引、复杂的Reshape加上Transpose组合、自定义归一化实现等。算子裁剪的第一步是看清计算图里有多少可替代的计算。我习惯用工具导出计算图结构统计算子类型分布然后按耗时排序。如果一个Transpose后面跟一个卷积且Transpose本身只是HWC和CHW的切换很多加速器支持直接写入卷积的布局参数省掉这个操作。类似的还有把多个小卷积融合成一次大矩阵乘、把BatchNorm在推理期折叠进前面卷积的权重里。调试时我还发现大量的Reshape和Transpose节点往往是因为模型在中间环节调整特征维度造成的这些操作不产生实际计算却会引发数据重排。重排动作在CPU上还好在NPU上经常要经过共享内存绕一大圈非常拖速度。所以能在框架层面改代码消除的布局转换尽量在源头解决不要全指望编译器变魔法。5. 排查实录几个值得写进笔记的坑5.1 动态Shape引发的编译爆炸有一次在开发板上跑一个语音唤醒模型板子CPU算力有限加载NPU后运行速度一直上不去。我翻运行日志发现同一段模型反复触发重新编译每次编译间隔很短明显是输入长度在波动导致缓存命中失败。语音数据经过特征提取后帧数不定代码里直接用了实际帧数造成shape每次不同。修改方案是把输入按最大帧数填充并在计算图中用slice截取有效区域。这样shape固定下来了编译只发生一次之后每次推理都走的缓存路径性能一下稳定了。这个坑很典型遇到“看起来一直重编译”的情况先别怀疑编译器是不是坏了优先检查输入shape会不会变。5.2 算子降级带来的隐形性能断层有一回模型转换报告里显示所有算子都支持跑起来速度却很一般。后来用性能分析工具逐层看耗时才发现某个形状动态变化的Scatter操作并没有跑在硬件计算单元上而是回退到了驱动里的参考实现那段代码吃掉了将近三分之一的时间。解决思路是把这个Scatter改写成若干基础操作的组合虽然运算次数多了但都能被硬件直接执行整体反而快了两倍不止。这里也提醒我转换报告说“支持”不代表“被加速”有些算子只是被软件模拟了下性能是灾难级的。识别这些坑的办法没有捷径只能在真实硬件上做逐层profile看到具体每一层的耗时数值让数据说话。5.3 现有排查速查表现象可能原因解决方向编译反复触发输入shape不稳定统一尺寸、padding到固定长度精度下降明显量化敏感层被强行INT8敏感层保留FP16、使用按通道量化权重速度上不去算子回退到模拟实现逐层profile找出异常耗时算子改写实现显存/内存暴涨内存池分配碎片严重调整缓存复用策略、减少并发推理实例加载模型极慢模型过大或算子切分不当精简算子、检查是否有冗余节点、开启模型压缩还有两个容易踩的坑我单独说下一个是调试时总拿静态数据测试结果一到线上发现输入分布和标定集差异太大精度崩了。量化模型的标定数据集最好直接从真实流量里采哪怕少一点也比纯离线生成的数据靠谱。另一个是批量推理时小batch性能看起来不错但batch加大以后延迟升高明显往往是内存带宽先到瓶颈这时候要回头优化数据布局而不是单纯减少batch。6. 个人经验一次成功的“全链路”最后聊一个我印象比较深的实操案例。某个图像分类系统要从旧架构迁移到新NPU方案整个链路包括数据预处理、模型推理、后处理三块。一开始模型直接转换到NPU上精度和速度都一般走了不少弯路后我总结下来的关键动作无非这么几件先把输入统一到固定分辨率静态shape跑通再做量化并且用真实业务数据做标定随后逐个检查转换报告里的降级算子能改写就改写最后调并发策略让预处理、推理、后处理三段流水线重叠起来。排掉前面说的那些坑之后系统端到端耗时从原来的120毫秒降到40毫秒左右功耗还低了。整个过程给我最大的感触是专用加速器的性能瓶颈往往不在硬件本身而在软件链路是否贴合硬件的脾气。编译器再聪明也架不住输入动态变化、算子形态太乱、量化标定随意。我现在拿到一个新模型第一件事永远是先做一次“算子普查”把支持情况和不支持的算子列清楚再谈优化和调度。如果你也想把模型跑上NPU或TPU建议从最简单的模型开始先把链路彻底打通再逐步增加复杂度千万不要一上来就把生产模型直接灌进去。硬件加速这件事底下全是细节每个细节都值得认真对待。

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

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

免费获取报价 →
↑