1. 黑暗硅到底黑在哪里:先算一笔芯片功耗账

很多人以为,芯片设计的终极目标是让所有晶体管都同时工作,处理器核心越多越快。但如果你真的做过SoC后端实现,或者跑过全芯片功耗仿真,就会清楚一件事情:在现代制程下,一颗芯片上真正能在同一时刻满负荷运行的晶体管,可能连一半都不到。剩下的那一大片电路,不是不想干活,是物理上根本开不了机。这个现象,学术界给它起了个很形象的名字——Dark Silicon,黑暗硅。

我第一次听到这个说法是在做一款边缘侧AI芯片架构预研的时候,当时的反应是:这不就是功耗墙吗?确实,底层逻辑就是功耗墙,但Dark Silicon强调的是另一个角度:随着制程不断微缩,晶体管密度一直在涨,可功耗预算却被封装、散热死死按住。于是每代芯片里“能亮”的硅越来越少,“黑着”的硅越来越多。这个问题直接影响了多核处理器的扩展路线,也催生了今天几乎所有芯片里都要塞一个机器学习加速器的设计范式。

这篇文章我想好好聊聊Dark Silicon的来龙去脉,以及为什么机器学习加速器会是这个问题的天然解药。内容会比较偏体系结构方向,但我会尽量用做项目时真正会碰到的数字和流程来讲,适合正在做芯片选型、异构SoC架构设计,或者对AI硬件感兴趣的同学参考。

1.1 功耗墙:晶体管密度涨了,功耗预算却没涨

先看一个最基本的公式,动态功耗的经典表达式:

P = αCV²f

其中α是开关活动因子,C是等效电容,V是核心电压,f是工作频率。在90nm往前的年代,每次制程进步,电压和电容都在降,哪怕频率往上拉,功耗还能勉强压在封装允许的范围内。但进入深亚微米之后,电压降幅越来越有限,阈值电压也不能跟着无限降,因为漏电功耗会指数级上升。到28nm、16nm、7nm这几代,情况非常明显:同样功耗预算下,晶体管数量可能翻了几倍,但你能“点亮”的比例反而在下降。

我拿一个自己参与过的芯片项目来举例。那颗芯片大概有80多亿个晶体管,封装允许的最大功耗是150W左右。但当我们把全部计算单元同时跑到满频率时,瞬态功耗仿真显示接近220W。这意味着什么?意味着你必须在硬件设计阶段就做出选择:哪些模块可以同时工作,哪些必须互相排他。

这不是软件调度能解决的,因为功耗是物理层的硬约束,软件看不到也管不到。你只能在架构层面,把“同时工作”这件事设计成一种稀缺资源。于是,片上一大片计算单元,在绝大多数应用场景下,都保持时钟关闭或者电源关闭的状态,只等特定任务来了才被唤醒。这就是Dark Silicon的雏形:不是因为设计浪费,而是因为功耗预算不允许。

1.2 多核扩展的黄昏:Amdahl定律与并发墙

在功耗墙出现之前,性能提升靠提频;频率撞墙之后,大家开始堆核心。这个思路在四核、八核时代是有效的,因为并行度还有挖掘空间。但核心数量继续往上涨,问题就来了。

Amdahl定律告诉我们,加速比受限于串行部分。假如一个应用有10%的串行代码,理论最大加速比就是10倍。当你从4核走到32核,串行比例稍微大一点,加速比就上不去了。更关键的是,在多核处理器里,每一个核心都有独立的取指、译码、乱序执行、寄存器重命名、缓存一致性协议这些开销。这些电路只有在核心真正忙碌时才有价值,而在更多时候,它们和那些睡眠的核心一样,都在贡献漏电,却不贡献性能。

还有个被很多文章忽略的问题:多核的负载均衡在真实系统里非常难做。你跑一个大模型推理,不可能把一层卷积均匀分到32个核上,因为核心之间通信、同步、数据搬运的开销,可能比计算本身还高。我实际测过,某些场景下从16核扩展到32核,加速比只能到1.3倍左右,这已经属于典型的“并发墙”了。

所以从架构演进的角度看,通用多核的边际收益越来越低,想继续提升性能,必须换一条路:不为所有场景设计一个通用部件,而是为特定工作负载设计专用部件。这条路的物理基础,恰恰是那些“用不上”的Dark Silicon区域。

