ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从HotChips看数据流架构:AI芯片设计的新范式与工程实践

从HotChips看数据流架构:AI芯片设计的新范式与工程实践

1. 从HotChips现场聊起:为什么数据流架构突然成了香饽饽

今年HotChips的议程一出来,我朋友圈里做芯片的几拨人反应截然不同。做GPU的照例在刷参数,做存算一体的在转 keynote 截图,而几个从大厂出来做AI加速器的老朋友,几乎同时给我发了同一句话:数据流架构这回是真的被推到台前了。我盯着议程表看了半天,最大的感受不是某一颗芯片有多炸裂,而是整个行业讨论AI芯片的坐标系变了——以前大家比的是峰值算力、比的是制程节点,现在越来越多的人开始问一个更本质的问题:数据在芯片里到底是怎么流动的,流动的效率是不是被架构本身卡住了。

这个问题听起来有点抽象,但落到实际场景里非常具体。你训练一个大模型,或者跑一个推理服务,真正拖后腿的往往不是乘加单元不够多,而是数据在存储和计算单元之间来回搬运消耗了太多时间和能量。业内有个被反复引用的经验数字:在典型的深度学习负载里,数据搬运的能耗可能比计算本身高出一到两个数量级。也就是说,你辛辛苦苦把算力堆上去,结果大部分功耗和延迟都花在了“搬数据”这件事上。数据流架构之所以在HotChips上被反复提及,本质上就是因为它试图从根子上改变这个局面——让计算跟着数据走,而不是让数据追着计算跑。

我写这篇东西,不是要复述HotChips的议程,而是想把我这些年看架构、做选型、踩过的一些坑,结合这届HotChips释放出来的信号,系统地聊一聊数据流架构到底是怎么回事。如果你是在做AI芯片架构评估的工程师,或者是在选推理/训练硬件的算法团队负责人,再或者只是对下一代算力形态好奇的技术爱好者,我希望这篇内容能帮你建立一个判断框架,而不是停留在“数据流听起来很先进”这种模糊印象上。接下来我会从架构思路、核心细节、实操落地、问题排查几个层面展开,尽量把“为什么这么设计”讲透。

2. 数据流架构到底在解决什么问题:一次架构思路的彻底拆解

2.1 传统冯诺依曼架构在AI负载下的三个死结

要理解数据流架构,得先看清楚它要对抗的是什么。我们熟悉的GPU、CPU本质上都是冯诺依曼架构的变体,核心特征是“指令流驱动”:控制器按顺序取指令、译码、执行,数据从存储里被搬到计算单元,算完再搬回去。这套机制通用性极强,但在AI负载面前暴露了三个死结。

第一个死结是访存墙。AI计算尤其是矩阵乘法,本质上是高度规则的数据复用,但冯诺依曼架构下,每次计算都要显式地从寄存器堆或共享内存里取操作数。GPU靠庞大的线程并行和层次化缓存来掩盖延迟,可一旦模型规模超过缓存容量,数据就得反复从HBM甚至更远的存储层级搬运,带宽和功耗立刻成为瓶颈。

第二个死结是控制开销。指令流的取指、译码、调度本身要消耗能量和面积。对于乘加这种简单操作,控制逻辑的占比高得离谱。有研究统计过,在某些通用处理器上,执行一条乘加指令,真正用于计算的能量可能不到总能量的百分之几,其余全花在了指令搬运和数据搬运上。

第三个死结是并行度与数据依赖的矛盾。AI模型里有大量可以并行的操作,但也有不少存在严格的数据依赖。指令流架构靠乱序执行、靠编译器调度来挖掘并行,可当依赖关系复杂到一定程度,调度器的复杂度和收益就不成正比了。这三个死结叠加在一起,就是为什么大家一边把GPU越做越大,一边又在拼命寻找新架构的根本原因。

2.2 数据流架构的核心思想:让计算就位,等数据上门

