try ai
科普
编辑
分享
反馈
  • 脉动阵列

脉动阵列

SciencePedia玻尔百科
核心要点
  • 脉动阵列是一种并行计算架构,它通过在一个简单的处理单元网格中节律性地泵送数据来解决内存瓶颈问题。
  • 它被归类为单指令多数据(SIMD)架构,通过让所有处理器对不同的数据流执行相同的指令来实现大规模并行。
  • 该架构的设计强调数据重用,即单个数据元素在流经阵列时被用于多次计算,从而极大地提高了算术强度和效率。
  • 脉动阵列对于具有规则、重复计算的应用非常有效,例如人工智能中的矩阵乘法、数字信号处理(DSP)中的卷积以及生物信息学中的序列比对。

引言

在追求更强计算能力的道路上,现代计算面临着一个根本性障碍:“内存瓶颈”,即强大的处理器在等待数据时处于空闲状态。传统的冯·诺伊曼架构以其中心化的处理单元,日益受到数据密集型任务需求的压力。本文探讨了一种革命性的解决方案:脉动阵列,一种其灵感源于人类心脏节律性搏动的并行处理架构。脉动阵列并非使用单一的强大处理器,而是利用一个由简单的、同步的处理单元组成的网格,数据在其中流动,从而实现大规模并行和前所未有的效率。

本文的探讨分为两个主要部分。在“原理与机制”部分,我们将剖析脉动阵列的核心工作方式,从其节律性的数据流和作为 SIMD 机器的分类,到使其如此强大的数据重用和计算波前等概念。我们还将考察硬件利用率和网络拓扑等实际设计挑战。随后,“应用与跨学科联系”部分将揭示这种架构范式如何成为不同领域取得突破的驱动力。我们将看到,作为脉动计算核心的简单“乘累加”模式,如何为现代人工智能、数字信号处理、基因组分析和机器人学提供动力,同时我们也将理解该架构不适用于哪些类型的问题。

原理与机制

想象一下,要建造一台能进行巨量计算的机器,比如两个巨大矩阵的相乘。由 John von Neumann 开创的传统方法是,拥有一个强大的中心处理器——一个卓越的“大脑”——它从一个巨大的图书馆(内存)中获取数据,执行计算,然后将结果写回。这种方法效果很好,但当任务巨大时,我们卓越的“大脑”大部分时间都在等待从图书馆送来的书籍。这个“内存瓶颈”是现代计算中最大的限制因素之一。

脉动阵列提出了一个截然不同且异常优美的解决方案。与其拥有一个卓越的大脑,为何不拥有一支由简单的、同步的工人组成的军队?与其让他们在图书馆来回奔波,为何不让数据在传送带上流过他们?这就是核心思想。该架构以心脏的收縮期(systole)命名,即推动血液流遍全身的节律性收缩。在脉动阵列中,被节律性地泵送通过一个简单处理单元(PE)网格的是数据。

机器的心脏:数据的节律性脉冲

让我们把这个概念具体化。想象一条由工人组成的一维装配线,这些工人就是我们的处理单元(PE)。每个工人的工作都非常简单。在常见的数字信号处理(DSP)任务中,如实现有限脉冲响应(FIR)滤波器,工作可能是从左边的工人那里获取一个输入值,将其与自己工位上存储的权重相乘,将该乘积与从右边传递过来的值相加,然后将最终的和传递给左边的工人。输入信号本身也沿着这条线从左向右移动,每次一个工人,伴随着全局时钟的每一次滴答。

这正是在数字电路 **** 中建模的场景。在线性阵列中的每个 PE 在每个时钟周期执行两个并发操作:一个输入数据值 XinX_{\text{in}}Xin​ 被传递给下一个 PE,成为 XoutX_{\text{out}}Xout​,同时一个累加和 YinY_{\text{in}}Yin​ 通过 XinX_{\text{in}}Xin​ 与 PE 的本地静态权重 WWW 的乘积进行更新。新的和成为输出 YoutY_{\text{out}}Yout​。该操作由以下寄存器传输定义:

  1. Xout←XinX_{\text{out}} \leftarrow X_{\text{in}}Xout​←Xin​
  2. Yout←Yin+(Xin×W)Y_{\text{out}} \leftarrow Y_{\text{in}} + (X_{\text{in}} \times W)Yout​←Yin​+(Xin​×W)