1.3 通用计算的代价:能效账算下来非常亏

通用CPU为什么能效低?因为它必须处理任何可能的指令序列。为了应对不确定性,它要花大量晶体管在控制逻辑、分支预测、乱序执行、缓存管理上。这些电路本身不完成任何用户需要的计算,它们只是在为“可能出现的复杂指令流”做准备。

打个比方,通用处理器就像一个大厨,他什么菜都能做,但为了做到什么菜都会,厨房里摆满了各种工具和调料。而专用加速器更像一条寿司流水线,只做固定品类,效率高、速度快、浪费少。深度学习推理就是这样一个“固定品类”——卷积、矩阵乘、激活函数、池化,算子类型非常有限,而且计算模式高度规则。

从实测数据看,差距很直观。一个高性能GPU跑FP32通用计算,能效大概在0.2-0.5 TFLOPS/W;但如果把同样的计算改成INT8精度,并使用专用的张量核心,能效可以提升到2-5 TFLOPS/W以上。手机SoC里那种小体积NPU,INT8推理能效甚至能做到10-20 TOPS/W。差距不是一个数量级,而是两个数量级。

这个差距就是Dark Silicon给机器学习加速器留出的生存空间:在通用核心用不满功耗预算的时候,把闲置的晶体管面积改造成专用加速器,既不吃功耗,又能按需提供远超通用核心的算力。

2. 机器学习加速器为什么能吃下黑暗硅这块蛋糕

Dark Silicon的本质是“面积有,功耗不够”。机器学习加速器的聪明之处在于,它完美匹配了这个约束:专用电路面积小,能效高,且大部分时间可以彻底断电。换句话说,它把原本“必须黑着”的硅变成了“需要时点亮一下”的高性能模块。

但如果你以为只要做一个乘加阵列就能叫加速器,那就太天真了。机器学习加速器能成为主流方案,背后是一整套软硬件协同设计逻辑,从计算模式到数据流到精度策略,每一环都在为“省功耗”服务。这章节我拆开讲。

2.1 计算模式高度规则:专用电路能榨干每一个晶体管

深度学习模型里最核心的计算是卷积和矩阵乘。卷积本质上是一系列乘加操作(MAC),矩阵乘也是。这些操作的特点是什么?数据访问模式规则、操作重复率高、并行度自然存在。

举个例子,一个3×3的卷积核在256通道的特征图上滑动,计算过程可以理解为:每次取一个窗口内的数据,和256个权重做乘加,然后把结果累加。这要是在CPU上跑,你需要一堆循环和访存指令;但在硬件上,你可以把它直接铺开成一条流水线,同一时刻处理几十个甚至几百个MAC操作。

因为计算模式规则,编译器可以提前安排好数据搬运的节奏,硬件的控制逻辑也非常简单。这意味着什么?意味着你可以把绝大部分面积留给真正的乘法器和加法器,而不是像CPU那样把一半面积花在控制逻辑上。同样面积的硅片,加速器的“有效计算密度”远高于通用核心。

这就是专用性的价值:电路越专一,能效越高。代价是灵活性下降,但深度学习这个领域足够大,值得为它做这种牺牲。

2.2 数据复用与片上存储:把访存功耗省到极致

芯片设计里有一句老话:计算是便宜的,访存是贵的。一个INT8乘加操作消耗的能量大约是0.2-0.5 pJ,而访问一次DRAM消耗的能量高达几百pJ,两者差了上千倍。所以降低功耗的核心策略,就是减少对DRAM的访问,提高数据复用率。

机器学习加速器的存储层次设计,就是围绕“复用”来展开的。具体来说,有三种数据复用模式:

  • 权重复用:同一个权重被多个输入数据共享,适用卷积核在空间维度滑动的情况。
  • 输入复用:同一个输入数据被多个权重使用,适用全连接层或多输出通道的情况。
  • 输出复用:多个部分结果在片上累加,避免中间结果频繁写回DRAM。

硬件设计上,这些复用模式决定了片上SRAM的容量、寄存器的排布、数据在计算阵列中的流动方向。我做过一个粗略的测算:一个卷积层的数据量如果全部从DRAM读,需要传输约几十MB;但通过合理的重用策略,实际DRAM访问可以压缩到几百KB级别,功耗差了两个数量级。