数据流架构的思路用一句话概括就是:计算单元不再被动等待指令,而是当它需要的所有输入数据都到齐时,自动触发计算。这听起来简单,但它把“控制”从指令流转移到了数据本身。在数据流架构里,没有全局的程序计数器,没有统一的取指译码,每个计算节点只关心一件事——我的输入操作数齐了没有,齐了就干活,干完把结果往下游送。

这个转变带来的好处是连锁性的。首先,控制开销被极大压缩,因为不需要为每条计算指令单独取指译码,计算节点的控制逻辑可以做得非常轻。其次,数据复用变得自然,一个数据可以被多个下游节点消费,不需要反复从存储里读取。再者,并行度是天然暴露的,只要数据依赖允许,所有就绪的节点可以同时工作,不需要复杂的乱序调度器去猜。

我经常用一个类比来解释:指令流架构像是一个大食堂,所有人排队打饭,厨师按顺序给每个人盛菜,队伍长了就堵;数据流架构更像是一个自助餐流水线,每个工位只负责一道工序,食材到了就加工,加工完传到下一站,工位之间靠传送带自然衔接。哪个效率高,取决于菜品的标准化程度——而AI计算恰恰是标准化程度极高的场景。

2.3 从HotChips看架构演进的三个信号

这届HotChips上,数据流相关的讨论集中在三个方向,我觉得很能说明问题。第一个信号是粗粒度与细粒度的融合。纯细粒度的数据流架构(每个加法器都独立触发)控制复杂度太高,纯粗粒度的又不够灵活,所以现在主流方案是在粗粒度的计算块之间用数据流调度,块内部再用传统的向量化或脉动阵列。这种混合思路在多个演讲里都有体现。

第二个信号是存储与计算的边界模糊化。数据流架构天然适合和存内计算、近存计算结合,因为当计算由数据触发时,把计算单元放到存储旁边就变得顺理成章。HotChips上有几个工作就是在讨论如何在SRAM阵列里嵌入数据流控制逻辑,让读写操作本身就携带计算语义。

第三个信号是编译器与架构的协同设计。数据流架构的性能极度依赖数据图的划分和映射,这就把编译器推到了核心位置。以前编译器主要是做指令调度,现在它要决定哪些计算放在哪个节点、数据怎么路由、缓冲区怎么分配。HotChips上不止一个团队在讲他们的编译器如何与硬件协同,这在前几年是很少见的。

3. 核心细节解析:数据流芯片的关键模块与设计取舍

3.1 计算节点的触发机制:标记令牌与数据依赖解析

数据流架构最核心的机制是触发。一个计算节点什么时候开始工作?答案是当它需要的所有输入令牌都到达时。这里的关键设计是“标记令牌”机制:每个数据包除了携带数值本身,还携带一个标记,标明它属于哪一次计算、对应哪个操作数位置。节点内部有一个匹配单元,负责把不同来源的令牌配对,配对成功就触发计算。

这个机制听起来简单,但实现起来有几个坑。第一个坑是令牌匹配的存储开销。如果依赖关系复杂,匹配单元需要缓存大量未配对的令牌,这部分存储可能比计算单元还大。所以实际设计中,通常会限制节点的输入端口数量,或者用编译期静态调度来减少运行时的匹配压力。第二个坑是死锁风险。如果数据图存在环或者令牌丢失,节点可能永远等不到齐活的输入。解决办法通常是在编译期做数据图的合法性检查,并在硬件里加超时或丢弃机制。

我在评估一个数据流加速器时,会特别关注它的令牌匹配策略。是纯运行时的还是编译期辅助的?匹配队列有多深?这些参数直接决定了架构在真实负载下的有效并行度。HotChips上有个工作提到他们用了一个浅匹配队列配合编译期的静态路由,把匹配开销压到了很低的水平,这个思路我觉得很务实。

3.2 片上网络与数据路由:数据流架构的血管系统

