1. 从能跑就行到跑得高效AI芯片软硬件协同设计的核心命题做AI芯片这行的人都有一个共识一颗芯片流片回来真正决定它能不能在真实业务里站住脚的往往不是峰值算力有多高而是软硬件配合得够不够默契。我见过太多项目纸面参数漂亮得不行TOPS数字一个比一个唬人结果一上真实模型利用率连30%都不到。问题出在哪几乎都出在软硬件设计的割裂上——硬件团队闷头堆MAC阵列软件团队拿到芯片才开始想怎么把算子映射上去中间那层编译器、运行时、调度策略全是事后补丁。这个系列写到第8篇我想把话题收拢到一个最核心的点上AI芯片的软硬件设计本质上是一个联合优化问题而不是两个独立工程的简单拼接。你可以在架构阶段就为软件留好接口也可以在指令集层面就考虑算子融合的便利性更可以在内存层次设计时就把数据复用模式想清楚。这些决策一旦定下来后面软件团队再怎么努力天花板就已经锁死了。这篇文章适合谁看如果你正在参与AI芯片的架构定义、编译器开发、算子库优化或者你是一个想理解为什么同样算力的芯片实际表现差这么多的技术管理者那接下来的内容应该对你有用。我会从数据流、指令集、内存层次、编译映射、运行时调度这几个维度把软硬件协同设计里那些文档不会写但实际绕不开的东西讲清楚。2. 数据流决定一切从计算模式反推硬件架构2.1 为什么数据流是软硬件设计的第一个决策点任何AI芯片的设计起点都不应该是我要做多少个MAC而应该是我的目标负载数据怎么流动。卷积、矩阵乘、注意力机制它们的共同特征是什么是数据复用。一个权重值可能被成百上千个激活值共享一个激活值也可能参与多个输出通道的计算。硬件设计的核心任务就是让这些复用尽可能在离计算单元最近的地方发生。我习惯把数据流分成三类来思考权重固定Weight Stationary、输出固定Output Stationary、行固定Row Stationary。这不是学术分类而是直接决定你SRAM怎么摆、总线怎么走、PE之间怎么连的工程选择。举个例子如果你做的是边缘推理芯片目标模型以深度可分离卷积为主那权重数据量小但激活值复用率高这时候输出固定的数据流配合较大的激活缓存就更合适。反过来如果是云端训练芯片大矩阵乘是主力权重和激活都需要高复用那行固定或者混合数据流方案往往能拿到更好的能效比。这里有个经验数据在典型的卷积层中如果数据流设计得当DRAM访问量可以降到理论最小值的1.5倍以内如果设计不当这个数字轻松突破10倍。而DRAM访问的能耗是片上SRAM访问的100到200倍。这意味着什么意味着数据流设计不好你堆再多计算单元也是白搭能耗全花在搬数据上了。2.2 从算子特征反推PE阵列结构我在实际项目中总结出一个方法先列出目标负载中占比最高的5到10个算子画出它们的数据依赖图然后看这些图里有没有共同的形状。比如3x3卷积的滑动窗口、矩阵乘的二维分块、注意力的QKV计算它们对PE阵列的要求是不一样的。假设你的目标负载里3x3卷积占主导那PE阵列最好能支持行卷积的滑动复用——也就是相邻输出像素共享输入行的数据。这时候PE之间的互联如果只是简单的二维网格数据搬运开销会很大。更合理的做法是在PE阵列里加入专门的广播通路和移位通路让一行输入数据能同时喂给多个PE并且支持跨周期的滑动。再比如如果Transformer类模型占比高那矩阵乘的维度往往很大比如512x512甚至更大这时候PE阵列的规模就要上去同时要支持分块计算——因为不可能把整个矩阵都放在片上。分块的大小又反过来影响SRAM的容量设计。我见过一个项目PE阵列做了256x256但SRAM只够存64x64的分块结果计算单元经常饿着利用率上不去。这就是典型的软硬件脱节。2.3 数据流设计中的常见误区第一个误区是追求通用性。有些团队想做一个能跑所有模型的芯片结果数据流设计得四不像什么都能跑但什么都跑不快。我的建议是明确你的主战场。如果80%的算力预算花在卷积上那就把卷积的数据流做到极致剩下的算子用可编程单元兜底。第二个误区是忽视稀疏性。现在很多模型经过剪枝后稀疏度能达到50%以上但硬件如果还是按稠密计算设计那实际有效算力就浪费了一半。支持稀疏计算的数据流设计需要在PE阵列里加入零值跳过逻辑同时编译器要能生成对应的稀疏编码格式。这部分的软硬件接口如果没提前定义好后面补起来非常痛苦。第三个误区是低估了数据搬运的复杂度。我经常用一个比喻计算单元是厨房里的灶台数据是食材。你灶台再多如果食材都堆在楼下仓库每次做饭都要跑上跑下那出菜速度肯定快不了。所以片上缓存层次的设计——寄存器文件、SRAM、全局缓冲——每一层的容量、带宽、访问延迟都要跟数据流匹配。3. 指令集与编译器软硬件之间的合同3.1 自定义指令集的粒度选择AI芯片的指令集设计有个经典难题粒度太粗灵活性差新算子支持不了粒度太细指令开销大取指译码的功耗就吃掉一大块。我参与过的一个项目最初设计了一套非常细粒度的SIMD指令结果发现卷积层的指令密度太高前端功耗占了总功耗的25%。后来改成粗粒度的卷积宏指令把循环控制、地址计算都交给硬件状态机前端功耗直接降到8%。那怎么选粒度我的经验法则是看算子的重复模式。如果一个计算模式在多个模型里反复出现比如3x3卷积、1x1卷积、矩阵乘那就值得做成一条宏指令。如果是一些零散的特殊算子比如某些激活函数、自定义的归一化那就用可编程的细粒度指令兜底。这样既保证了主路径的效率又保留了灵活性。指令集的另一个关键点是数据搬运指令的设计。很多团队把注意力全放在计算指令上搬运指令随便设计结果编译器生成代码时发现数据搬不动。搬运指令要支持什么至少要支持不同存储层次之间的块拷贝、带步长的访问、广播模式、转置模式。这些模式如果硬件不支持编译器就得用多条指令拼效率直线下降。3.2 编译器如何理解硬件编译器是软硬件之间的翻译官但这个翻译官如果不懂硬件的脾气翻出来的代码就没法看。我见过最离谱的案例是硬件有一个非常高效的权重预取机制但编译器不知道生成的代码还是按部就班地先搬权重再计算预取机制完全没用上。要让编译器理解硬件需要在指令集设计阶段就提供足够的元信息。比如每条指令的延迟、吞吐量、资源占用、依赖关系。这些信息通常以调度模型的形式提供给编译器。调度模型越准确编译器的指令调度就越高效。还有一个容易被忽视的点编译器的中间表示IR要能表达硬件特有的优化。比如张量核心的矩阵乘指令它要求输入数据按特定格式排列。如果IR里只有通用的矩阵乘操作编译器就很难自动生成这种指令。更好的做法是在IR里加入硬件内建函数intrinsic让上层框架能直接调用同时编译器也能识别并优化这些模式。3.3 算子融合的软硬件协同算子融合是提升效率的大杀器。把卷积、批归一化、激活函数融合成一个计算块可以减少中间结果的写回和读取节省大量带宽。但算子融合不是软件单方面能做的它需要硬件支持。硬件要支持什么首先计算单元要能在一次数据流中完成多个操作。比如卷积计算完后结果直接进入激活函数单元不需要写回SRAM再读出来。其次要有灵活的旁路通路让数据在不同计算单元之间直接传递。最后指令集要支持融合算子的表达让编译器能生成对应的指令序列。我在实际项目中的做法是在硬件设计阶段就定义一组融合模式比如卷积BNReLU、矩阵乘Softmax等然后在指令集里为这些模式预留编码空间。编译器识别到对应的算子组合时直接生成融合指令。这样既保证了效率又不会让指令集过于复杂。4. 内存层次设计被低估的性能杠杆4.1 片上缓存的容量与带宽权衡AI芯片的片上缓存设计是个多目标优化问题容量要大带宽要高面积要小功耗要低。这四个目标互相矛盾必须做取舍。我的经验是先确定计算单元的吞吐量然后反推缓存带宽需求。举个例子假设你的PE阵列有1024个MAC每个周期能完成1024次乘加。如果每个MAC需要两个操作数一个权重、一个激活那每周期需要2048个操作数。如果操作数来自SRAM那SRAM的带宽至少要达到2048个元素/周期。假设每个元素是16位那就是4096字节/周期的带宽。这个数字直接决定了SRAM的位宽和bank数量。容量方面要保证计算单元不会频繁等待数据。通常的做法是权重缓存要能存下至少一个完整卷积层的权重或者一个分块的权重激活缓存要能存下至少两行输入特征图支持滑动窗口。如果容量不够计算单元就会饿着。这里有个实际数据在28nm工艺下1MB的SRAM面积大约是1平方毫米功耗大约是100毫瓦。如果你的芯片面积预算是10平方毫米那SRAM最多占3到4平方毫米也就是3到4MB。这个容量约束会直接限制你能支持的最大模型和最大分块。4.2 数据复用与缓存替换策略缓存替换策略在通用CPU里是硬件自动管理的但在AI芯片里很多时候需要软件参与。为什么因为AI计算的数据访问模式是可预测的。编译器知道下一步要访问哪些数据可以提前发出预取指令也可以显式地管理缓存的换入换出。我比较推崇的做法是软件管理的暂存器Scratchpad Memory而不是硬件自动管理的Cache。Scratchpad的地址由软件直接控制编译器可以精确地安排数据的加载和使用顺序避免Cache带来的不确定性。当然这增加了编译器的复杂度但换来的效率提升是值得的。具体到数据复用要区分三种复用时间复用同一数据在不同时间被多次使用、空间复用同一数据被多个计算单元同时使用、通道复用同一数据在不同通道间共享。不同的复用模式需要不同的缓存策略。时间复用要求缓存容量大空间复用要求缓存带宽高通道复用要求缓存支持多播。4.3 片外内存接口的设计考量片外内存通常是DRAM的带宽和延迟是AI芯片的另一个瓶颈。设计内存接口时要考虑几个问题带宽够不够、延迟能不能隐藏、访问模式是否友好。带宽方面一个简单的估算方法是片外带宽至少要是片内带宽的1/10。比如片内SRAM带宽是4TB/s那DRAM带宽至少要400GB/s。当然这个比例取决于你的数据复用做得多好。复用做得好片外访问就少带宽需求就低。延迟隐藏方面通常用预取和流水线来掩盖DRAM的长延迟。编译器要能生成预取指令硬件要有足够的缓冲来存放预取的数据。我见过一个设计DRAM延迟是200个周期但预取缓冲只有4个条目结果预取根本来不及计算单元经常停顿。后来把预取缓冲加到16个条目利用率立刻上去了。访问模式方面DRAM最喜欢的是连续的大块访问。如果访问模式是随机的、小块的那有效带宽会大打折扣。所以编译器和硬件要配合尽量把访问模式整理成连续的。比如卷积的im2col操作就是把不连续的访问变成连续的矩阵访问这样DRAM效率高很多。5. 运行时调度让硬件活起来5.1 任务划分与负载均衡一颗AI芯片上通常有多个计算簇、多个内存通道。运行时调度器的任务就是把这些资源合理地分配给不同的计算任务让它们并行起来同时避免资源冲突。任务划分的粒度很关键。粒度太粗并行度不够粒度太细调度开销大。我的经验是以计算簇为单位划分任务每个任务的计算量至少能覆盖调度开销的10倍以上。比如调度一个任务的开销是1000个周期那这个任务的计算量至少要10000个周期否则调度本身就成了瓶颈。负载均衡方面静态划分简单但容易不均动态划分灵活但有开销。实际项目中我通常采用静态为主、动态为辅的策略编译时做一次静态划分运行时根据实际执行情况做微调。比如某个簇执行慢了运行时可以把下一个任务优先分给它。5.2 多核协同与数据一致性多核AI芯片的一个难点是数据一致性。多个计算簇可能同时访问同一块内存如果缺乏同步机制就会出现数据竞争。硬件上通常用屏障Barrier和原子操作来支持同步但软件上怎么用这些机制直接影响性能。我见过一个设计每个计算簇都有自己的私有缓存但缓存之间没有硬件一致性协议。结果软件必须显式地做缓存刷新和失效代码复杂不说性能还差。后来改成共享缓存加硬件一致性软件简单了性能也上去了。所以我的建议是如果面积和功耗允许尽量做硬件一致性。软件管理一致性的代价太高了。5.3 动态电压频率调整与功耗管理AI芯片的功耗管理是个系统工程。动态电压频率调整DVFS是最常用的手段但怎么调、什么时候调需要软硬件配合。硬件要提供什么频率和电压的调节接口、功耗和温度的传感器、以及调节的粒度。软件要做什么根据当前负载和热状况决定调节策略。比如推理任务对延迟不敏感可以降频省电训练任务对延迟敏感要保持高频。这里有个实际经验DVFS的调节频率不要太高。我见过一个设计每1000个周期调一次频率结果调节开销比省下来的功耗还大。通常来说调节周期在毫秒级比较合适这样既能响应负载变化又不会引入太多开销。6. 从纸面到硅片那些只有流片后才明白的事6.1 仿真与实测的差距来源流片前我们通常用仿真器评估性能。但仿真器和真实芯片之间往往有差距有时候差距还很大。差距从哪来我总结了几点第一时钟树和布线延迟。仿真时通常假设时钟是理想的但真实芯片里时钟树有偏斜布线有延迟。这些在先进工艺下尤其明显。我见过一个设计仿真时能跑1GHz流片后只能跑800MHz问题就出在时钟树上。第二内存的实际带宽。仿真时通常假设内存带宽是理论峰值但真实访问模式下有效带宽可能只有峰值的60%到70%。特别是当访问模式不连续时差距更大。第三功耗和热的影响。仿真时通常不考虑热但真实芯片跑起来会发热发热会导致漏电增加进而影响频率和功耗。如果散热设计不好芯片可能被迫降频。6.2 软件栈的适配与调优芯片流片回来软件栈的适配是个大工程。编译器要重新调优算子库要重新实现运行时要做性能剖析。这个过程通常需要几个月甚至更长时间。我的经验是在流片前就要准备好软件栈的框架。编译器可以先用功能仿真器验证算子库可以先用指令集模拟器测试。等芯片回来只需要把后端替换成真实硬件大部分软件逻辑可以复用。这样能大大缩短适配周期。调优方面要重点关注瓶颈在哪里。用性能计数器收集数据看计算单元利用率、内存带宽利用率、指令发射率等指标。哪个指标低就重点优化哪里。不要盲目地改代码要有数据支撑。6.3 常见流片后问题与应对流片后最常见的问题包括时序不满足、功耗超标、功能bug、性能不达标。时序问题通常靠降频解决但降频会影响性能。功耗问题要靠DVFS和软件优化。功能bug要靠软件绕过或者重新流片代价很大。性能不达标要靠软件调优但如果差距太大可能就要考虑改版了。我的建议是在架构阶段就留足余量。时序上留10%到15%的余量功耗上留20%的余量性能上留30%的余量。这样即使流片后有偏差也不至于无法挽回。7. 一些个人体会做AI芯片软硬件设计这些年我最大的体会是不要试图把软硬件分开设计再拼起来。最好的芯片往往是软硬件团队坐在一起从算法特征出发一步步推导出架构、指令集、编译策略和运行时方案。这个过程很痛苦因为要反复迭代要互相妥协但最终的结果会好很多。另一个体会是不要迷信峰值指标。TOPS、带宽、能效比这些数字只有在真实负载下才有意义。我见过太多芯片峰值指标很好看但实际跑模型时利用率很低。所以评估一颗芯片一定要看它在目标负载上的端到端表现而不是纸面参数。最后软件栈的投入不要省。一颗芯片的硬件成本是固定的但软件栈的质量决定了这颗芯片能用多久、能跑多少模型。我见过硬件不错但软件稀烂的芯片最后没人用也见过硬件一般但软件极其好用的芯片生态做起来了。所以如果预算允许软件团队的投入至少要和硬件团队相当。这个系列写到第8篇基本上把AI芯片软硬件设计的主要方面都覆盖了。后面如果还有想聊的可能会写写具体案例的拆解或者某些专项技术的深入分析。有什么想讨论的欢迎交流。