AI芯片软硬件协同设计:从架构到验证的全链路实践
发布时间:2026/10/19 1:02:06 锦皓数字建站

1. 从一颗芯片的诞生说起为什么软硬件必须一起设计很多人第一次听到“AI芯片的软硬件设计”脑子里浮现的画面可能是两拨人各干各的一拨人在电脑上画电路图、跑仿真另一拨人埋头写驱动、调算子库最后在某个节点上把两边拼在一起能跑通就万事大吉。这种“先硬件后软件”的串行思路在传统通用处理器时代勉强能用但放到AI芯片上几乎注定要翻车。原因不复杂。AI芯片和通用CPU最大的区别在于它的计算模式高度专用化。一个矩阵乘法单元、一个卷积加速器、一个张量核心它们对数据怎么摆放、以什么粒度搬运、什么时候该预取、什么时候该写回都有非常具体的偏好。如果硬件设计阶段不考虑上层框架会怎么调用、算子会怎么切分、内存会怎么复用那做出来的芯片很可能出现一种尴尬局面理论算力很漂亮实测吞吐却只有峰值的百分之二三十功耗还压不下来。我见过一个比较典型的例子。某团队做了一款面向边缘推理的加速器MAC阵列规模堆得很大片上缓存也给得足单看规格表非常能打。但流片回来之后跑主流视觉模型时利用率始终上不去。后来排查发现问题出在数据排布上硬件默认按NCHW格式做连续搬运而框架侧为了兼容性默认走的是NHWC两边在内存访问模式上拧着来导致每次卷积都要多做一次隐式转置带宽全耗在无效搬运上了。这个坑如果在前端设计阶段就让软件团队参与评审本来是可以避免的。所以AI芯片的软硬件设计本质上不是两个独立工程的简单相加而是一个需要反复迭代、互相约束的协同过程。硬件要为软件留出足够的灵活性和可编程空间软件也要理解硬件的物理边界和性能模型不能天马行空地提需求。这篇文章我想从实际项目推进的角度把这条链路上几个关键环节拆开来讲清楚从需求定义、架构选型、算子映射到编译器设计、驱动适配、性能调优再到流片前的软硬件联合验证。适合正在做AI芯片相关工作的工程师、准备进入这个方向的学生以及对芯片设计流程好奇的技术管理者阅读。不需要你精通Verilog或深度学习框架底层但最好对计算机体系结构和神经网络的基本计算过程有概念。2. 需求定义阶段先想清楚芯片到底要跑什么2.1 模型画像比算力数字更重要很多项目立项时第一句话就是“我们要做一颗XX TOPS的AI芯片”。这个说法本身没错但TOPS这个指标太粗了。同样是100 TOPS跑ResNet-50和跑Transformer实际有效算力可能差出好几倍。所以在需求定义阶段比定算力数字更重要的是先把目标模型画像画出来。模型画像至少包含这几个维度主流算子类型及占比、典型张量形状和批次大小、精度要求FP32/FP16/INT8/INT4、内存访问特征计算密集还是访存密集、以及是否有动态形状需求。比如你做的是安防场景的人脸检测那模型以轻量级CNN为主输入分辨率固定INT8量化就能满足精度这种场景对峰值算力要求不高但对延迟和功耗极其敏感。反过来如果目标是云端训练或大模型推理那重点就变成高带宽内存、高精度支持和灵活的并行切分能力。我个人的经验是在需求阶段至少要跑一遍目标模型的算子统计。用PyTorch或ONNX把模型导出来遍历计算图统计每类算子的调用次数、总FLOPs占比、以及内存占用峰值。这个统计结果会直接决定后面架构设计的重心。如果卷积占了80%以上的计算量那卷积加速器的设计就是核心如果矩阵乘和LayerNorm交替出现那就要考虑通用矩阵单元和向量单元的配比以及它们之间的数据通路怎么设计才不至于互相等。2.2 精度策略要在架构定稿前敲定精度这件事越早定越好。我见过一些项目硬件按FP16设计流片回来发现客户要求INT8部署结果只能靠软件做量化模拟性能损失一大截。反过来如果一开始就按INT8设计后面想支持FP16训练就非常困难。比较稳妥的做法是在架构定义阶段就明确支持哪几种精度组合以及它们之间的转换开销。常见的选择是FP16做训练和精度敏感推理INT8做高吞吐推理有些场景还会用到INT4做极致压缩。硬件上乘法器阵列可以设计成可重构的比如一个FP16乘法器拆成两个INT8乘法器用这样在低精度下算力翻倍灵活性也好很多。但代价是面积和功耗会增加需要根据目标场景做权衡。这里有一个容易被忽略的点量化的精度损失不完全是硬件位宽决定的跟校准算法和数据分布关系很大。所以软件团队在需求阶段就应该介入用目标模型跑一遍量化仿真看看INT8下精度掉多少需不需要混合精度。如果INT8掉点严重那硬件可能就要考虑支持INT16或者FP16回退这个决策必须在RTL freeze之前做完。2.3 软件栈的边界要提前画出来需求阶段还有一个关键动作是明确软件栈的职责边界。具体来说要回答几个问题芯片是只提供裸金属驱动还是配套完整的运行时和算子库上层框架是通过自定义算子接入还是走标准ONNX/TFLite路径编译器是自研还是基于TVM/MLIR做二次开发这些问题的答案会反向影响硬件设计。举个例子如果决定走标准ONNX路径那硬件就必须支持ONNX里常见的算子语义包括各种padding模式、dilation、group convolution等。如果只支持自定义算子那灵活性高但客户迁移成本大生态很难做起来。再比如如果编译器基于MLIR做那硬件指令集的设计最好能跟MLIR的dialect对齐这样lowering过程会顺畅很多否则中间要加很多转换层既影响性能又增加维护成本。我的建议是在需求阶段就拉一个软硬件联合评审把目标模型、精度策略、软件栈边界这三件事一起过一遍。不要等到架构定稿了再让软件团队提意见那时候改硬件的代价太大了。3. 架构设计在灵活性和效率之间找平衡3.1 计算阵列的粒度选择AI芯片的计算核心通常是一个二维的乘法累加阵列也就是常说的MAC阵列或脉动阵列。阵列的大小和粒度直接决定了芯片的算力密度和灵活性。大阵列的好处是算力高、数据复用充分适合规则的大矩阵运算。但缺点是灵活性差遇到小矩阵或者不规则计算时利用率会暴跌。小阵列灵活但算力上限低需要靠更高的频率或者更多的核心来补。实际设计中很少有纯大阵列或纯小阵列的方案更多是混合架构一个大矩阵单元负责主力计算配合若干向量单元处理激活、归一化等逐元素操作。这里有一个经验参数阵列的维度最好跟目标模型里最常见的矩阵形状对齐。比如Transformer里常见的head dimension是64或128那矩阵单元的行列数最好能整除这些值避免出现大量padding浪费。如果目标模型里矩阵形状变化很大那可以考虑把阵列设计成可分区的比如一个16x16的阵列可以拆成四个8x8独立工作这样小矩阵也能跑满。3.2 片上内存层次的设计取舍AI芯片的性能瓶颈十有八九出在内存上。算力再高数据喂不进来也是白搭。所以片上内存层次的设计是架构阶段最需要花心思的地方。典型的层次是寄存器文件 - 片上缓存SRAM - 高带宽内存HBM/DDR。寄存器文件离计算单元最近带宽最高但容量最小SRAM容量中等带宽较高HBM容量大但延迟高、功耗大。设计的关键是让数据尽量在高层级里复用减少对低层级内存的访问。具体来说要分析目标模型的访存模式。卷积运算里权重和输入特征图都有很高的复用率适合放在SRAM里反复使用。而全连接层或者大矩阵乘权重矩阵可能大到SRAM放不下那就需要设计高效的流式加载机制让数据一边从HBM读进来一边参与计算同时把中间结果写回去。这里面的双缓冲、乒乓缓冲、预取策略都需要在架构阶段就规划好。我踩过的一个坑是SRAM的bank划分没做好导致多个计算单元同时访问同一块内存时出现bank conflict有效带宽直接减半。后来改成多bank交叉编址并且让编译器在分配地址时做对齐优化才把带宽利用率提上来。这个教训说明内存子系统的设计不能只看容量和理论带宽访问模式冲突才是隐藏的性能杀手。3.3 可编程性的尺度把握AI芯片和ASIC的区别在于它需要一定的可编程性来适应不断演进的模型。但可编程性给多了就变成通用处理器效率上不去给少了又变成硬连线ASIC新模型跑不了。这个尺度怎么把握是架构设计里最考验判断力的地方。常见的做法是“粗粒度可重构”计算阵列的互联和功能可以通过配置寄存器动态改变但基本的计算单元和存储层次是固定的。比如你可以配置阵列是做卷积还是做矩阵乘可以配置数据流的走向但不能改变乘法器的位宽或者SRAM的容量。这种粒度下编译器可以通过指令调度来适配不同模型同时硬件又保持了较高的能效。另一个思路是“领域专用指令集”。为AI计算定义一套精简的向量指令比如向量乘加、向量激活、向量归约等让编译器把模型编译成这些指令的序列。这样既比纯硬件加速器灵活又比通用CPU高效。关键是指令集的设计要跟上层框架的算子语义对齐否则编译器要做大量pattern matching既复杂又容易出错。3.4 互联与多核扩展单核算力总有上限多核扩展是必然选择。但多核不是简单地把几个核拼在一起核间互联的设计直接决定了扩展效率。常见的互联拓扑有总线、环形、网状等。总线简单但扩展性差核多了会争抢环形适合中等规模延迟随核数线性增长网状扩展性好但路由逻辑复杂。对于AI芯片来说因为数据流通常有规律可以根据目标模型的并行模式来定制互联。比如如果模型主要是数据并行那核间通信以广播为主总线或环形就够了如果模型有模型并行或者流水线并行那核间需要点对点的高带宽通道网状或者专用链路更合适。还有一个容易被忽略的点是全局同步。多核之间如果需要频繁同步那同步开销会吃掉很多性能。设计上可以考虑用硬件屏障或者异步流水线来减少同步次数。软件侧也要配合尽量把计算图切分成可以独立执行的子图减少核间依赖。4. 软件栈从框架到硬件的完整链路4.1 编译器是软硬件协同的核心枢纽在AI芯片的软件栈里编译器是连接上层框架和底层硬件的桥梁也是软硬件协同设计最集中的体现。一个设计良好的编译器能够把框架里的计算图经过一系列优化和变换最终映射成硬件能高效执行的指令序列。编译器的前端通常要支持多种框架格式比如PyTorch、TensorFlow、ONNX等。这一层的主要工作是把不同框架的算子统一到中间表示IR上。中间表示的选择很关键太高层了丢失硬件信息太底层了又难以做跨平台优化。现在比较流行的做法是基于MLIR做多级IR从高层计算图逐步lowering到硬件相关的指令层每一级都可以做针对性的优化。中端的优化包括算子融合、常量折叠、内存规划、循环变换等。算子融合是最影响性能的优化之一。比如把卷积、批归一化、激活函数融合成一个算子可以减少中间结果的写回和读取节省大量带宽。但融合的粒度要跟硬件的计算单元和缓存容量匹配融合得太狠可能导致寄存器溢出或者缓存不够用反而变慢。后端的代码生成要把优化后的IR映射到具体的硬件指令。这里要考虑指令调度、寄存器分配、流水线排布等问题。如果硬件有特殊的计算模式比如脉动阵列的权重固定模式编译器就要相应地调整数据流让权重尽量留在阵列里输入数据流过时完成计算。4.2 算子库的手写优化与自动生成编译器不是万能的有些关键算子还是需要手写优化才能达到极致性能。比如卷积、矩阵乘、注意力机制这些核心算子通常会有专门的手写实现针对硬件的特性做深度调优。手写算子的好处是性能可控可以精确地控制数据搬运、计算顺序、指令排布。但缺点是工作量大每换一代硬件就要重写一遍。所以现在很多团队在探索自动生成的方法用模板加搜索的方式让编译器自动为不同形状的算子生成优化代码。TVM的AutoTVM和Ansor就是这方面的代表通过定义搜索空间和代价模型自动找到较优的调度方案。实际项目中通常是手写和自动生成结合。最核心的几个算子手写保证峰值性能长尾算子用自动生成保证覆盖率。手写算子的经验也可以反哺自动生成把人工调优的策略抽象成搜索空间里的模板让自动生成也能受益。4.3 运行时与驱动别让底层拖了后腿运行时和驱动是软件栈里最贴近硬件的部分也是最容易被忽视的部分。很多性能问题追到最后发现是驱动里的一个锁竞争或者运行时的一次多余拷贝。运行时的核心职责是管理设备资源、调度任务、处理同步。设计上要注意几点任务提交的延迟要低避免在关键路径上做重操作内存分配要高效尽量复用而不是频繁申请释放多流并发要支持让计算和搬运能重叠起来。驱动层则要处理好与操作系统的交互包括设备初始化、中断处理、DMA控制等。这里的一个常见问题是中断风暴如果每个小任务完成都触发一次中断CPU会被中断处理拖垮。解决办法是用轮询加中断结合的方式或者做中断合并积累一批完成事件再统一上报。还有一个实际经验是驱动的调试接口要尽早做好。芯片流片回来之后如果驱动没有完善的日志和性能计数器排查问题会非常痛苦。最好在设计阶段就把性能监控的硬件计数器规划进去软件侧配套做好采集和展示工具。4.4 框架适配让用户无感迁移AI芯片最终是要给用户用的用户不会关心你底层怎么实现他们只关心自己的模型能不能跑、跑得快不快、精度对不对。所以框架适配的目标是让用户尽量无感迁移。常见的做法是提供自定义算子插件让用户在PyTorch或TensorFlow里直接调用。用户只需要把原来的算子替换成你的实现其他代码不用改。另一种做法是提供图优化工具用户把模型导出来工具自动做算子替换和子图融合生成适配你硬件的推理引擎。不管哪种方式精度对齐都是必须过的关。用户原来的模型在GPU上跑出一个结果在你的芯片上跑出另一个结果哪怕差异很小用户也会不放心。所以适配过程中要建立完善的精度比对流程逐层对比输出定位差异来源。有时候差异来自浮点累加顺序的不同这种就要在文档里说明清楚并给出可接受的误差范围。5. 联合验证流片前必须跑通的软硬件闭环5.1 仿真验证在RTL阶段就跑真实模型流片一次的成本极高所以流片前的验证必须尽可能充分。传统的验证方法是跑测试向量看波形对不对。但对于AI芯片来说光看波形不够还要看真实模型的端到端性能。现在比较成熟的做法是在RTL仿真阶段就接入真实的模型推理。具体来说用硬件仿真器比如基于FPGA的原型验证平台或者软件仿真器加载RTL然后让软件栈把模型编译成指令驱动仿真器执行最后比对输出结果和GPU上的参考结果。这个过程能发现很多纯硬件验证发现不了的问题比如指令集设计的缺陷、编译器生成的代码有bug、内存一致性有问题等。这个阶段的一个挑战是仿真速度。RTL仿真的速度通常比真实芯片慢几个数量级跑一个完整模型可能要几个小时甚至几天。所以实际中会做取舍小模型跑全流程大模型跑关键子图或者用FPGA原型来加速。FPGA原型的速度可以到MHz级别虽然还是比真实芯片慢但至少能在可接受的时间内跑完主流模型。5.2 性能建模提前预判瓶颈在硬件还没回来之前怎么知道性能能不能达标靠性能建模。性能模型可以是解析式的也可以是仿真式的。解析式模型用公式估算算力、带宽、延迟快速但精度有限。仿真式模型更精确但需要更多的硬件细节。我比较推荐的做法是在架构阶段就建立一个周期级的性能模型把计算阵列、内存层次、互联都建模进去。然后用这个模型跑目标模型看看瓶颈在哪里。如果发现某个环节是瓶颈就回去改架构改完再跑直到性能达标。这个过程可能要迭代很多轮但比流片回来发现性能不达标要好得多。性能模型还有一个用途是指导编译器优化。编译器在做调度决策时需要知道硬件的性能特征比如各级内存的延迟和带宽、计算单元的吞吐率等。这些参数可以从性能模型里提取也可以在实际硬件上测量后反馈给编译器。5.3 硅后调试问题往往出在意想不到的地方芯片回来之后调试才是真正考验团队的时候。硅后调试的挑战在于你面对的是一个黑盒只能通过软件接口去观测和控制很多在仿真阶段能看到的内部信号在真实芯片上可能没有引出来。常见的硅后问题包括时序不满足导致偶发错误、功耗超标导致降频、内存控制器配置不对导致带宽上不去、驱动有bug导致任务挂死等。排查这些问题需要软硬件团队紧密配合。硬件团队提供寄存器手册和调试指南软件团队写测试用例和诊断工具两边一起分析日志和波形。我的经验是硅后调试阶段一定要有优先级。先保证基本功能能跑通再追求性能。很多团队一上来就调性能结果发现功能还有bug白忙一场。另外要尽早建立自动化测试流程每次改驱动或者固件都跑一遍回归测试确保没有引入新问题。6. 一些踩过的坑和总结的经验做AI芯片的软硬件设计最深的体会是没有银弹只有权衡。算力和灵活性、性能和功耗、开发效率和运行效率这些矛盾贯穿始终每个决策都要根据目标场景来定。第一个坑是低估了软件的工作量。很多团队在立项时硬件配了很多人软件只有两三个人结果流片回来发现软件根本跟不上芯片只能躺在实验室里。我的建议是软件团队从第一天就要介入参与架构评审提前开发编译器和算子库不要等硬件定型了再开始。第二个坑是忽视了精度对齐。用户迁移模型时最怕的就是精度对不上。所以从第一天就要建立精度比对流程每支持一个算子就跟参考实现做逐元素对比确保误差在可接受范围内。不要等到最后再统一验证那时候问题堆在一起排查起来非常痛苦。第三个坑是性能调优开始得太晚。性能不是最后调出来的是设计出来的。架构阶段就要有性能模型编译器阶段就要有性能预估硅后阶段才能快速定位瓶颈。如果等到芯片回来才开始想怎么优化很多硬件上的限制已经改不了了。最后一个建议是多跟用户聊。芯片是给用户用的用户的实际需求往往跟规格书里写的不一样。有的用户在乎延迟有的在乎吞吐有的在乎精度有的在乎易用性。搞清楚用户真正在乎什么才能把有限的资源投入到最关键的地方。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。