数据流架构里,计算节点之间的通信靠片上网络(NoC)。这个NoC的设计好坏,直接决定了架构能不能把理论并行度转化成实际性能。和传统多核CPU的NoC不同,数据流架构的NoC要处理的是流式数据,特点是数据量大、模式相对规则、但对延迟和吞吐的确定性要求高。

设计NoC时几个关键取舍:拓扑结构上,Mesh适合规则的数据流,但跳数多延迟高;Crossbar延迟低但面积和功耗随节点数平方增长;现在比较流行的是分层拓扑,把计算节点分组,组内用Crossbar,组间用Mesh或Ring。路由策略上,确定性路由实现简单但容易拥塞,自适应路由能绕开热点但需要更复杂的仲裁逻辑。流控机制上, credit-based流控能保证不丢包但需要额外存储,on/off流控简单但可能引起抖动。

我个人的经验是,看一个数据流芯片的NoC设计,不要只看峰值带宽,要看它在实际数据图映射下的有效带宽。有些芯片标称NoC带宽很高,但因为路由策略和计算节点的映射不匹配,实际跑起来只有标称值的三四成。HotChips上有个团队专门讲了他们如何用编译器来指导NoC的路由配置,让数据流的空间局部性和NoC的拓扑对齐,这个思路很值得借鉴。

3.3 存储层次与数据复用:把搬运成本降到最低

数据流架构的一个核心优势是数据复用,但复用不会自动发生,需要存储层次和调度策略的配合。典型的做法是在计算节点附近放小的暂存器或FIFO,用来缓存即将被消费的数据。当多个下游节点需要同一个数据时,这个数据可以从暂存器广播,而不是每个节点都去主存取。

这里的关键参数是暂存器深度和复用距离。暂存器太浅,数据还没被消费完就被覆盖了;太深,面积和功耗浪费。复用距离指的是一个数据从产生到被最后一个消费者使用的间隔,这个距离决定了需要多大的缓冲。在编译期,这些信息可以从数据图里静态分析出来,然后用来配置硬件。我见过一些设计,把暂存器深度做成可配置的,编译器根据数据图特征动态调整,这个灵活性在跑不同模型时很有价值。

还有一个容易被忽视的点是权重数据的处理。在推理场景里,权重是只读的,而且会被大量复用。数据流架构可以把权重预加载到计算节点附近的专用存储里,让它们像“常驻居民”一样待着,只让激活值在NoC里流动。这个思路在HotChips的多个推理芯片方案里都有体现,效果也很明显——权重搬运的能耗被几乎消除了。

3.4 控制与配置接口:数据流不是不要控制,而是换了个位置

很多人误以为数据流架构就是“没有控制”,这是不对的。数据流架构只是把控制从运行时的指令流转移到了编译期的配置和运行时的轻量级状态机。芯片上仍然需要配置接口,用来加载数据图的映射信息、设置路由表、初始化暂存器。这些配置通常在kernel启动前完成,运行过程中很少变动。

这个特点带来一个实际好处:配置开销可以被摊销。如果一个数据图要反复执行很多次(比如推理服务里的固定模型),配置成本几乎可以忽略。但如果数据图频繁切换(比如多模型混跑),配置开销就会显现。所以数据流芯片在固定负载、长时间运行的场景下优势最大,这也是为什么很多数据流方案首先瞄准推理而不是训练。

4. 实操过程:从数据图到芯片映射的完整链路

4.1 第一步:把模型转换成数据流图

数据流架构的实操起点不是写CUDA kernel,而是把模型表达成数据流图。这个过程通常由编译器前端完成,输入是计算图(比如ONNX或PyTorch的FX图),输出是细化的数据流图。关键操作包括算子融合、循环展开和依赖分析。

算子融合在数据流架构里比在GPU上更重要,因为融合后的算子可以映射到同一个计算簇,减少跨节点的数据流动。比如把卷积、批归一化和激活函数融合成一个复合节点,数据在节点内部流动,不经过NoC。循环展开则是把矩阵乘法里的循环维度展开成并行的数据流路径,让多个乘加节点可以同时工作。依赖分析负责识别哪些计算之间有真正的数据依赖,哪些只是控制依赖可以消除。