这也是为什么几乎所有AI加速器都会在计算阵列周围堆大量SRAM,有的还专门设计多级缓存结构。存储不直接产生算力,但没有足够的片上存储,算力再高也会被访存功耗拖垮。

2.3 精度与稀疏性:能省一点是一点,积少成多

深度学习领域有一个很反直觉的事实:大多数推理任务根本不需要FP32精度。神经网络权重和激活值经过量化后,用INT8甚至INT4表示,精度损失通常很小,但功耗和面积开销可以大幅下降。

为什么整型计算更省?因为整型乘法器的面积大概是浮点乘法器的四分之一左右,功耗也低得多。从FP32换成INT8,在很多加速器上能效可以提升4-6倍。所以你会看到,Google TPU、NVIDIA Tensor Core、各类NPU都在大力支持低精度计算。

另一个被广泛利用的特性是稀疏性。深度神经网络经过训练后,大量权重值为零或者接近零。实际推理时可以跳过这些零值,省掉对应的MAC计算。稀疏加速器可以根据稀疏模式动态跳过无效计算,理论上能把性能提升一倍甚至更多,同时功耗几乎不变。

但稀疏加速也不是白给的,它需要额外的稀疏索引逻辑和负载均衡策略,设计不好甚至可能比密集加速更慢。所以实际产品往往只在特定场景开放稀疏支持。我个人建议做架构评估时,先把密集计算能效做到位,再考虑稀疏化,不要一上来就做复杂设计。

3. 从一个设计实例开始:芯片面积预算怎么分给加速器

聊完理论,进入实操部分。假设我们要设计一颗用于边缘设备的SoC,制程选7nm,芯片总面积为250mm²,功耗预算10W。现在要在片上加一个机器学习加速器,怎么决定加速器面积、算力、存储容量这些参数?这就是设计空间探索,简称DSE。

我的经验是:不要上来就拍脑袋定TOPS,而是从目标场景反推。下面我以一个典型的端侧视觉任务为例,走一遍完整的估算流程。

3.1 第一步:从应用场景推导算力需求

假设设备要运行一个实时视频分析模型,输入是1080p分辨率的视频流,帧率30fps。选一个轻量级模型,比如YOLOv5s,它的计算量大约在16 GFLOPs左右。这是FP32的浮点运算量。

如果换到INT8精度,运算量同样是16 GOPS(乘加操作数基本不变,只是精度变了)。我们用这个题目反推硬件的峰值算力:

  • 目标帧率:30fps
  • 每帧计算量:16 GOPS
  • 所以需要算力:30 × 16 = 480 GOPS ≈ 0.5 TOPS
  • 考虑到实际利用率很难达到100%,按50%计算效率算,峰值需要约1 TOPS。

这是纯视频模型的需求。如果还要跑语音识别或者更复杂的模型,就得多留一些余量。我一般会按峰值需求的3-4倍来设计,这样既能覆盖不同模型的波动,还能给未来模型升级留空间。在这个例子里,最终选1.5 TOPS左右的INT8峰值算力比较稳妥。

3.2 第二步:从算力目标反推MAC阵列规模与面积

有了峰值算力目标,下一步就是确定计算阵列有多大。INT8乘法器加上累加器,在7nm工艺下,一个MAC单元的面积大约在200-400μm²之间。这个数字包含了寄存器和局部布线,实际项目里要看标准单元库和布局情况。

假设每个MAC单元面积取300μm²,目标算力1.5 TOPS,即每秒完成1.5万亿次乘加操作。如果工作频率设为1GHz,那么每个周期需要完成:

1.5 TOPS ÷ 1GHz = 1500 MAC

也就是计算阵列至少要有1500个MAC单元。用面积乘以数量:

1500 × 300μm² = 450,000μm² = 0.45mm²

这还只是MAC阵列的裸面积。算上权重缓冲、激活缓冲、输出累加器、控制逻辑、片上SRAM,整个加速器核心大约需要放大5-8倍。我们按6倍算,那就是约2.7mm²。

这个面积放在250mm²的SoC里,占比只有1%左右,几乎可以忽略不计。但要注意,如果目标场景换成训练或者更大的模型,比如CLIP、Diffusion这种,算力需求可能直接翻几百倍,加速器面积也会随之涨到几十平方毫米,这时候就需要认真思考面积分配了。

