news 2026/10/28 14:30:52

脉动阵列深度解析:从数据流动到AI芯片设计实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
脉动阵列深度解析:从数据流动到AI芯片设计实践

1. 从一次面试翻车聊起:为什么脉动阵列值得单独拎出来讲

前几年我面一家做推理加速的芯片团队,面试官问了一个问题:“你们上一版加速器里MAC阵列的利用率是多少?”我当时脱口而出“峰值算力的百分之七八十吧”,对方接着追问:“那实际跑ResNet的逐层利用率呢?卷积层和全连接层差多少?为什么差?”我当场卡壳。后来复盘才意识到,我脑子里只有“算力峰值”这个概念,却从没认真想过数据是怎么在阵列里流动的——而决定这个流动效率的核心结构,就是脉动阵列(Systolic Array)。

这几年AI芯片火得一塌糊涂,几乎每家的架构图里都会画一个方方正正的网格,标注着“PE阵列”或者“Tensor Core”。但真正把脉动阵列讲清楚、讲透它为什么省带宽、为什么适合矩阵乘、又为什么在某些场景下反而拖后腿的资料并不多。这篇内容我打算从工程实现的角度,把脉动阵列的来龙去脉、数据流动方式、设计取舍和实际踩坑经验完整梳理一遍。不管你是刚入行的数字IC设计工程师,还是做算法部署想搞懂底层硬件的同学,看完应该都能对“数据怎么在芯片里跑起来”这件事有一个具象的认知。

需要先说明的是,脉动阵列不是为AI发明的。它最早出现在1978年H.T. Kung的论文里,那时候的目标是给信号处理、矩阵运算做专用硬件。几十年后深度学习爆发,大家发现卷积和全连接的本质就是大规模矩阵乘加,脉动阵列这种“数据流过即计算”的结构刚好对上了,于是被Google TPU、各类NPU大量采用。理解它的关键,不在于记住结构长什么样,而在于理解它解决的核心矛盾:计算单元的算力增长速度,远远快于内存带宽的增长速度。这个矛盾到今天依然存在,而且越来越尖锐。

2. 脉动阵列到底在“脉动”什么:数据流动的本质

2.1 从“取数-计算-写回”到“数据流过”

要理解脉动阵列,先看传统计算单元是怎么干活的。一个普通的MAC(乘累加)单元做一次运算,典型流程是:从寄存器堆或缓存里读操作数A,读操作数B,相乘,累加,把结果写回。每一次运算都要伴随多次访存。如果只有一个MAC,访存开销还能忍;但当你想堆几千个MAC来提升算力时,问题就来了——每个MAC都要独立地从内存里取数,内存带宽瞬间成为瓶颈,算力再高也喂不饱。

脉动阵列的思路完全不同。它把大量PE(Processing Element,处理单元)排成规则的二维网格,数据像心跳一样有节奏地从阵列边缘流入,经过一个个PE,在流动的过程中被计算、被传递。每个PE只跟相邻的PE交换数据,不需要每个周期都去访问大容量的内存。这就是“脉动”这个名字的由来——数据像血液在血管里脉动一样,一波一波地流过整个阵列。

我用一个生活化的类比来解释。假设你要给一长排工人传递砖块并让他们两两配对砌墙。传统做法是每个工人都跑到仓库去领砖,仓库门口挤成一团。脉动阵列的做法是:砖块从队列一端传进来,每个工人从传送带上拿一块,同时把手里的另一块传给下一个人,工人之间只做相邻传递,仓库只需要在传送带起点供货。结果就是仓库的压力骤降,工人们几乎不停手。

2.2 权重固定、输入流动:最经典的输出 stationary 变体

脉动阵列有多种数据流组织方式,工程上最常见的是权重固定(Weight Stationary)。以矩阵乘 C = A × B 为例,假设A是输入激活,B是权重。做法是:把权重B预先加载并“钉”在每个PE里,之后不再移动;输入激活A从阵列左侧按行流入,部分和(partial sum)从阵列上方或下方按列流出。每个PE每个周期做一次乘加,把结果累加到从上方传下来的部分和上,再往下传。

这种结构的妙处在于:权重加载一次,可以被成百上千次复用,极大减少了对权重存储的访问。而输入激活虽然要流动,但它在阵列里被复用的次数等于阵列的行数或列数。整体算下来,访存量相比“每个MAC独立取数”能降低一到两个数量级。这也是为什么TPU能在相对有限的带宽下跑出很高的有效算力。

2.3 一个具体的时序推演