我实际操作时的体会是,数据流图的粒度选择是个艺术。粒度太细,节点数量爆炸,NoC和匹配单元扛不住;粒度太粗,并行度不够,计算单元利用率上不去。通常的做法是从算子级别开始,然后根据硬件资源约束逐步细化。HotChips上有个演讲提到他们用自动化的粒度搜索,在编译期尝试不同的划分方案,选性能最好的那个,这个思路对工程落地很有帮助。

4.2 第二步:资源分配与映射

有了数据流图,下一步是把它映射到具体的硬件资源上。这包括计算节点分配、存储分配和路由配置。计算节点分配要解决的是哪个算子放在哪个计算簇上,目标是让通信量最小、负载最均衡。存储分配要决定每个节点的暂存器大小和FIFO深度。路由配置则是为NoC设置路由表,让数据包走最合适的路径。

这个映射问题本质上是NP难的,实际中通常用启发式算法。我见过比较有效的策略是先做空间划分再做时间调度:先把数据图切成若干个子图,每个子图映射到一个计算簇,子图内部用数据流调度,子图之间用流水线或批处理来重叠。这样既利用了数据流的并行性,又控制了映射的复杂度。

映射过程中有几个硬约束要时刻盯着:片上存储总量、NoC带宽、计算单元数量。这三个约束往往互相矛盾,增加并行度就要更多存储和带宽,减少存储又可能限制并行度。我的经验是先用一个简化的性能模型快速评估不同映射方案的瓶颈在哪里,然后再针对瓶颈做优化,比盲目搜索高效得多。

4.3 第三步:运行时调度与动态调整

数据流芯片的运行时调度比传统架构轻量,但并非没有。运行时主要处理几件事:数据图的启动和切换、异常处理、负载均衡的动态微调。启动时,配置信息被加载到各个节点,然后数据从输入端口注入,整个数据流图开始运转。切换时,需要等待当前数据图排空,然后加载新的配置。

动态调整主要针对负载不均衡的情况。虽然编译期已经做了静态映射,但实际运行中可能因为数据分布变化导致某些节点成为热点。一些先进的数据流芯片支持运行时的任务窃取或动态重路由,让空闲节点帮忙处理热点节点的任务。这个机制在HotChips的某些方案里有提及,但实现复杂度不低,需要硬件和编译器的深度配合。

我实测下来的感受是,运行时调度的收益在规则负载下有限,但在不规则负载下很关键。如果你的模型结构规整、batch size固定,静态映射基本就够了;但如果模型有动态shape或者多模型混跑,运行时调度就是刚需。

4.4 一个简化的映射示例:以矩阵乘法为例

为了把上面的流程讲具体,我拿一个矩阵乘法举例。假设我们要算 C = A × B,A是M×K,B是K×N。在数据流架构里,这个计算可以分解成K个秩1更新,每个更新是A的一列和B的一行做外积,累加到C上。

映射时,我们可以把C的每个元素分配给一个计算节点,每个节点负责累加K次。A的列和B的行通过NoC广播到所有节点。每个节点有一个累加器和一个小的FIFO,用来缓存到达的A和B数据。当一对A和B数据到达时,节点做一次乘加,更新累加器。K次更新完成后,C的元素就绪,输出到下游。

这个映射的关键参数是广播带宽和FIFO深度。广播带宽决定了A和B数据能多快送到所有节点,FIFO深度决定了能容忍多大的数据到达抖动。如果M和N很大,节点数量多,广播带宽可能成为瓶颈,这时候可以考虑把C分块,每块用一组节点,减少广播范围。这个分块策略就是编译期映射要做的决策。

5. 常见问题与排查技巧实录

5.1 数据流芯片跑不满算力的五个典型原因

