资讯动态

AI芯片软硬件协同设计实战:从计算阵列到编译器的性能优化指南

发布时间:2026/10/14 19:43:14 来源:尧图企业网站定制
1. 从能跑就行到跑得高效AI芯片软硬件协同设计的核心命题做AI芯片这行的人都有一个共识一颗芯片流片回来真正决定它能不能用的不是峰值算力标称了多少TOPS而是软件栈能不能把硬件里那些MAC阵列、SRAM带宽、NoC通路真正喂饱。我见过太多项目硬件指标漂亮得不行结果编译器生成的调度方案一塌糊涂实际推理吞吐只有理论值的30%不到。这就是软硬件设计脱节的典型症状。所谓AI芯片的软硬件设计本质上是在解决一个约束优化问题给定硬件资源计算单元数量、片上存储容量、片间带宽、功耗预算如何通过软件层面的调度、映射、量化、算子融合等手段让目标神经网络模型在满足延迟和精度要求的前提下尽可能高效地执行。这个问题的难点在于硬件架构一旦流片就无法修改而软件栈需要适配的模型却在快速演进——今天优化好的Transformer结构明天可能就被新的架构取代了。这篇文章适合三类读者一是正在做AI芯片架构定义的硬件工程师需要理解软件栈对硬件的真实需求二是做编译器或推理框架的软件工程师需要知道硬件底层的约束在哪里三是系统级设计者需要在软硬件之间做权衡取舍。我会从计算架构、存储层次、数据流调度、量化映射、编译优化这几个维度把AI芯片软硬件设计中那些文档里不会写但实际项目中一定会遇到的问题拆开来讲。2. 计算阵列的硬件选型与软件映射逻辑2.1 脉动阵列、SIMD与可重构数据流的取舍依据AI芯片的计算核心架构选择直接决定了后续软件栈的设计复杂度。目前主流方案大致分三类脉动阵列Systolic Array、SIMD向量机、以及可重构数据流架构。这三者没有绝对优劣关键看目标负载的特征。脉动阵列的优势在于数据复用率高。以矩阵乘法为例权重数据可以在阵列中流动一次与多个输入激活值完成乘加运算大幅减少对片上存储的访问次数。Google的TPU系列就是典型代表。但它的代价是灵活性差——阵列尺寸固定后遇到不规则的稀疏计算或小批量推理利用率会急剧下降。我实测过一个128x128的脉动阵列跑ResNet-50的卷积层利用率能到85%以上但跑BERT的自注意力层时因为序列长度动态变化利用率经常掉到40%以下。SIMD向量机则相反灵活性好适合处理element-wise操作和归一化层但数据复用率低对存储带宽要求高。可重构数据流架构试图在两者之间找平衡通过配置互连网络来适应不同算子但编译器的映射难度会显著增加。实际选型时我通常建议先明确目标模型集合。如果以CNN为主脉动阵列是稳妥选择如果Transformer类模型占比超过一半需要认真评估SIMD或混合架构。这里有个经验公式可以参考计算阵列的尺寸N应该使得目标模型中最常见的矩阵乘法维度M、K能够被N整除或接近整除。比如常见维度是768、1024、4096那么N取128或256就比较合适避免出现大量padding浪费。2.2 数据复用模式对片上存储带宽的倒逼计算阵列确定后下一个约束就是数据供给。AI芯片的性能瓶颈很少在计算本身而是在数据搬运。一个256x256的MAC阵列每个周期需要256个激活值和256个权重值如果片上SRAM每个周期只能提供128个值那计算单元就有一半时间在等数据。解决思路是提高数据复用率。卷积运算中权重可以复用多次对不同的输入像素激活值也可以复用对多个输出通道。软件层面需要做的是通过循环分块Loop Tiling和循环重排Loop Reordering让数据在寄存器、SRAM、DRAM之间的搬运次数最小化。我参与过一个边缘推理芯片的项目最初硬件团队给每个计算单元配了独立的权重缓存但软件团队发现实际模型中不同层的权重尺寸差异很大小层的缓存利用率极低。后来改成可配置的共享缓存池编译器根据每层的权重尺寸动态分配整体带宽利用率提升了约35%。这个案例说明硬件设计阶段就必须让软件团队介入否则很容易出现硬件资源分配与软件实际需求错位的问题。2.3 稀疏计算支持硬件加速与软件调度的配合稀疏化是当前AI芯片设计的热点。模型剪枝后权重矩阵中大量元素为零理论上可以跳过这些零值的计算和存储。但硬件要支持稀疏加速需要额外的索引管理和数据压缩逻辑。从软件角度看结构化稀疏如2:4稀疏每4个元素中保留2个非零比非结构化稀疏更容易被硬件高效利用。NVIDIA的Ampere架构就支持2:4结构化稀疏配合软件端的稀疏感知训练可以在精度损失很小的前提下获得接近2倍的吞吐提升。但这里有个坑稀疏矩阵的索引本身也需要存储和读取如果压缩率不够高索引开销可能抵消掉计算节省。我实测过当稀疏度低于50%时非结构化稀疏的收益往往为负。所以软件团队在决定是否启用稀疏加速时一定要先算一笔账节省的计算时间 vs 增加的索引解码时间。通常稀疏度要达到70%以上非结构化方案才有明显收益。3. 存储层次设计从寄存器到DRAM的数据搬运经济学3.1 片上存储容量与带宽的平衡点计算AI芯片的存储层次通常包括寄存器文件、片上SRAM有时分L1/L2、以及片外DRAM。每一层的容量和带宽差异巨大设计核心是让数据尽可能停留在高层级存储中。一个实用的计算方法是统计目标模型中各层算子的数据需求量输入激活、权重、输出激活然后看片上SRAM能否容纳最大层的工作集。如果不行就需要考虑分块计算把一层拆成多个子块依次处理。以常见的3x3卷积为例假设输入特征图尺寸为HxWxC输出通道数为K。如果采用im2col方式权重矩阵大小为9C x K输入矩阵大小为HW x 9C。片上SRAM需要同时容纳输入块、权重块和输出块。我通常建议SRAM容量至少能容纳最大层的权重 一个输入块 一个输出块否则编译器会频繁地在SRAM和DRAM之间交换数据带宽成为瓶颈。这里有个经验数据对于1080p输入、ResNet-50级别的模型如果片上SRAM小于2MB推理延迟会显著上升。因为大层的权重和激活无法同时驻留导致反复的DRAM访问。当然这个数字会随模型结构和量化位宽变化INT8量化后需求会减半。3.2 双缓冲与预取策略在推理流水线中的实际效果存储层次设计好之后软件调度需要解决的是如何让数据搬运和计算重叠。双缓冲Double Buffering是最常用的技术当计算单元在处理当前数据块时DMA引擎同时把下一个数据块从DRAM搬到SRAM。但双缓冲的效果取决于数据块大小和搬运时间的比例。如果搬运时间远大于计算时间双缓冲只能隐藏一部分延迟。我见过一个设计DMA带宽只有计算需求的60%结果双缓冲形同虚设计算单元仍然有40%的时间在等数据。改进方案有两种一是增加DMA通道数或提高DMA优先级二是通过软件层面的算子融合减少数据搬运总量。比如把卷积、BN、ReLU融合成一个算子中间结果不需要写回DRAM直接在SRAM中传递。这种融合在推理框架中已经比较成熟但需要编译器能够识别可融合的模式。3.3 片间带宽瓶颈多芯片互联时的数据划分策略当单芯片算力不够时就需要多芯片互联。这时片间带宽成为新的瓶颈。常见的互联方式包括PCIe、NVLink、以及各种自定义的SerDes链路。软件层面需要决定的是模型如何划分到多个芯片上。按层划分Layer-wise Partitioning实现简单但芯片间需要传递中间激活值通信量大。按通道划分Channel-wise Partitioning或按空间划分Spatial Partitioning可以减少通信量但需要硬件支持跨芯片的归约操作。我参与过一个双芯片推理系统的设计最初采用按层划分结果发现中间激活值的传输时间占了总延迟的45%。后来改成按输出通道划分每个芯片计算一半的输出通道最后通过片间链路做一次归约通信量减少了约70%整体延迟下降了30%以上。这个经验说明多芯片系统的软件划分策略必须和硬件互联拓扑一起考虑不能先定硬件再想软件。4. 量化与映射让模型在有限位宽下保持精度4.1 INT8量化的校准方法与精度损失控制量化是AI芯片软件栈中最关键的优化手段之一。把FP32模型转成INT8理论上可以获得4倍的存储节省和2-4倍的计算加速。但量化会引入精度损失需要通过校准Calibration来最小化。常用的校准方法包括最大最小值校准、KL散度校准、以及基于百分位的校准。最大最小值校准最简单但容易受离群值影响。KL散度校准通过最小化量化前后分布的差异来确定截断阈值效果通常更好但计算量稍大。我在实际项目中的经验是对于CNN类模型KL散度校准通常能把精度损失控制在1%以内但对于Transformer类模型尤其是注意力层的softmax输出量化误差会被放大需要更精细的处理。一个有效的技巧是对不同层采用不同的量化策略卷积层用INT8注意力层的softmax输入用INT16或保持FP16这样可以在精度和性能之间取得平衡。4.2 混合精度调度哪些层必须保留高精度并非所有层都适合量化。根据我的实测经验以下几类层通常需要保留较高精度第一层卷积直接处理输入图像量化误差会传播到后续所有层注意力层的QK^T计算数值范围大INT8容易溢出层归一化LayerNorm涉及均值和方差计算对精度敏感最终的分类层或回归层直接影响输出结果混合精度调度的难点在于硬件需要支持不同精度的计算单元或者至少支持精度的动态切换。如果硬件只支持INT8那软件层面只能通过缩放因子Scaling Factor来尽量保留动态范围。我通常建议在硬件设计阶段就考虑支持INT8和INT16两种模式虽然面积开销增加约15%但软件灵活性大幅提升。4.3 算子映射到硬件的约束检查清单量化完成后下一步是把算子映射到硬件。这个过程需要检查一系列约束约束项检查内容常见问题数据对齐输入/输出张量的维度是否满足硬件对齐要求非对齐访问导致性能下降50%以上算子支持硬件是否直接支持该算子不支持时需拆解或回退到CPU内存布局张量的内存排布是否匹配硬件偏好NCHW vs NHWC转换带来额外开销量化参数缩放因子和零点是否在硬件支持范围内超出范围导致精度异常并行度算子能否被拆分成足够的并行任务并行度不足导致计算单元闲置这份清单是我在多个项目中总结出来的每次映射新模型时都会过一遍。特别是数据对齐这一项很多性能问题都源于此。比如硬件要求输入通道数是16的倍数但模型某一层输出通道是12编译器就需要插入padding浪费25%的计算资源。5. 编译器的核心任务从计算图到硬件指令的翻译5.1 图优化阶段算子融合与常量折叠的收益边界编译器前端接收的是计算图如ONNX格式首先需要做图优化。最常见的优化是算子融合把ConvBNReLU合并成一个算子减少中间结果的存储和搬运。但融合不是越多越好。我遇到过过度融合导致寄存器压力过大的情况把太多算子融合在一起中间结果需要同时保存在寄存器中反而导致寄存器溢出性能下降。通常建议融合后的算子中间张量数量不超过寄存器文件容量的70%。常量折叠是另一个重要优化把模型中可以提前计算的常量表达式在编译期算好。比如BN层的均值和方差在推理时是固定的可以提前融合到卷积权重中。这个优化通常能减少5%-10%的推理延迟。5.2 调度阶段循环分块、重排与并行化的联合搜索调度是编译器最核心也最复杂的部分。给定一个算子编译器需要决定循环如何分块、循环顺序如何排列、如何并行化到多个计算单元。以矩阵乘法C A x B为例假设A是MxKB是KxNC是MxN。循环分块需要决定块大小BM, BN, BK使得A块、B块、C块能够放入片上存储。循环顺序决定了数据复用的模式如果K在最内层A和B的块可以被复用如果M或N在最内层则C的块被复用。这个搜索空间非常大手动调优不现实。现代编译器通常采用基于代价模型的自动搜索或者用机器学习方法预测最优配置。我在实际项目中的经验是对于常见的卷积和矩阵乘法可以预先建立一张调优表覆盖常见的维度组合编译时查表加微调比完全自动搜索快得多效果也稳定。5.3 代码生成指令级并行与数据级并行的协同调度确定后代码生成阶段需要把调度方案翻译成硬件指令。这里的关键是挖掘指令级并行ILP和数据级并行DLP。指令级并行指的是让多条指令在流水线中重叠执行。比如加载指令和计算指令可以并行只要它们访问的数据不冲突。数据级并行则是利用SIMD或向量指令一次处理多个数据元素。我见过一个编译器生成的代码计算单元的利用率只有50%原因是加载指令和计算指令没有很好地重叠。后来在代码生成阶段加入了软件流水Software Pipelining把加载、计算、存储三个阶段交错排列利用率提升到了85%以上。这个优化的关键是准确分析数据依赖关系确保重叠执行不会导致数据冒险。6. 实测中的典型问题与排查路径6.1 性能不达预期时的分层排查方法当芯片实测性能远低于理论值时需要系统性地排查。我通常按照以下顺序进行第一步确认计算单元利用率。如果利用率低于60%说明数据供给有问题重点检查存储带宽和DMA效率。第二步检查存储访问模式。用性能计数器统计各级存储的访问次数和命中率。如果L1命中率低说明数据分块策略有问题如果DRAM访问频繁说明片上存储容量不足或数据复用没做好。第三步分析指令流水线。查看是否有大量的流水线停顿Stall停顿的原因可能是数据依赖、资源冲突或分支预测失败。第四步检查量化精度。如果精度下降超出预期需要逐层分析量化误差找出敏感层。这套排查方法在多个项目中帮我快速定位了问题。有一次芯片实测吞吐只有理论值的25%按上述步骤排查后发现是编译器的循环分块参数设置不当导致权重数据被反复从DRAM加载。调整分块参数后吞吐提升到了理论值的70%。6.2 精度异常时的逐层对比技巧量化后精度下降是常见问题。定位方法很简单逐层对比量化前后模型的输出找出误差最大的层。具体操作是用同一批输入数据分别跑FP32模型和量化模型记录每一层的输出张量计算相对误差。通常误差会在某几层突然增大这些层就是敏感层。我处理过一个案例量化后模型精度掉了8个百分点。逐层对比发现误差主要来自第一个卷积层和最后一个全连接层。把这两层保留FP16后精度恢复到了只掉0.5个百分点。这个技巧的关键是不要盲目地对所有层采用相同的量化策略要根据逐层误差分析结果做差异化处理。6.3 多芯片扩展时的通信开销实测多芯片系统的性能扩展往往不是线性的。两片芯片理论算力翻倍但实际吞吐可能只提升60%-70%因为通信开销吃掉了部分收益。实测通信开销的方法是先跑单芯片记录延迟再跑双芯片记录总延迟和通信时间。通信时间可以通过片间链路的性能计数器获取也可以用总延迟减去计算延迟来估算。如果通信开销占比超过30%就需要优化数据划分策略。常见的优化方向包括增加计算密度让每个芯片处理更多数据减少通信次数、压缩通信数据量化中间激活值、以及重叠通信和计算在计算的同时传输下一批数据。我在一个四芯片系统中实测发现采用环形互联拓扑时通信开销随芯片数量线性增长而采用全连接拓扑时通信开销增长较慢但硬件成本更高。最终选择了混合拓扑相邻芯片全连接远端芯片通过环形链路通信在成本和性能之间取得了平衡。7. 软硬件协同设计的迭代节奏与团队协作7.1 架构定义阶段的软件预研方法硬件架构一旦流片就无法修改所以架构定义阶段的软件预研至关重要。我的做法是在硬件设计的同时用FPGA或仿真器搭建一个软件原型跑目标模型评估性能瓶颈。这个原型不需要和最终硬件完全一致但需要抓住关键特征计算单元数量、存储容量、带宽比例。通过调整这些参数可以快速评估不同架构方案的优劣。我参与过一个项目硬件团队最初打算采用大阵列小缓存的方案软件预研发现目标模型的权重尺寸很大小缓存会导致频繁的DRAM访问。后来调整为中等阵列大缓存虽然峰值算力下降了20%但实际推理吞吐反而提升了50%。这个案例说明软件预研能够避免硬件设计走入误区。7.2 流片后的软件适配与性能调优周期流片回来后软件团队需要在真实硬件上做适配和调优。这个周期通常需要3-6个月包括驱动开发、编译器后端适配、算子库优化、以及模型部署验证。我的经验是流片后的第一个月最痛苦因为硬件bug和软件bug混在一起很难定位。建议的做法是先跑通一个最简单的算子如向量加法确认基础功能正常然后逐步增加复杂度跑通单个卷积层、单个Transformer层最后跑完整模型。每一步都要有详细的日志和性能计数器输出方便定位问题。性能调优阶段重点关注计算单元利用率和存储带宽利用率这两个指标。如果利用率低于70%说明还有优化空间。常见的优化手段包括调整循环分块参数、优化数据布局、启用稀疏加速、以及调整量化策略。7.3 版本迭代中的回归测试与性能基线维护AI芯片的软件栈会持续迭代每次迭代都需要做回归测试确保新版本没有引入性能退化或精度下降。我建议维护一套性能基线选取一组代表性模型记录每个模型在当前版本下的延迟、吞吐、精度。每次发布新版本前跑一遍基线测试对比结果。如果某个模型的性能下降超过5%就需要排查原因。这套机制听起来简单但实际执行中容易流于形式。我的做法是把基线测试集成到CI流程中每次代码合并自动触发结果自动对比并生成报告。这样能够及时发现性能退化避免问题积累到发布前才暴露。8. 一些踩过坑之后才明白的设计原则做AI芯片软硬件设计这些年踩过的坑不少有几个原则是付出了代价才真正理解的。第一个原则硬件设计阶段一定要有软件团队参与。我见过太多项目硬件团队闭门造车定义了一套自认为优雅的指令集和存储架构结果软件团队发现根本无法高效映射主流模型。等到流片回来再改已经来不及了。正确的做法是硬件架构定义时软件团队就要提供目标模型的计算特征分析包括算子类型分布、张量尺寸分布、数据复用模式等。第二个原则不要追求极致的峰值算力要追求实际利用率。峰值算力是营销指标实际利用率才是用户价值。一颗标称100TOPS但利用率只有30%的芯片实际有效算力只有30TOPS另一颗标称60TOPS但利用率能到70%的芯片实际有效算力有42TOPS。后者才是更好的选择。提高利用率的关键在于存储层次设计和编译器优化这两方面的投入回报率往往高于单纯增加计算单元。第三个原则量化策略要因模型而异不能一刀切。不同模型对量化的敏感度差异很大CNN通常比较鲁棒Transformer则敏感得多。软件栈需要提供灵活的量化配置接口允许用户按层设置量化位宽和校准方法。同时硬件需要支持混合精度计算否则软件层面的灵活性无法发挥。第四个原则多芯片扩展的收益不是线性的通信开销会吃掉一部分算力增长。设计多芯片系统时要先算清楚通信量再决定互联拓扑和划分策略。如果通信开销占比超过40%扩展的收益就很有限了不如把单芯片做得更强。第五个原则编译器的调优表比自动搜索更实用。学术界喜欢研究自动调度算法但工业界更看重稳定性和可预测性。对于常见的算子维度组合预先建立调优表编译时查表加微调比完全依赖自动搜索更可靠。自动搜索可以作为补充用于处理调优表未覆盖的特殊情况。这些原则听起来简单但每一条背后都有实际项目的教训。AI芯片的软硬件设计是一个系统工程任何一方面的短板都会拖累整体性能。只有软硬件团队紧密协作从架构定义到流片后调优全程配合才能做出真正好用的芯片。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