光说概念容易飘,我拿一个4×4的脉动阵列做一次矩阵乘的时序推演,你就能看清数据是怎么“脉动”的。假设我们要算一个4×4矩阵A乘以4×4矩阵B,权重B固定在PE里,A从左侧流入。

  • 第1个周期:A的第0行第0列元素进入最左侧PE,与固定权重相乘,产生第一个部分和。
  • 第2个周期:A的第0行第1列元素进入,同时上一个部分和向右/向下传递,与新的乘积累加。
  • 以此类推,A的每一行元素像波浪一样斜着穿过阵列,部分和沿着对角线方向累积。

整个计算完成需要的周期数大约是“阵列维度 + 矩阵维度 - 1”。对于大矩阵,这个启动开销(pipeline fill)可以忽略;但对于小矩阵或者逐层维度差异很大的网络,启动开销占比就会变得可观。这一点后面讲踩坑时会重点说。

3. 为什么AI芯片偏爱脉动阵列:三个绕不开的理由

3.1 数据复用率:把带宽压力从内存转移到阵列内部

AI推理和训练里,超过90%的运算量集中在矩阵乘和卷积上。这类运算的特点是:权重的数据量相对固定,而输入激活的数据量随batch和feature map变化。脉动阵列通过让权重驻留、输入流动,把权重的复用做到了极致。一个256×256的阵列,一次权重加载可以支撑256次复用(取决于数据流方向),这意味着权重存储的访问次数被压缩了两个数量级。

我做过一个粗略的估算:假设一个卷积层有100万个权重,输入激活是1000万个数据。如果每个MAC独立取数,权重和激活都要反复从DRAM读,带宽需求轻松上到TB/s级别,这在移动端根本不可能。而用脉动阵列,权重只在加载时读一次,激活在阵列内复用,实际DRAM带宽需求能降到几十GB/s的量级。这个差距就是脉动阵列存在的根本理由。

3.2 能效比:减少访存就是减少功耗

在芯片功耗构成里,数据搬运的功耗往往比计算本身还高。有研究数据表明,在先进工艺下,一次32位DRAM访问的能耗大约是一次32位乘加运算的几十到上百倍。也就是说,省一次访存比省一次计算划算得多。脉动阵列把大量数据搬运限制在PE之间的短距离互连上,这些短互连的电容小、驱动功耗低,整体能效比就上去了。

这也是为什么很多NPU在宣传时强调“TOPS/W”而不是单纯的TOPS。算力堆上去不难,难的是在有限功耗下把算力真正用起来。脉动阵列在这方面天然有优势,因为它从结构上就减少了长距离、高功耗的数据搬运。

3.3 规整性:对后端物理设计友好

从芯片实现角度看,脉动阵列的PE是高度重复的单元,排列成规则网格,互连也是局部、规则的。这种规整性对后端布局布线非常友好:时钟树容易平衡,电源网格好设计,信号完整性可控。相比之下,如果做一堆不规则的计算单元加复杂的交叉开关,物理实现的难度和面积开销都会飙升。对于要快速迭代、控制成本的AI芯片来说,规整性带来的工程便利是实打实的。

4. 脉动阵列不是万能药:那些设计时必须面对的取舍

4.1 阵列维度定死之后,小矩阵怎么办

脉动阵列最大的尴尬在于:硬件阵列的维度是固定的,比如128×128。但实际网络里,矩阵的维度千变万化。遇到一个大矩阵,可以切成多个128×128的块,效率很高;但遇到一个维度只有16的小矩阵,128×128的阵列大部分PE就闲置了,利用率可能掉到百分之十几。

我见过不少加速器在跑某些轻量级网络或者网络的最后几层(全连接层维度小)时,实测利用率惨不忍睹。解决办法通常有两种:一是做多阵列分区,把小矩阵分配到子阵列上并行;二是做数据重排,把多个小矩阵拼成一个大矩阵。前者增加控制复杂度,后者增加数据准备开销。没有银弹,只能根据目标网络的特点去权衡。

4.2 数据流方向决定了谁被复用,选错了就白干

脉动阵列有输出固定、权重固定、行固定等多种数据流。选哪种,取决于你的网络里什么数据复用机会最多。卷积层里权重复用高,选权重固定;但如果是全连接层或者注意力机制里的某些运算,激活的复用模式可能不同。如果数据流选错,本该被复用的数据反而要反复加载,阵列利用率再高也救不回来。

这里有个经验:不要指望一种数据流打天下。现在很多NPU支持可配置的数据流,根据算子类型动态切换。代价是控制逻辑变复杂,PE里需要更多的寄存器和多路选择器,面积和功耗都会涨。这个取舍要在架构定义阶段就想清楚。

4.3 启动开销和排空开销:流水线不是免费的

脉动阵列本质是一条深度流水线。流水线有填充(fill)和排空(drain)阶段,这两个阶段PE是没在做有效计算的。对于大矩阵,填充排空占比小;但对于大量小算子串联的网络,每个算子都要重新填充排空,累积起来的开销很可观。

