
做了这么多年芯片相关的工作我越来越觉得AI芯片的软硬件设计这句话被说滥了。很多人以为设计AI芯片就是把一堆矩阵乘法单元堆上去然后配个编译器就完事——真不是这样。我做过的项目里真正的精力消耗往往不在芯片本身而在于让软件栈能把硬件的能力榨干。一个很扎心的事实是硬件能跑100 TOPS的算力如果编译器调度不合理、数据搬运路径绕远路实际端到端性能可能连40 TOPS都到不了。这正是软硬件协同设计要解决的根本问题。这篇文章我想从一个系统工程师的角度把AI芯片软硬件设计这件事拆开讲清楚。目标读者不是只看新闻的围观者而是真正要入行做芯片、做编译器、做算子库、或者做AI应用性能优化的工程师。这块领域交叉性极强纯硬件背景的人容易忽略软件栈的复杂度纯软件背景的人又容易把硬件细节想得太简单。所以这篇文章的核心命题就是一句话为什么AI芯片的性能天花板是由软硬件一起决定的以及你在实际项目里该怎么入手去设计这个协同体系。1. 算力只是标称值AI芯片真正的三个性能瓶颈先记住一个概念任何AI芯片的标称算力比如XX TOPS都只是理论上限实际能跑到多少取决于你能否绕过三个瓶颈。这三个瓶颈是软硬件协同设计必须直面的一线战场。第一个是计算瓶颈Compute Bound。矩阵乘、卷积这类算子理论上乘法器越多越好。但你要知道一旦算力上去了数据供给就成了问题——这就是第二个瓶颈访存瓶颈Memory Bound。AI计算的核心规律是一次读取的数据要尽可能多地参与计算否则时间全浪费在数据搬运上。业界常提的算术强度Arithmetic Intensity即计算量除以访存量单位是FLOPs/Byte就是在量化这件事。算法上算术强度越高越容易逼近计算瓶颈的极限反之如果数据复用性差就算算力再高也白搭因为数据从DRAM搬进片上缓存的带宽就那么大。第三个是延迟瓶颈Latency Bound。小模型、边缘场景或者交互式推理不仅是吞吐问题单个请求的延迟也很关键。这种场景下算力过剩没用能不能快速把数据流式地灌进计算阵列反而更重要。软硬件设计里就得考虑流水线部署、多级缓冲、局部性调度这些细活。这里还要引出一个关键概念Roofline模型。它把可达到的性能画成一条屋顶曲线左边是内存受限区斜率为带宽右边是计算受限区水平线为算力峰值。软硬件协同优化的本质就是让一个个算子尽量从屋顶的左边移动到屋顶的右边。我常跟团队说一个生活化的类比把芯片想象成一个中央厨房。算力是灶台数量访存是食材运输通道编译器就是厨师长。你在厨房里堆再多灶台如果食材通道只有一扇小门厨师再快也只能等着食材到场。AI芯片设计里灶台算力容易堆但食材通道片内总线、缓存、HBM接口的硬件面积和功耗都是巨大开销怎么分配资源是软硬件协同设计的核心权衡。2. 从神经网络到芯片指令算法如何映射成硬件行为软硬件协同设计的第一步不是写RTL代码也不是写Python模型而是想清楚一个问题你支持的神经网络算子该怎么变成硬件上的具体行为2.1 算子拆解与硬件原语对齐主流的神经网络无非是卷积、矩阵乘、激活、归一化、池化、各种elementwise算子。硬件层面上你需要定义一套硬件原语也就是芯片能高效执行的最小操作单元。通常是一个矩阵乘块比如一个Cycle算完一个16x16x16的乘累加、一个向量处理单元Vector Unit用来跑激活和elementwise再加上数据搬运引擎DMA和片内缓冲。我见过不少团队一上来就想着做通用可编程架构结果硬件原语复杂到软件根本驾驭不住最后只能用手写算子维护成本高得惊人。正确的做法是反过来——从算法负载的特征出发定义少量且高频的原语。当时我们做目标检测模型的时候最高频的操作就是3x3卷积和1x1卷积那硬件原语就围绕这两种形态来优化其他不常见的例如空洞卷积直接分解成多个3x3卷积的组合在软件层解决而不是为它在硬件上加特殊通道。这个原则叫让90%的算子跑得极快10%的算子靠组合变通。2.2 一个具体例子GeLU激活函数的硬件处理很多人觉得激活函数有什么好设计的但在软硬件协同里这种不起眼的算子往往是性能黑洞。比如Transformer里的GeLU激活函数数学定义是 x * Φ(x)里面带着一个误差函数。如果完全用精准数学去算要么上多项式展开要么查表硬件逻辑会变得很大。我们的做法是软硬件协同设计这个算子——精度上允许误差硬件上不直接算GeLU而是先算一个相对简单的近似在硬件里内置一个近似单元利用分段线性插值或者低阶多项式去拟合。编译器在编译计算图的时候识别到GeLU节点自动替换成硬件近似实现。这样就在不显著影响模型精度的前提下省掉了一大块硬件面积。这个流程需要回流验证——把优化后的算子再放回整个PyTorch模型里跑一遍精度对比误差在允许范围内才能落地。这就是软硬件协同在日常项目里的一个缩影硬件提供能力选项软件负责在精度和效率之间找到平衡点。2.3 卷积如何映射到矩阵乘单元上卷积在硬件上真正的执行方式往往不是直观的滑窗扫描而是转化为矩阵乘。两种经典映射方案im2col把卷积窗口展开成矩阵和隐式GEMM直接用矩阵乘逻辑去映射卷积的滑动窗口。两者在硬件实现里都为了同一个目的——让卷积复用在为矩阵乘设计的脉动阵列或者乘累加阵列上。这里面有个关键决策数据在片上的布局。你是用NHWC还是NCHW权重是存储成亲和计算阵列的形状还是亲和连续访存的形状别小看这个选择它直接影响编译器后续做数据切片和张量布局优化的空间。我们的经验是硬件上定义好逻辑的数据布局约束编译器在这个约束下自由优化模型跑出来之前不要过早固定布局方案。先设计空间大一点保留编译器优化的自由度到后期发现瓶颈再收敛约束这个序别搞反。3. 编译器是芯片灵魂中间表示、调度与内存分配的实战逻辑如果只做硬件不做配套的编译器AI芯片几乎没有实用价值。业界常说编译器是芯片灵魂这话一点不夸张。因为AI算法迭代太快你不能指望每一个算子都靠手写汇编或者手写RTL适配模型。3.1 工具链的分层结构一个典型的AI芯片软件栈从下往上大致是硬件抽象层HAL→ 指令集或宏指令 → 编译器对应TVM、XLA、llvm等→ 图优化层前端→ 算子库/运行时 → 推理框架接口。不同公司对这个分层的命名不同但逻辑大致如此。这里我特别想强调前端图优化层的重要性。这个层跟你用什么后端实现关系较小它负责的是从计算图层面做算子融合、布局转换、消除冗余计算。比如把Convolution BatchNorm ReLU三个节点融合成一个算子推理时BatchNorm在训练之外是可以折叠进卷积权重的这一步融合在纯框架层面就能做但是只有当编译器告诉它我底层硬件支持融合算子形态时它才敢合得彻底。所以软硬件协同的一个细节就是图优化层要早定义一套可扩展的算子语义硬件原语的边界要跟这个语义对齐。3.2 调度与内存分配里的真功夫编译器真正体现价值的地方在调度和内存规划。一个模型跑在芯片上每一层的数据从哪里来算完放哪去中间结果要多大空间多条流水线之间怎么重叠这些号称调度问题的内容是纯软件可解的难点中最硬的一块。一个很常见的优化叫算子融合Operator Fusion。两个连续的elementwise算子可以进行算子融合内存里数据就不用来回搬运。举个量化场景的例子推理的时候Conv - ReLU - Quantize三个算子以前是三个算子做三次读写融合后卷积单元算完一个像素块数据直接留在片内buffer过ReLU和Quantize再直接写回输出。对HBM带宽的节省可以达到几十个GB/s的级别。另一个实战中容易踩的坑是循环分块Loop Tiling。你以为把维度拆开就完事了分块的大小必须和片上SRAM大小、DMA对齐粒度、算子的算术强度配合起来。我们当时调一个3x3卷积的性能死活上不去最后发现问题出在分块大小选的跟DMA突发传输长度不匹配——传输的每一步都带了一点无效数据带宽利用率掉了近一半。这种问题光在软件层面看是看不出来的你必须理解硬件的突发长度与对齐要求。这就是软硬件协同设计最真实的状态两边都要懂两边都要妥协。优化手段核心收益主要代价适用场景算子融合降低访存次数编译器复杂度上升w1. 内存带宽受限的模型循环分块提升数据复用率需要硬件参数配合超大feature map卷积布局转换改善内存访问连续性引入额外transpose算子NHWC/NCHW混用场景内存复用降低片上buffer占用可能有生命周期分析问题大模型推理端侧部署3.3 性能模型与预估工具软硬件协同设计不可能每次优化都等到芯片流片回来看结果那样周期太长根本不能接受。真正的做法是开发一套性能模型Performance Model在芯片还在设计阶段就能估算出每条指令的执行周期、访存冲突情况、流水线stall情况。性能模型的价值在于可迭代硬件改一个参数比如SRAM容量从1MB加到2MB软件侧模拟就能立刻看到卷积算子的延迟变化编译器改了调度策略也能通过模型验证是否真实改进了性能。我们团队曾通过性能模型发现把两个DMA通道从轮流搬运改成乒乓交替搬运整体推理吞吐提升了约23%。这个改动如果等到芯片回来再验证成本会高太多。4. 精度、数值格式与模型量化软硬件协同里的隐蔽战场AI芯片不只是算得快还要算得对。这里的对不是指数学意义上的绝对准确而是最终模型精度可接受。软硬件协同里最隐蔽、最烧脑的一块就是对数值精度和量化的处理。4.1 为什么不能全部用FP32道理很简单成本和效率。FP32的乘法器和存储单元面积大约是INT8的几倍功耗更高访存量还大。在边缘端跑大模型全FP32根本不现实。所以业界普遍用混合精度策略——对精度敏感的层用FP16/FP32对精度不敏感的层用INT8甚至INT4。但问题是你怎么知道哪一层敏感这就要靠量化感知训练QATQuantization-Aware Training来做。那我的建议是软硬件设计时先确保硬件支持多种精度模式的快速切换而把哪层用多少bit的权力交给编译器。编译器结合硬件后端的性能和实测精度来决定每一个算子的实际精度配置。我们内部称为精度搜索思路跟神经架构搜索有点像只是搜索空间变成了每个算子的数值格式。4.2 不凑整数的数据宽度最近这些年几个大厂开始推进非整数倍bit宽度的浮点格式比如MXFP4、MXFP6这种。动机很直白在模型精度只损失一点点的情况下访存和运算开销又降了一个档次。硬件上支持这些花式格式会给编译器带来额外负担——所有数据都需要做格式转换。这个转换的代价也是同步在设计时需要算进去的格式转换单元放在DMA路径上还是计算阵列前直接影响流水线会不会出现气泡。我给一个体感参考如果只是一般业务模型FP16和混合精度其实够用了如果做超大模型那么低位宽格式是绕不开的而且最好是软硬件一起设计好这个新格式而不是等软件栈先出一版格式、硬件后面再去适配那样一定会出现数据布局对不上的兼容性噩梦。我们的经验是先定好数值格式语义再分别做硬件和软件侧的实现最终用一套统一的抽象描述格式来串联——这样两边不会出现理解偏差。4.3 数值误差的追踪手段还有一个在实践里容易翻车的细节浮点累加的顺序会影响结果。你在性能模型里模拟FP16累加和在真实硬件上跑的结果会有一点点差异但在评估大模型最终输出时误差可能被放大。我们是主张从设计初期就建立bit级精确的行为仿真器在硬件还没回来之前软件就已经知道某种组合的数值计算会产生什么误差。同时配合一套自动化测试每次模型精度有异常就自动下钻到具体哪一层算子的误差贡献大。没有这套工具AI芯片项目做深了迟早会被精度问题搞得焦头烂额。5. 验证与调试的真实世界从仿真、FPGA到硅后调试任何芯片项目都会经历从仿真验证到硅后调试的漫长链路AI芯片因为软硬件的深度耦合这条链路会更加纠缠。5.1 仿真阶段就先跑真实模型其实一个非常值得推广的做法是在RTL仿真阶段就接入真实模型。当时我们是把编译器的输出变成一组指令序列然后在RTL仿真器里跑起来比对结果与CPU参考实现的差异。在仿真阶段跑全量ResNet50或者BERT确实非常慢但好处惊人——基本两层以内的错误都能被逮到。等芯片回来软件栈的初始版本大概率是能跑通的能省掉无数调试的夜晚。这个阶段我们能得到什么数据每一条指令的周期数每个模块的空闲率DMA的带宽利用率SRAM的拥塞情况。这些数据对后续优化硬件调度策略极其有用。其实芯片设计不是一个纯脑力活很多时候是靠仿真数据来引导的仿真阶段把硬件行为吃透软硬件接口就已经成功了一大半。5.2 FPGA原型验证与性能预估的差距FPGA原型平台也是绕不开的验证手段。不过必须说清楚FPGA跑AI模型目标是验证功能而不是看性能。FPGA的频率和片上网络跟真实ASIC的差异非常大所以你看到FPGA上的性能数据往往远低于真实芯片。但FPGA的价值在于做软硬件集成的预演——编译器、runtime、驱动、推理框架全部跑一遍把接口问题都暴露干净。我们踩过的坑包括DMA地址对齐与burst length不匹配导致传输效率骤降中断处理路径过长导致推理流水线停顿权重布局没有按硬件SRAM bank对齐出现bank冲突读取效率减半。这些问题里前两个其实是比较经典的软硬件接口问题不是芯片逻辑错了而是软件调用方式跟硬件设计预期不一致。到了FPGA阶段才暴露虽然有点晚但好在不是在硅片上暴露。5.3 硅后调试的新挑战芯片真正回来后调试的难度会再次上升。你看不到内部节点的真实状态只能通过扫描链、观察寄存器、以及精心设计的硬件计数器来反推。这里最需要的东西是硬件侧埋足够的性能计数器。我们是强烈建议AI芯片设计早期就规划好性能监控单元PMUPerformance Monitoring Unit至少按sub-system粒度去统计计算单元利用率、DMA传输总量、片上buffer命中率、总线stall周期数、流水线空泡数。没有这些数据性能调优的路基本走到头了。在那些头部团队的分享中很多难度极高的性能问题是靠性能计数器一层一层跟踪定位出来的而不是靠猜。所以在RTL设计阶段就规划PMU我认为是AI芯片软硬件协同设计里性价比最高的行为之一。6. 生态、工具链与商业落地的现实博弈最后回到一个更现实的话题芯片做出来不难难的是有人愿意用你的工具链并且性能真的达标。这里面有大量生态层面的软硬件博弈。6.1 好用 vs 可控在项目管理上你通常会面临一个持续不断的选择编译器是尽量自动完成调度还是把调度权开放给开发者手工调优自动调度的好处是上手门槛低PyTorch模型扔进去改改配置就能跑起来坏处是通用路径往往拿不到极致性能。高水平的性能工程师会希望手写关键算子或者至少能手动干预调度策略比如指定循环分块的大小、指定数据放在哪一级Buffer、指定DMA预取时机。我的实践经验是两套机制都要有。默认情况下编译器自动调度提供一系列分析报告告诉用户哪几个算子最耗时、为什么耗时、建议怎么优化高阶能力则通过一种意图式编程接口向用户开放让懂行的人直接干预调度。这两个层面缺一个都会在实际落地时遇到重大阻碍。只开放自动编译顶尖客户会觉得芯片太弱只强调手工调优普通客户根本用不起来OS出包就没了竞争力。6.2 与主流框架的适配节奏另一个核心问题是AI芯片的软件栈必须快速拥抱主流的训练框架如PyTorch和推理运行时如ONNX Runtime而且这两者的版本迭代极快。芯片软件团队必须时刻跟进框架的新特性。我们会把跟框架社区周期同步作为一条工作原则每个季度做一次主干合并每次发布新版本都要完整回归一遍相关算子和端到端模型清单。这里有个具体的软硬件协同点框架侧对算子的语义定义会直接影响编译器中算子的语义映射实现的一致性。比如PyTorch新出了一个融合的注意力算子编译器要判断它能否额外地做一次折叠、融合进之前的矩阵乘这就涉及硬件片上缓存容量的问题——如果缓存放不下整个中间结果就得分块做性能又变了。所以这些协同设计往往不是一次性的而是一条持续拉通的长线任务。6.3 路标决策通用与专用之争设计AI芯片时还有一个宏观决策走更通用的GPGPU路线还是走面向特定模型的专用ASIC路线。通俗一点说这其实是铺高速公路和修地铁专线的区别。高速公路能让各种车都跑但跑特定班次的高速专列不一定最划算专线很高效但一旦出行需求变了专线可能会废掉。我们当年的判断标准很简单考虑清楚产品生命周期内你主打的模型family是什么。如果你是先锚定CNN做优化那么Transformer大火之后硬件能不能灵活应对如果硬件里计算单元高度专用于卷积的im2col逻辑处理attention矩阵乘可能就很吃力。所以现代AI芯片设计普遍强调在计算阵列可重构的前提下对一些固定pattern做专用硬化。软硬件协同设计在这里收敛形成一个结论计算要通用访存要丰富专用算子要用软件融合去实现。7. 我的几条个人经验总结如果非要用几句话总结AI芯片软硬件设计的核心心得我会说以下几点第一硬件设计从第一天起就要想着软件。很多芯片团队在流片回来之后才召集软件团队开会这是最大的错误。我见过太多这样的事。编译器开发者需要的是和RTL开发者坐同一张桌子提前讨论指令集语义、缓存替换策略、DMA对齐方式这些细节。这种软件早于硬件介入的方式是协同设计能否落地的根源保障。第二性能模型的投入永远是划算的。在芯片设计周期中性能模型越早建立、越贴近真实实现后面调节点的时候越有底气。纯靠估算、靠经验拍脑袋很多问题直到硅后才暴露那就来不及了。第三准备好一套从模型到芯片的可复现调试链路。从PyTorch算子到高层IR到底层指令再到仿真器和FPGA再到真实芯片每一步的状态都要能追踪、能回放、能对比。这个工程基建听起来不性感但没有它软硬件协同设计就是纸上谈兵。最后分享一个操作层面的小技巧在做算子映射的初期先把性能模型和指令集手册整理成一份机器可读的硬件能力描述文件然后让编译器直接读这个文件做资源调度和可行性检查。这样能避免编译器里硬编码大量硬件假设后续硬件调整时只要更新描述文件编译器就能自动适配。这个小事对我们的开发效率提升极大强烈建议做AI芯片软硬件协同的团队都考虑这个方向。AI芯片的软硬件协同设计是一条少有人走完的路但它的价值正体现在每多走一步你对如何让计算更快、更省、更准这件事的理解就更深一层。希望这篇偏实战的梳理能帮你在这条路上少走几步弯路。