3. 端侧芯片硬件架构:NPU/DSP/GPU的异构计算单元、内存层次结构(SRAM/DRAM)、数据搬运与计算的比例关系
好,咱们直接切入正题。这一章聊的是端侧芯片的“家底”——硬件架构。说白了,就是NPU、DSP、GPU这些计算单元怎么分工,内存怎么倒腾数据,以及最要命的:数据搬运和计算到底谁更拖后腿。
我这些年调试过不少端侧芯片,从手机SoC到IoT的MCU都碰过。一个深刻的体会是:不懂硬件架构,做混合精度推理就是盲人摸象。你算法算得再准,模型压得再小,搬数据搬不过来了,一切白搭。
3.1 异构计算单元:各司其职,别乱点鸳鸯谱
端侧芯片里,CPU、GPU、NPU、DSP这几位爷,各有各的脾气。咱们做推理部署,得学会“看人下菜碟”。
3.4.1 NPU:专为神经网络而生
NPU,全称神经网络处理单元。这玩意儿就是为矩阵乘法、卷积这些操作量身定做的。我见过最夸张的NPU,一个时钟周期能处理上千个MAC(乘加)操作。
NPU的核心优势:
- 数据流架构:数据从SRAM里流进来,算完直接流出去,中间不走回头路。这比CPU那种“取指-译码-执行”的冯·诺依曼架构高效得多。
- 定点计算:大部分NPU只支持INT8甚至INT4。浮点?不存在的。所以混合精度推理里,NPU是处理量化后权重的主力。
- 脉动阵列:很多NPU内部是脉动阵列结构。数据像波浪一样在计算单元间传递,延迟低、吞吐高。
个人经验:我在一个项目里,把FP32的模型强行塞进只支持INT8的NPU。结果精度掉了5个点。后来发现,NPU对激活值的量化特别敏感。我的建议是:权重可以大胆量化,激活值最好留一手,比如用INT16或者混合精度。
3.4.2 DSP:信号处理的万金油
DSP,数字信号处理器。这老兄本来是做音频、图像处理的。但它的SIMD(单指令多数据)能力,做小规模的矩阵运算也绰绰有余。
DSP的用武之地:
- 预处理/后处理:比如图像缩放、颜色空间转换、非极大值抑制(NMS)。这些活儿让NPU干太浪费,让CPU干又太慢。DSP刚刚好。
- 小模型推理:一些轻量级模型(比如MobileNetV2的某些层),在DSP上跑可能比NPU还快。因为NPU启动开销大,模型太小的话,还没跑起来就结束了。
- 混合精度中的“精度补偿”:NPU算完INT8的结果,有些层精度不够。这时候可以用DSP做一次高精度的“修正”。
避坑指南:我曾经在DSP上跑一个LSTM层,结果发现DSP的指令缓存太小,模型参数一多就频繁miss。后来我把LSTM拆成多个小批次,才把性能提上来。记住:DSP的缓存是稀缺资源,别一股脑把大模型往里塞。
3.4.3 GPU:通用计算的备胎
端侧GPU,比如高通的Adreno、ARM的Mali。它们本来是做图形渲染的,但也能跑通用计算(GPGPU)。
GPU的定位:
- 兜底方案:当NPU不支持某些算子(比如动态形状、条件分支),或者DSP算力不够时,GPU可以顶上。
- 高精度计算:GPU支持FP16甚至FP32。如果你需要混合精度中的高精度分支,GPU是个好选择。
- 并行度极高:GPU有上千个核心,适合大矩阵乘法。但代价是功耗高、延迟大。
我个人习惯是:能上NPU的,绝不上GPU。GPU的功耗和发热,在端侧设备上是个大问题。你想想看,手机跑个模型,5分钟就烫得拿不住,这谁受得了?
3.2 内存层次结构:SRAM vs DRAM,速度与容量的博弈
端侧芯片的内存,说白了就两层:SRAM和DRAM。但这两层之间的差距,比你和马斯克的财富差距还大。
| 特性 | SRAM | DRAM |
|---|---|---|
| 速度 | ~1ns(几个时钟周期) | ~50ns(几十个时钟周期) |
| 容量 | 几MB到几十MB | 几GB到几十GB |
| 功耗 | 低(静态功耗高) | 高(刷新功耗高) |
| 成本 | 高(6个晶体管/bit) | 低(1个晶体管+电容/bit) |
| 用途 | 缓存、NPU本地内存 | 主存、模型存储 |
这里有个关键点:SRAM是芯片上的“黄金地段”,离计算单元近,速度快。DRAM是“郊区”,远,慢。但SRAM贵,容量小。所以,怎么把数据在SRAM和DRAM之间倒腾,就是门学问了。
注意:很多端侧芯片的NPU,内部有自己私有的SRAM(比如几MB)。这个SRAM是NPU的“专属高速缓存”,CPU和GPU碰不到。所以,模型参数如果能全部塞进NPU的私有SRAM,推理速度会快得飞起。一旦塞不下,就得频繁从DRAM搬数据,性能直接腰斩。
3.3 数据搬运与计算的比例关系:算力再强,也怕带宽不够
这是本章的重头戏。很多做算法的人,只盯着算力(TOPS),觉得算力高就万事大吉。其实,数据搬运才是端侧推理的真正瓶颈。
我给你们一个公式,叫“计算密度”或者“算术强度”:
算术强度 = 计算量(FLOPs) / 数据搬运量(Bytes)
这个值越大,说明计算越密集,数据搬运的负担越小。反之,如果算术强度很小,说明大部分时间都在搬数据,计算单元在“等米下锅”。
举个例子:
- 卷积层:假设输入是3x224x224,卷积核是64x3x3x3,输出是64x112x112。计算量大约是1.7GFLOPs。数据搬运量呢?输入约0.6MB,权重约0.17MB,输出约0.8MB。算术强度 ≈ 1.7G / (0.6+0.17+0.8)M ≈ 1.1K FLOPs/Byte。这个值还不错,属于计算密集型。
- 全连接层:输入是1024,输出是1024,权重是1024x1024。计算量是2MFLOPs。数据搬运量:输入4KB,权重4MB,输出4KB。算术强度 ≈ 2M / 4M ≈ 0.5 FLOPs/Byte。这个值很低,属于带宽密集型。
看到了吗?全连接层的算术强度只有卷积层的几千分之一。所以,全连接层在端侧芯片上特别慢,不是因为算力不够,而是因为带宽不够。
我的经验:我在优化一个BERT模型时,发现大部分时间都花在全连接层上。后来我把全连接层的权重做了INT4量化,数据搬运量直接减半,推理速度提升了近一倍。这就是混合精度的威力——降低精度,本质上是降低数据搬运量。
3.4 知识体系结构图
下面这张图,是我自己画的,把本章的核心逻辑串起来了。你们可以保存下来,以后做部署时对照着看。
这张图的核心逻辑是:计算单元(NPU/DSP/GPU)从SRAM取数据,SRAM不够了再从DRAM搬。而数据搬运的速度,远远跟不上计算单元“吃数据”的速度。所以,混合精度推理的本质,就是通过降低数据精度(比如从FP32降到INT8),来减少数据搬运量,让计算单元“吃饱”。
实用技巧:在实际部署时,我建议你们先算一下模型的“算术强度”。如果某个层的算术强度低于100 FLOPs/Byte,那就要小心了——这层大概率是带宽瓶颈。这时候,优先考虑对该层做量化,或者用算子融合(比如把卷积和BN融合)来减少数据搬运次数。
嗯,这一章的内容就到这里。记住:端侧推理,拼的不是算力,而是数据搬运的效率。下一章,我们会聊聊如何在具体的芯片上,把这些理论落地。
公众号:蓝海资料掘金营,微信deep3321