我实测过一个极端情况:某网络里有几十个维度很小的逐元素运算,如果每个都走脉动阵列,光填充排空就吃掉了将近30%的周期。后来改成把这些小算子融合成一个大算子,或者用旁路的向量单元处理,效率才回来。所以架构设计时,一定要给非矩阵类运算留一条高效的旁路通道,别什么都往脉动阵列上塞。

5. 从纸面到硅片:脉动阵列的实现细节与踩坑记录

5.1 PE的内部结构:比你想的要简单,但细节要命

一个典型的PE内部其实很简单:一个乘法器、一个加法器、几个寄存器,加上用于传递数据的多路选择器。但就是这几个寄存器怎么摆、数据怎么打拍,决定了整个阵列能不能跑到目标频率。

我踩过的一个坑是:早期版本里PE之间的数据传递没有做足够的寄存器打拍,导致关键路径太长,时序跑不到目标频率。后来在PE之间插入流水寄存器,频率上去了,但延迟也增加了,填充排空开销变大。这个平衡点需要反复迭代。经验做法是:先保证功能正确,再用综合报告去定位关键路径,逐步插入流水级,每插一级都重新评估延迟和频率的收益。

5.2 权重加载通路:别让它成为新的瓶颈

权重固定意味着权重需要预先加载到每个PE的寄存器里。如果加载通路设计得不好,加载一次权重的时间可能比计算本身还长。我见过一个设计,权重加载走的是慢速串行通路,结果每次切换网络层都要等很久,整体吞吐被拖垮。

优化方向有几个:一是做权重加载的并行化,多路同时写入;二是做权重预取,在上一层还在计算时就把下一层的权重准备好;三是如果权重能压缩,先解压再加载,减少加载数据量。这几个手段通常要组合使用。

5.3 部分和的精度与溢出:一个容易被忽视的坑

脉动阵列里,部分和会沿着阵列不断累积。如果累加位宽不够,中间结果就会溢出,导致最终结果错误。这个问题在定点实现里尤其突出。我见过一个团队为了省面积,把累加器位宽压得很紧,结果在某些输入分布下精度崩了,只能回片重做。

稳妥的做法是:累加器位宽要留足余量,通常比输入位宽宽不少。比如输入是8位定点,累加器至少给到24位甚至32位。如果实在要省,可以做饱和处理或者分段累加,但验证工作量和风险都会增加。这个钱不能省。

5.4 验证策略:怎么确认阵列真的算对了

脉动阵列的验证比普通计算单元麻烦,因为数据是流动的,时序相关性强。我的做法是分三层验证:第一层,用行为级模型跑随机矩阵,跟黄金参考对比;第二层,在RTL级做带时序的仿真,重点检查边界情况,比如矩阵维度不是阵列维度的整数倍时怎么处理;第三层,上FPGA原型跑真实网络,看端到端精度。

特别要提醒的是边界情况:当矩阵维度小于阵列维度时,多余的PE怎么处理?是输入补零还是直接旁路?补零会浪费计算周期,旁路会增加控制复杂度。这个决策要在架构阶段定好,并且验证要覆盖到。

6. 脉动阵列之外:它和别的加速结构的对比与配合

6.1 和向量单元、SIMD阵列的分工

脉动阵列擅长的是规整的大矩阵乘,但网络里还有大量非矩阵运算:激活函数、归一化、逐元素乘加、池化等。这些运算用脉动阵列做效率很低,通常需要配一个向量单元或者SIMD阵列来处理。两者分工明确:矩阵类走脉动阵列,向量类走向量单元,中间通过片上缓存交换数据。

这个异构架构的设计难点在于任务调度和数据搬运。如果调度不好,脉动阵列和向量单元会互相等,整体利用率都上不去。我的经验是:尽量让两类运算在时间上重叠,比如脉动阵列算当前层时,向量单元处理上一层的后处理,通过双缓冲隐藏搬运延迟。

6.2 和存内计算、近存计算的关系

最近几年存内计算很热,思路是把计算单元放进存储阵列里,进一步减少数据搬运。脉动阵列和存内计算不是替代关系,而是可以结合的。比如把脉动阵列的PE和SRAM bitcell做在一起,让权重直接存在计算单元旁边,省掉权重加载的通路。这个方向学术界和工业界都在探索,但目前成熟度还不如传统脉动阵列,工程落地还有距离。

6.3 什么场景下不该用脉动阵列