如果将这些 PE 串联起来,一个输入信号 X(k)X(k)X(k) 进入第一个 PE 后,会沿着阵列“行进”,每个时钟周期前进一个 PE。在每一步中,它都会对一个部分和做出贡献,这个部分和也沿着阵列行进,但在行进过程中不断累积结果。当到达最后一个 PE 时,它已经累积了多个时间延迟输入的加权和——这正是一个 FIR 滤波器所做的工作。数据在流动,计算是局部的、重复的,整个结构以完美的、节律性的锁步方式运行。这就是脉动作用:简单、局部且极其高效。

простых тружеников армия: мощь SIMD

我们应该如何对这台奇特而美妙的机器进行分类?计算机架构师有一个有用的分类系统,称为​​弗林分类法​​(Flynn's Taxonomy),它根据指令流和数据流对并行计算机进行分类。一次对一个数据执行一条指令的传统CPU是​​单指令单数据(SISD)​​。一个大型超级计算机,其中许多处理器在各自的数据上运行各自的程序,是​​多指令多数据(MIMD)​​。

脉动阵列属于哪一类呢?让我们考虑一个用于矩阵乘法的二维阵列,如 ​​ 中所述。它是一个由相同的 PE 组成的网格。一个单一的控制单元向阵列中的每一个 PE 广播相同的命令——例如,“执行乘累加”。它们全部同步执行这个命令。这正是​​单指令流的定义。

然而,每个 PE 操作的数据是不同的。在任何给定时刻,位置 (i,j)(i, j)(i,j) 的 PE 可能正在将元素 ai,ka_{i,k}ai,k​ 与 bk,jb_{k,j}bk,j​ 相乘,而其相邻的 (i,j+1)(i, j+1)(i,j+1) 位置的 PE 则在处理一对完全不同的数据元素。来自输入矩阵的数据流跨行和列流动,确保每个 PE 随时间推移接收到唯一的运算对象序列。因此,我们有​​多数据​​流。

综上所述,脉动阵列是​​单指令多数据(SIMD)​​架构的典型例子。它不是一群独立的思考者;它是一支纪律严明的简单工人军队,都在执行相同的任务,但处理的是流向它们的不同问题片段。这种专门化是它的优势,它牺牲了通用性以换取在特定任务上的大规模并行能力。

计算的形状:波前与效率

当你启动一个脉动阵列时,它不会立即以满负荷运行。计算像波浪一样在 PE 网格中传播,从数据首次进入的地方开始。这被称为​​计算波前​​。这个波浪到达最远的 PE 并使其开始有效工作所需的时间称为​​流水线填充时间​​。对于一个方形的 P×PP \times PP×P 阵列,这个初始设置需要 2P−22P-22P−2 个周期。类似地,一旦最后的输入进入阵列,最后的 PE 完成最终结果并将其“排空”也需要时间。这个​​流水线排空时间​​通常也是 2P−22P-22P−2 个周期 ****。

计算一个大小为 P×PP \times PP×P 且内维度为 KtK_tKt​ 的数据瓦片所需的总时间不仅仅是 KtK_tKt​ 个周期;它更接近于 Kt+2P−2K_t + 2P - 2Kt​+2P−2 个周期,这考虑了填充和排空的开销 ****。这意味着在整个计算期间,并非所有的 PE 都在做有效工作。在开始和结束时,许多 PE 是空闲的。这种不可避免的低效率是阵列空间特性的结果。

这就引出了一个至关重要的实际问题:当问题规模与硬件规模不完全匹配时会发生什么?想象一下,你需要将两个 192×192192 \times 192192×192 的矩阵相乘,但你的脉动阵列是一个固定的 128×128128 \times 128128×128 网格。你必须将问题分解成更小的瓦片。其中一些瓦片将是完整的 128×128128 \times 128128×128 块,但在边缘处,你会有部分瓦片,可能是 64×12864 \times 12864×128 或 64×6464 \times 6464×64。当硬件处理一个部分瓦片时,落在活动区域之外的 PE 不做任何有效工作,但整个阵列在该瓦片计算的整个期间仍然保持时钟同步。

这种效应直接影响硬件的整体效率或​​利用率​​。利用率可以表示为真实工作区域与“付费的”填充区域之比。对于一个 r×cr \times cr×c 的问题在一个 m×nm \times nm×n 的阵列上,利用率由一个优雅的公式给出:

U=rcmn⌈rm⌉⌈cn⌉U = \frac{rc}{mn \left\lceil \frac{r}{m} \right\rceil \left\lceil \frac{c}{n} \right\rceil}U=mn⌈mr​⌉⌈nc​⌉rc​

这个来自 **** 的表达式优美地捕捉了这种不匹配造成的效率损失。它告诉我们,一个加速器的有效性能不仅取决于其峰值速度,还取决于问题的形状与硬件形状的匹配程度。

杂耍的艺术:数据重用与攻克内存墙

所有这些架构努力的主要原因是为了攻克​​内存墙​​——处理器速度与内存速度之间日益扩大的鸿沟。脉动阵列的设计是最小化数据移动的典范。

关键原则是​​数据重用​​。在许多算法中,如矩阵乘法或卷积,一个单一的输入值需要用于许多不同的输出计算。传统处理器必须一次又一次地从内存中获取这个值。相比之下,脉动阵列只需从主存中获取该值一次。然后,它沿着一行或一列从一个 PE 传递到另一个 PE,在每一步都参与一次新的计算。PE 之间的片上连接成为数据重用的主要机制,几乎完全消除了冗余且昂贵的片外内存访问 ****。

这种节律性的流动还带来了另一个深远的优势:​​性能确定性​​。传统的处理器,如 DSP,通常依赖缓存来隐藏内存延迟。但如果数据不在缓存中(缓存未命中),处理器必须停顿多个周期,等待从主存中获取数据。由于缓存未命中可能是不可预测的,性能变得可变且不确定 ****。然而,脉动阵列被设计为由稳定、可预测的数据流供给。一旦初始流水线被填满,它的性能就是恒定且完全可预测的,只取决于阵列的大小和时钟频率,而不是内存访问模式的变幻莫测。这对于实时应用和系统分析来说是一个巨大的好处。

当然,这种稳定的数据流不会凭空出现。在一个真实的片上系统(SoC)中,这是通过精心的编排实现的。大问题被分解成可以放入高速片上内存(如 FPGA 上的 BRAM)的​​瓦片​​。当脉动阵列忙于计算瓦片 N 的数据时,一个直接内存访问(DMA)引擎在后台工作,就像一个不知疲倦的舞台工作人员。它从慢速的片外 DRAM 中获取下一个瓦片(瓦片 N+1)的数据,同时将上一个瓦片(瓦片 N-1)的结果写回 DRAM。这种被称为​​双缓冲​​的技术,将漫长的内存访问延迟隐藏在计算时间之后 ****。系统的整体速度于是受限于两个任务中较慢的一个:计算或数据传输。

这揭示了硬件设计的复杂舞蹈。你可以构建的阵列大小(S×SS \times SS×S)受到你所能承受的总芯片​​面积​​和​​功耗​​预算的限制 ​​。你可以处理的瓦片大小受限于你拥有的高速​​片上内存​​的数量。而你处理瓦片的速率则受限于到外部内存的​​带宽​​ ​​。设计一个脉动阵列加速器是一门平衡所有这些物理和架构约束的艺术,旨在创造出一台既强大又“喂得饱”的机器。

单元之间的道路:更深入的观察

我们已经将 PE 想象成一个简单的网格。但如果我们将每行和每列的最后一个 PE 连接回第一个,形成一个​​环面​​(torus)呢?这可以缩短数据需要传输的平均距离。然而,这种优雅的环绕连接引入了一个微妙而危险的新问题:​​死锁​​。

想象一条环形道路,交通拥堵到每辆车都在等待前面的车移动。没有车能动,系统陷入僵局。同样的情况也可能发生在环面网络中。如果连接 PE 的通道中的缓冲区都满了,就可能形成一个依赖循环,其中每个数据包都在等待一个被循环中下一个数据包占用的缓冲区 ****。

解决这个问题的方法和问题本身一样优雅而微妙。一种常用的技术是使用​​虚拟通道​​。可以把它想象成在我们的环形道路上增加一条平行的车道。然后我们建立一个规则:你在大部分旅程中必须在0号车道行驶,但如果你越过一个特定的指定点——一条“数据线”——你必须切换到1号车道,并且禁止切换回来。这个简单的规则使得在同一车道上完成一个完整的循环成为不可能。它打破了资源图中的循环依赖,保证了交通僵局——即死锁——永远不会发生。这使我们能够保留环面拓扑的性能优势,而不会陷入其隐藏的危险。这是一个美丽的例证,说明了来自网络理论的深刻理论概念如何对于构建健壮、高性能的计算硬件至关重要。

应用与跨学科联系

所以,我们有了脉动阵列这个奇妙的想法——一台优美、富有节律的机器,数据像心跳一样在一系列处理器中搏动。我们已经探讨了使其运转的原理、其局部通信的优雅简洁性,以及它所释放的巨大并行性。但是,任何科学思想最激动人心的部分不仅仅是其内在的美,而是当它与现实世界相遇时会发生什么。这台机器擅长什么?这种计算的节律性脉搏在我们想要解决的各种问题中,在哪里找到了它的节奏?

你可能会感到惊讶。事实证明,脉动阵列表现出色的简单、重复的“乘法和累加”模式,并非某种晦涩的数学奇观。实际上,它是计算的基本旋律之一,出现在各种令人眼花繚亂的领域中。让我们踏上一段旅程,看看这个优雅的架构出现在何处,从我们计算机的人工智能大脑到生命本身的代码。

人工智能的心跳

如果说有一个领域被脉动阵列彻底改变,那就是人工智能。现代神经网络,特别是那些能够“看”和“听”的网络,是建立在两个关键运算基础上的庞大结构:矩阵乘法和卷积。而事实证明,这些运算与脉动数据流完美匹配。

为什么?秘密在于一个我们可以称之为算術強度的概念——这是一个花哨的术语,代表一个简单而深刻的想法:对于你从遥远、缓慢的主存世界中获取的每一片数据,你能完成多少有用的工作?一种天真的方法,比如说进行卷积,可能涉及处理器获取一小块图像和一组滤波器权重,将它们相乘,然后……扔掉它们,再去获取下一块图像和权重。这是极其浪费的!这就像一个木匠为每一颗钉子都跑一趟木材厂。处理器大部分时间都在等待数据,而不是计算。

脉动阵列彻底改变了这一点。想象一个图像瓦片从阵列的一侧流入,而神经网络的权重从另一侧流入。当一个数据片段进入一个处理单元(PE)时,它被用于一次计算。但它不会被丢弃,而是被传递给它的邻居。那个邻居用它进行自己的计算,然后再传递下去。一个只从内存中获取一次的数据元素,在它穿越阵列的过程中被一次又一次地重用。结果是算术強度的惊人提升。处理器保持持续繁忙,对它们最初从内存请求的每个字节执行数百次操作。这正是诸如谷歌的张量处理单元(TPU)等架构能够在 AI 工作负载上实现令人难以置信的性能,将更通用的处理器远远甩在身后的原理。

这也不仅仅是针对简单卷积的一个小技巧。人工智能的世界里充斥着种类日益增多的运算。考虑像*深度可分离卷积*这样的东西,这是一种在移动和边缘 AI 模型中常见的更高效的层类型。它将问题分解为两个不同的步骤。你如何将这个映射到一个刚性的处理器阵列上?在这里,架构设计的艺术就发挥作用了。你应该使用一个长的一维阵列还是一个方形的二维阵列?事实证明,这个选择对于数据如何被重用以及需要多少片上内存来存储中间结果有着深远的影响。一种布局可能对第一步非常出色,但对第二步很笨拙,而另一种则提供了更好的平衡。为这些任务设计一个领域特定架构(DSA)是在算法的数据流和硬件的拓扑结构之间进行的一场微妙的舞蹈,一个在每一步都力求最小化数据移动的谜题。

自然与工程的节律

但是,如果认为脉动阵列只适用于 AI,那就错了。同样的计算模式在科学和工程的许多其他角落里回响。

想想数字信号处理(DSP),我们数字化的音频和通信世界的基础。一个有限脉冲响应(FIR)滤波器,用于从清理嘈杂的音频到塑造无线电信号的各种应用,本质上是一个滑动的点积——正是那个“乘法和累加”的模式。因此,脉动阵列能够以惊人的效率执行 FIR 滤波器也就不足为奇了。当我们将一个滤波器映射到这个架构上时,我们看到了同样的原理在起作用:输入信号流跨越阵列,与存储在每个处理器中的静止滤波器系数相互作用。这种联系也迫使我们思考计算的实际问题,例如不同数字格式之间的权衡,比如 DSP 传统的定点运算与 AI 中使用的更奇特的 [bfloat16](/sciencepedia/feynman/keyword/bfloat16) 格式,以及这些选择如何影响我们结果的最终精度。

让我们从电子世界转向生物世界。科学家如何比较 DNA 序列以寻找可能指示进化关系或遗传疾病的相似之处?最有力的工具之一是 Smith-Waterman 算法,一种来自动态规划世界的方法。它涉及到填写一个大网格,其中每个单元格的值取决于其邻居。如果你仔细观察依赖关系,你会注意到一些奇妙的事情:沿着任何给定的反对角线的所有单元格都可以同时计算!它们不相互依赖。这就创造了一个可以扫过整個网格的计算“波前”。

什么样的硬件最适合这个?一个一维脉动阵列!你可以将每个处理器分配给波前上的一个单元格。在第一个周期,一个处理器工作。在下一个周期,两个处理器工作。活动波逐渐增长,扫过网格,然后收缩,看起来就像一个扩张和收缩的涟漪。这种算法到架构的完美映射使脉動陣列成为高速生物信息学和基因组分析的基石。

或者考虑机器人世界。一个在空间中导航的机器人,一架飞行的无人机,或者一辆自动驾驶汽车,需要不断地确定自己的位置。它通过融合来自各种传感器——摄像头、GPS、惯性传感器——的数据来做到这一点,使用的是一种称为卡尔曼滤波器的算法。该滤波器的核心是一系列矩阵运算,包括矩阵求逆这个关键步骤。正如我们所见,脉動陣列擅长结构化的矩阵代数。但并非所有算法都是生而平等的。试图用像高斯-若尔当消元法这样的经典方法来解决这个系统是一个糟糕的选择;它需要在整个阵列上广播数据行,打破了“仅局部通信”的规则,并造成了瓶颈。然而,一种更复杂的方法,如 Cholesky 分解,适用于这个问题中出现的特殊对称矩阵,可以分解为一系列三角求解,这些求解可以完美地映射到一个仅有最近邻通信的脉动阵列上。算法和架构的选择是紧密交织的,正确的配对可能意味着一个能够实时反应的机器人和一个不能的机器人之间的区别。

不匹配的艺术:当节奏被打破

现在,科学中一个非常重要的教训是,没有任何思想,無論多么聪明,能够解决所有问题。我们也必须问:脉动阵列不擅长什么?答案告诉我们一些关于算法本质的深刻道理。

考虑一下快速傅里叶变换(FFT),这是有史以来最重要的算法之一。它无处不在,从信号处理到图像压缩。它非常快,但它有一个奇特的通信模式。为了计算 FFT,你需要组合输入数组中相距很远的数据点。该算法具有一种“全局”性质。

如果你试图将它映射到一个一维脉动阵列上,处理器只能与它们的直接邻居通信,会发生什么?这是一场灾难。为了将一个数据点从阵列的一端传到另一端,它必须一步一步地通过中间的每一个处理器。通信成本,即仅仅用于移动数据的时间,变得极其高昂,完全超过了实际计算所花费的时间。一维阵列上通信的渐近成本增长为 Θ(n2)\Theta(n^2)Θ(n2),而计算仅为 Θ(nlog⁡n)\Theta(n \log n)Θ(nlogn)。这是一个可怕的不匹配。这就像试图通过在拥挤的体育场里传递一张纸条来 across 进行对话。脉动的节奏被打破了。这教会了我们一个至关重要的教训:并行架构的效率取决于其通信拓扑与算法通信图的匹配程度。

脉动思维:一种通用范式

所以我们看到,脉动阵列是一个特定的硬件,一个领域特定架构,它对于某些问题非常出色,而对于其他问题则不适合。但故事就到此为止了吗?完全不是。

也许最深刻的联系是:我们可以将物理的脉动阵列的想法与更普遍的脉动思维原则分离开来。如果你没有一个特殊的加速器芯片怎么办?如果你只有一个常规的多核处理器,带有一个由网络连接的通用核心网格呢?你仍然可以应用脉动思维!

你可以划分你的问题,比如一个大型卷积,将其划分为瓦片,并为每个核心分配一个瓦片。每个核心计算自己的区域,然后将边界数据——“光环”(halo)——与它的邻居通信,就像硬件阵列中的 PE 一样。这种数据流模仿了脉动计算。当然,它不会那么高效。通信是通过通用网络上的软件消息来处理的,其延迟更高,带宽更低,远不如定制芯片中的专用线路。这种通信的开销是显著的。但原则是相同的:组织计算以最大化局部数据重用,并创造一个规则的、有节奏的信息流。

最终,这揭示了脉动概念的真正力量和美丽。它不仅仅是硅片的巧妙排列。它是并行计算的一个基本范式。它教我们不仅要思考操作本身,还要思考数据在机器中的流动。它提醒我们,在高性能计算的世界里,你能做的最昂贵的事情不是将两个数字相乘,而是将一个数字从一个地方移动到另一个地方。通过最小化这种移动,通过让数据持续运动并持续工作,脉动的搏动为众多问题带来了深刻的效率,将人工智能、信号处理、生物信息学和机器人学的世界统一在一个简单而强大的节奏之下。