3.3 第三步:存储容量与带宽的权衡

算力只是加速器的一半,另一半是存储和带宽。我经常看到有人设计加速器时只吹算力,结果一测带宽,数据根本喂不进去,芯片花了大价钱做了高算力,实际运行效率只有20%。

继续用上面那个例子。目标算力1.5 TOPS,工作频率1GHz,即每个周期需要1500个MAC。每个MAC需要至少读一个权重和一个激活值,总共两个数据。如果都用INT8,一个周期需要读取:

1500 × 2 × 1B = 3000B

在1GHz频率下,这相当于每秒约3TB的数据吞吐。这个带宽,DRAM是绝对给不了的。所以必须在片上做数据复用和缓存,把绝大多数数据访问限定在SRAM甚至寄存器堆里。

实际设计中,我们一般会根据卷积层的特征图尺寸和权重尺寸来设计SRAM容量。比如前面提到的YOLOv5s,某卷积层输入是640×640×32,权重是32×3×3×32。如果能把整层权重放在片上,只需要在计算开始时从DRAM读一次,之后全部复用,DRAM带宽压力就能大幅下降。估下来,一个加速器核心配512KB到1MB的SRAM是常见做法。

3.4 第四步:电源域划分,让Dark Silicon按需点亮

加速器没有任务时怎么办?绝对不能让它一直通电,否则漏电功耗就会侵蚀整个系统的功耗预算。所以物理设计上必须把加速器规划成独立的电源域,支持Power Gating,也就是彻底断电。

我做过一个真实的项目,加速器没有独立电源域,结果整机待机功耗直接多了200mW,这在以10mW级待机为目标的设备里完全不可接受。后来把加速器单独切成一个电源域,软件通过一个寄存器控制通断,待机功耗才降回来。

电源管理还需要考虑唤醒延迟。Power Gating之后,供电恢复需要时间,SRAM里的数据也会丢失。如果模型的权重需要重新加载,唤醒一次可能就要几百微秒甚至几毫秒。设计任务调度时,要把这些开销算进去,否则会出现加速器频繁启停,性能反而下降的情况。

4. 业界落地盘点:TPU、Tensor Core与移动端NPU的取舍

理论讲再多,不如看看现实世界里的产品怎么做的。Google TPU、NVIDIA Tensor Core、手机SoC里的NPU,这三类加速器代表了Dark Silicon方案的三种不同落地策略,非常值得拆开分析。

4.1 数据中心专用加速器:Google TPU的启发

Google TPU v1是2016年发布的,设计目标很简单:加速推理。它采用了256×256的脉动阵列,针对INT8精度优化,峰值算力92 TOPS,功耗约40-75W,能效比同时期的GPU高一个数量级。

TPU最让我佩服的地方是它的纯粹。它不做训练,不做通用计算,甚至不算高精度浮点,只做推理。为什么这么设计?就是因为Google当时在数据中心里已经跑大量的深度学习推理任务,这些任务足够多,值得专门为它造一块芯片。

从Dark Silicon的角度看,TPU的思路是把数据中心的“暗硅”集中起来,做成一个独立的加速单元,用PCIe挂到主机上。它不是去改造CPU,而是直接新增一个高能效计算节点,让需要跑GPU又不甘心用通用GPU的场景有了更便宜的选择。

当然TPU也有明确短板:灵活性不行。模型算子一变,脉动阵列利用率就会下降。Google的应对办法是持续迭代架构,比如TPU v2/v3开始支持训练,v4/v5进一步扩展了灵活性和互连能力。但核心设计哲学依然是:用足够大的专用算力覆盖一个足够大的需求场景。

4.2 板载加速模块:NVIDIA Tensor Core的嵌入式思维

Tensor Core和TPU最大的不同在于,它不是独立的芯片,而是GPU内部的一个加速区域。最初专为矩阵乘设计,支持FP16、INT8、BF16等混合精度,后来扩展到更多的张量操作。

这种设计的优势是灵活部署:你买一张GPU,既能跑通用并行计算,也能跑深度学习Tensor Core加速。共享显存带宽和存储系统,让资源利用率更高。但它也面临一个尴尬:GPU本来就是耗电大户,Tensor Core在功耗预算内部要和其他模块竞争,省下的功耗远不如TPU那么显著。