在实际使用数据流芯片时,最常见的问题就是“标称算力很高,实际跑起来只有零头”。我整理了几个典型原因和排查思路。

问题现象可能原因排查方法解决思路
计算单元利用率低于30%数据图粒度太细,NoC成为瓶颈用性能计数器看NoC带宽利用率增大算子融合粒度,减少跨节点通信
延迟远高于预期令牌匹配队列溢出,节点等待检查匹配单元的溢出计数增加匹配队列深度或改用静态调度
功耗异常高数据搬运占比过大分析各存储层级的访问次数增加数据复用,把权重预加载到近端存储
多模型切换时性能骤降配置开销没有摊销测量配置加载时间占比合并模型或增大批处理减少切换频率
某些层特别慢该层的数据图映射不均衡逐层分析节点负载分布重新映射该层,或对该层做特殊处理

这个表里的每一条,我都在实际项目里遇到过。最让我头疼的是第一条,因为NoC瓶颈往往不是一眼能看出来的。后来我养成了一个习惯:拿到任何数据流芯片,先跑一个简单的矩阵乘法,逐步增大矩阵规模,观察利用率的拐点在哪里。拐点出现的位置,基本就是NoC或存储开始成为瓶颈的规模。

5.2 编译器与硬件不匹配的坑

数据流架构对编译器的依赖极深,编译器如果和硬件设计脱节,性能会大打折扣。我见过一个案例,硬件支持灵活的暂存器配置,但编译器只会用一种固定配置,结果在某些层上暂存器不够用,数据频繁溢出到主存,性能直接腰斩。

排查这类问题,关键是看编译器的资源分配策略是否和硬件的实际约束对齐。具体做法是:拿一个已知性能的基准模型,用编译器编译后跑一遍,同时用硬件性能计数器记录实际资源使用情况。如果发现某个资源(比如暂存器)的利用率很低但性能又不好,那很可能是编译器没有充分利用硬件能力。

解决思路通常是两条:要么改编译器,让它感知硬件的资源约束;要么改硬件,让资源约束更宽松。实际中往往是两边都做一点。HotChips上有个团队分享了他们如何用硬件性能计数器反馈来指导编译器优化,这个闭环思路我觉得是数据流架构走向成熟的关键。

5.3 数据精度与数值稳定性的隐藏问题

数据流架构为了追求能效,往往会在数据表示上做文章,比如用定点数、用低精度浮点、甚至用对数域计算。这些选择在理想情况下能大幅降低能耗,但实际中可能引入数值稳定性问题。

我踩过的一个坑是:某个数据流芯片用了一种自定义的块浮点格式,在大部分层上精度够用,但在某些对精度敏感的层(比如softmax之前的累加)上误差累积,导致最终结果偏差超出容忍范围。排查这个问题花了很久,因为误差不是均匀分布的,而是集中在特定数据分布下。

后来我的做法是:在映射之前,先用软件模拟器跑一遍全精度和低精度的对比,找出对精度敏感的层,然后对这些层单独配置更高的精度。数据流架构的好处是,不同节点可以用不同的精度,这个灵活性正好可以用来做精度和能效的权衡。

5.4 调试工具链的现状与自救方案

说实话,数据流芯片的调试工具链目前普遍不如GPU成熟。GPU有Nsight、有CUPTI,数据流芯片往往只有基础的性能计数器和日志。我遇到问题时,经常需要自己搭一套分析工具。

我的自救方案是:在编译器输出的数据流图上做插桩,记录每个节点的触发次数、等待时间、数据传输量。这些信息虽然粗糙,但足以定位大部分性能问题。另外,我会用FPGA原型或者周期精确的模拟器来做深度分析,虽然慢,但能看到每个周期的状态,对理解架构行为很有帮助。

HotChips上有个趋势是,越来越多的数据流芯片开始提供可视化的数据流图执行追踪,把每个节点的状态随时间的变化画出来。这个工具对调试太重要了,我希望它能成为行业标配。