说句实在话,脉动阵列不是所有AI负载的最优解。如果你的目标网络以稀疏运算为主,或者矩阵维度普遍很小且不规则,脉动阵列的利用率会很差,这时候可能稀疏加速器或者可重构阵列更合适。另外,如果芯片面积和功耗预算极其紧张,堆不起大阵列,那还不如用小的向量单元加高效缓存。架构选型一定要从实际负载出发,别因为“别人都用脉动阵列”就盲目跟。

7. 给想动手实现的人的几点实操建议

如果你打算自己做一个脉动阵列的原型,不管是FPGA验证还是ASIC流片,我有几个从实际项目里总结的建议。

第一,先用高级语言或者行为级模型把数据流跑通,确认矩阵乘的结果正确,再动手写RTL。直接写RTL调时序和功能一起抓,效率极低。我通常用Python或者C++写一个周期精确的模型,把每个周期的数据流动都打印出来,对着波形图核对。

第二,阵列维度不要一上来就贪大。先做8×8或者16×16的小阵列,把数据流、控制逻辑、边界处理都验证清楚,再往上扩。大阵列的问题往往在小阵列阶段就能暴露,早发现早解决。

第三,重视片上缓存的带宽匹配。脉动阵列再能复用数据,也得有人给它供数。如果片上缓存带宽不够,阵列照样饿着。设计时要算清楚:阵列每个周期需要多少数据,缓存能不能供上,供不上就要加宽或者加多级缓存。

第四,仿真激励要覆盖真实网络的维度分布。别只用方方正正的大矩阵测,要拿目标网络每一层的真实维度去跑,看看利用率曲线长什么样。很多问题只有在真实维度分布下才会暴露。

第五,功耗和面积的评估要趁早。脉动阵列的PE数量直接决定面积和功耗,而PE数量又取决于目标算力。这个账要在项目初期就算清楚,别做到一半发现面积超了再砍阵列,那时候改动成本极高。

脉动阵列这个结构,说穿了就是把“数据复用”这件事做到极致的一种工程手段。它不神秘,但细节极多,每一个寄存器的位置、每一条通路的位宽、每一个控制信号的时序,都可能影响最终的效率和正确性。我自己在这个方向上踩过的坑,远比这篇内容里写出来的多。如果你也在做类似的事情,希望这些经验能帮你少走点弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 14:30:42

impeccable用法全解析:从词根到场景,告别翻译腔

这个单词我盯了很久:impeccable。词典里翻来覆去就那几句,"无可挑剔的""无懈可击的",但真到了写邮件、发简历、跟客户沟通的时候,十个人里有九个用不对。要么把它跟"perfect"混为一谈,要…

作者头像 李华
网站建设 2026/10/28 14:29:08

Caveman数字极简指南:离线优先与注意力管理的三个月实践

1. Caveman 是什么:我为什么把自己活成穴居人如果你每天解锁手机八十多次,却想不起来上一次完整读完一篇文章是什么时候,那 Caveman 这套玩法或许值得你看看。Caveman 是我给自己一个“低科技生活实验”起的代号,听起来像是要搬进…

作者头像 李华
网站建设 2026/10/28 14:28:24

impeccable用法详解:与perfect、flawless的区别及地道搭配

1. 说白了:拆解“impeccable”的本义和词源1.1 词典定义之外的隐性含义很多人第一次见到“impeccable”这个词,是在雅思作文或职场邮件的模板里。词典给的解释很简单:完美的、无可挑剔的、无懈可击的。但如果你只是在写作时把它当成“perfect…

作者头像 李华
网站建设 2026/10/28 14:28:16

AI编码代理上下文压缩恢复实验:long_mem与engram记忆机制

1. 这个实验到底在折腾什么先把这个标题拆开看。上下文压缩,指的是 AI 编码代理在长会话里,因为上下文窗口有限,不得不把历史对话、代码片段、工具调用记录做摘要或截断,腾出空间给新内容。AI 编码代理,就是像 Codex 这…

作者头像 李华
网站建设 2026/10/28 14:27:46

邓宁-克鲁格效应与技术认知四阶段:工程识别与成长路径

1. 先把这个被用烂的概念拆开看带过团队的人大概都有过这种体验:一个刚上手三个月的同事,在评审会上对着一套跑了五年的老架构说“这个设计太啰嗦了,我两天能重写一版”;而真正把系统从零扛过三次大促的老手,反而在会议…

作者头像 李华
网站建设 2026/10/28 14:26:56

无人艇编队协同控制:反步法与神经网络补偿技术解析

1. 项目背景与核心挑战水面无人艇(USV)的编队协同控制在海洋勘探、水域监测等领域具有重要应用价值。这个项目针对欠驱动USV编队控制中的三个核心难题展开:欠驱动特性:大多数USV只有推进器和方向舵两个控制输入,却需要…

作者头像 李华