从设计理念来看,Tensor Core更符合传统GPU的演进逻辑——在已有的大芯片里加一个高能效功能区,让它在“GPU本身就用不满所有面积”的情况下,把暗硅区域利用起来。

实际做推理部署时,Tensor Core的效果确实不错。我测过几个模型,在A100上用INT8 Tensor Core跑推理,能效比纯CUDA核跑FP32高3-5倍。如果你没有条件定制ASIC,直接用GPU的Tensor Core是性价比很高的方案。

4.3 手机SoC的NPU:面积受限下的极致权衡

手机SoC是Dark Silicon概念最典型的商业落地场景。芯片面积十几平方毫米,功耗预算只有几瓦,却要跑相机算法、语音识别、AI美颜、超级分辨率等各种模型。苹果的Neural Engine、高通的Hexagon、华为的达芬奇NPU,本质都是在极小的面积里塞进一个高能效加速单元。

手机NPU和TPU、Tensor Core最大的区别是极其关注待机功耗。手机大部分时间是待机的,NPU如果没有任务,就必须做到近乎零漏电。所以手机SoC里的NPU普遍采用多级电源门控,配合固件调度器动态开关。

还有一个有意思的取舍是,手机NPU通常会支持多种精度和多种算子,但不会像TPU那样追求极致算力,因为功耗预算实在有限。反而会把心思花在数据流优化上——如何让每个MAC操作真正被有效使用,减少空转,这才是边缘侧加速器的核心竞争力。

5. 设计加速器时踩过的坑:利用率、带宽与灵活性

最后分享一些我在实际设计、验证和部署AI加速器时踩过的坑。这些内容论文里很少写,但做项目几乎一定会遇到,算是避坑合集。

5.1 加速器利用率过低:算力再高,跑不起来就是废铁

利用率是加速器设计里最容易被高估的指标。设计时觉得峰值1.5 TOPS很漂亮,等集成到系统里一测,实际平均利用率只有30%,有时候真的会怀疑人生。

利用率低的原因很杂,最常见的有三个:

  • 模型算子碎片化。一个模型里有卷积、有池化、有归一化,还有各种激活函数。如果加速器只优化了卷积,其他算子跑到CPU上,那么CPU和加速器之间的同步开销就会吃掉不少收益。
  • 小算子太多。很多模型在开头和结尾有几个低计算量、高访存量的层,这些层在加速器上的利用率很低,但恰恰是它们的开销拉低了整体效果。
  • 驱动和应用没有做好缓存复用。如果每次调用加速器都重新加载权重、重新初始化上下文,一批小任务下来,光加载权重的时间就比计算时间还长。

我的建议是:做设计之前,先拿真实的目标benchmark在模拟器里跑一遍,把每一层的算力需求、访存需求、数据流模式统计出来,再决定加速器的数据流和存储结构。不要拿一个理想化的卷积层来设计整个加速器,否则最后打板测试时一定会有惊喜。

5.2 带宽不足:计算再快也喂不饱数据

这是加速器项目里最常见也最难解决的问题。计算阵列可以在1GHz下轻松跑出几个TOPS,但芯片外部只有LPDDR4/LPDDR5,带宽可能只有30-50GB/s。这时候你会发现,加速器大部分时间都在等数据,计算单元在那儿空转,功耗没少耗,效率却惨不忍睹。

解决带宽问题有三个思路,按优先级排序:

  • 第一,加大片上SRAM容量,把数据复用做到极致。同一个模型,多批次推理时,权重可以常驻片上,只换激活值,能明显降低DRAM带宽压力。
  • 第二,数据压缩。权重和激活值有很多稀疏和连续重复的值,用简单的压缩算法在DRAM和SRAM之间传输,可以有效降低带宽需求。INT8数据还可以做量化压缩。
  • 第三,任务分片。把大数据块拆成多个小片,每片计算完之后再写回,降低瞬时带宽峰值。

我做过一个项目,最开始带宽计算就只看了峰值需求,结果实测时频繁触发带宽不足,最后通过把batch从1改成4,权重复用率提上来,情况才好转。所以设计加速器时,请务必按照真实场景的batch大小来评估带宽。