6. 数据流架构的适用边界与选型建议

6.1 什么场景下数据流架构优势最大

数据流架构不是万能的,它有明确的优势区间。根据我的经验,以下场景最适合:

固定模型的大规模推理。模型结构固定、batch size稳定、需要长时间高吞吐运行,数据流架构可以把配置开销摊销到极致,同时通过权重预加载和数据复用把能效做到很高。这也是目前数据流芯片落地最多的场景。

稀疏计算和结构化稀疏。数据流架构天然适合处理稀疏性,因为计算是由数据触发的,零值可以直接被跳过,不需要像GPU那样靠预测或压缩来间接处理。对于稀疏度高的模型,数据流架构的能效优势非常明显。

多算子融合的复合层。当模型里有大量可以融合的小算子时,数据流架构可以把它们映射到同一个计算簇,避免反复进出主存。这个优势在Transformer类模型里特别突出,因为注意力机制里有大量逐元素操作和小矩阵乘法。

6.2 什么场景下要谨慎选择

反过来,以下场景选数据流架构要谨慎:

模型结构频繁变化。如果模型在运行时动态改变结构,数据流架构的编译期映射优势就没了,配置开销会吃掉大部分收益。这种情况下GPU的通用性更有优势。

需要极致灵活性的研究场景。做算法研究时,模型结构一天变三次,数据流架构的编译流程可能跟不上迭代速度。这时候用GPU快速验证想法更实际。

小规模、低延迟的单次推理。数据流架构的启动和配置有固定开销,如果只是偶尔跑一次小模型,这个开销占比会很高。GPU的成熟生态和低启动延迟反而更合适。

6.3 选型时的关键评估维度

如果你在评估是否采用数据流架构,我建议从这几个维度打分:

编译器的成熟度。这是最重要的维度。数据流架构的性能上限由硬件决定,但实际能达到多少由编译器决定。评估时不要只看硬件参数,要拿你的真实模型让编译器跑一遍,看映射质量和性能。

存储层次的设计。片上存储总量、暂存器灵活性、权重预加载支持,这些直接决定了数据复用效率。特别要关注权重存储是否独立于激活存储,以及权重加载的带宽。

NoC的拓扑和带宽。不要只看峰值带宽,要看在实际数据图下的有效带宽。可以问厂商要一些真实模型的性能数据,或者自己跑基准测试。

调试和性能分析工具。这个往往被忽视,但实际使用中极其重要。没有好的工具,性能问题排查会非常痛苦。

生态和编程模型。数据流芯片的编程模型和GPU差异很大,团队的学习成本要考虑进去。如果团队已经深度绑定CUDA生态,迁移成本可能很高。

7. 我对数据流架构未来两年的一些个人判断

聊了这么多技术和实操,最后说点我自己的判断。这届HotChips让我最确信的一件事是:数据流架构不会再停留在学术论文和初创公司的PPT里了。随着大模型推理需求爆发,能效成为硬约束,数据流架构的工程化落地会加速。

但我也不认为数据流会取代GPU。更可能的格局是分工:GPU继续统治训练和灵活推理,数据流芯片在固定模型的高吞吐推理、边缘端低功耗推理、以及特定稀疏计算场景里占据一席之地。两者之间的边界会随着编译器和工具链的成熟而动态变化。

对于工程师来说,我的建议是:不要只盯着某一种架构,而是要理解数据流动的本质。无论架构怎么变,减少数据搬运、提高数据复用、让计算和存储更近这三个原则是不变的。理解了这些原则,你就能在任何新架构出现时快速判断它的价值和边界。

我在实际项目里最大的体会是,架构选型从来不是选“最先进”的,而是选“最匹配”的。数据流架构有它闪耀的场景,也有它力不从心的地方。把场景吃透,把数据图分析清楚,比盲目追新要重要得多。如果你正在做相关的评估或落地,欢迎交流,这个领域变化太快,多碰撞才能少踩坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进