5.3 灵活性不足:新算子来了,加速器不会跑

专用加速器的宿命就是:当你设计完芯片,模型结构已经变了。今天还是卷积为主,明天可能全是Transformer的Self-Attention。虽然矩阵乘这个底层操作还在,但数据流模式变了,固定数据流的加速器可能就在原地发呆。

应对灵活性不足,目前工业界主要有几种做法:

  • 支持算子拆分。把复杂算子拆成多个子操作,让加速器逐一执行。这需要硬件上支持细粒度的配置,比如可配置的输入输出步长、可配置的数据对齐模式。
  • 提供可编程模块。比如在加速器旁边加一个小型向量处理器,专门处理归一化、激活函数、Reshape等不规则算子。
  • 软件编译器做极致的算子优化。编译器负责把新算子映射到已有硬件上,通过循环变换、数据重排等方式提升硬件利用率。

这里要强调的是,硬件设计时需要预留一定的配置寄存器空间。我见过很多项目,硬件加速器设计得很漂亮,但没有留足够的可配置寄存器,导致软件侧再怎么优化,也只能在固定的数据流下打转,最后不得不为每个新算子重新流片。这个坑一定不要踩。

5.4 评估Dark Silicon ROI:加速器到底值不值得做

Dark Silicon策略的本质是拿面积换能效。但面积是芯片最贵的资源,多一块加速器,就少一块SRAM,或者少一组通用核心。怎么判断这个trade-off划不划算?

我的评估框架是算一个综合指标:在目标功耗预算内,所有工作负载的加权平均性能。加速器虽然只服务一部分模型,但它能释放功耗预算,让剩余功耗投入到通用计算或者更多加速模块中。这个逻辑是要看整体收益的。

具体做法是:把目标场景的每一类模型、频率、允许的延迟列出来,分别计算三种方案的性能:只有CPU、CPU+加速器、CPU+不同规格加速器。然后取加权代价函数,比如延迟越界惩罚、功耗越界惩罚、面积开销惩罚,跑一遍设计空间探索。

我建议项目初期就用这套方法做一轮快速估算,不要等到RTL写完再评估。加速器做不做、做多大,这类问题应该在架构定义阶段回答完毕。等流片回来发现加速器是块暗硅,那就真的只能让它黑着了。

5.5 低功耗库与标准单元的选择

最后聊一个后端实现阶段的细节。同样一个加速器逻辑,用高性能库还是低功耗库实现,能效差距可以超过30%。高性能库速度快,但漏电大;低功耗库速度慢,但漏电小。对于AI加速器这种“大部分时间都在闲着”的模块,低功耗库往往更划算。

当然这不是绝对的。如果加速器处理的是实时视频流,需要持续满载运行,那么漏电占比就不高,选用高性能库、把动态功耗压在更低电压下,可能是更好的选择。我的习惯是:先画功耗曲线,确定模块的“活跃占比”,再来选库。

SRAM编译器也有类似的选择问题。片上SRAM的漏电在先进制程下非常可观,很多SoC的待机功耗大头就是SRAM。建议给加速器的SRAM加上休眠模式,在没有访问时自动降电压,把漏电压下去。

写在最后的个人经验

做了几个AI加速器相关项目之后,我越来越觉得Dark Silicon不是一种无奈,而是一种机遇。它逼着芯片设计者重新思考:我们到底需要什么样的计算?用多少面积去换多少能效?什么样的模块值得占用一大片硅片?

如果你也在做类似的架构设计,我给三点建议。第一,一定要先统计真实工作负载,再决定加速器规格,不要先拍算力再找应用。第二,把加速器当成一个必须独立管理电源域的系统模块来设计,从架构阶段就规划好DVFS和Power Gating,不要等后端再补。第三,软件编译器团队要尽早介入,硬件和软件协同设计是加速器能发挥效力的前提,没有配套的编译器,再强的加速器也只是一块精致的暗硅。

最后再分享一个小技巧:给加速器设计一个简单的硬件性能计数器,统计每一层的执行时间、存储访问次数、空转周期。这个计数器在芯片验证阶段作用极大,很多性能问题的定位就靠它。实际项目里,这个看似不起眼的模块往往能省下团队几周的调试时间。

更多推荐