ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

AI芯片软硬件设计:从架构到流片的协同实践

AI芯片软硬件设计:从架构到流片的协同实践 国产彩票平台安全吗开头≥200字前100字融入核心关键词“AI芯片”“软硬件设计”做AI芯片和做普通SoC给我的感觉差别最大的一点是AI芯片的软硬件设计基本不是在“定完架构之后让两个团队各干各的”而是从第一天起就得把指令集、计算阵列、存储层次、编译器优化空间甚至调试手段绑在一起考虑。这几年我跟着团队做了两代边缘侧AI芯片踩了不少坑也攒了一些经验。这篇系列第9篇我想专门聊聊从架构定义到流片验证这个阶段里那些做硬件的人容易忽略、但最后都被软件团队用脚投票回来的问题。文章里涉及的流程和参数都是基于常见实践补全的不一定适合所有场景但思路应该能复用。正文主体1. 为什么边缘AI芯片比云端芯片更需要“软硬件一起想”1.1 先定性能模型再谈上板我第一次参与AI芯片设计时团队的做法是最传统的硬件组先画框图、定MAC阵列规模、定缓存大小软件组等RTL冻结之后才开始写驱动和编译器。结果芯片回来之后跑一个8位的MobileNet类网络帧率只有预期的一半不到。后来排查发现问题不在算力而在数据搬运DMA配置开销太大小tensor的搬运时间比计算时间还长。这个教训让我彻底明白AI芯片的软硬件设计核心不在“硬件能算多快”而在“软硬件之间配合得有多顺”。从那以后我们不管做多大点儿的芯片第一件事一定是先定性能模型把计算、搬运、调度这三块的时间预算在Excel里先算清楚。说白一点云端芯片可以靠大算力、高带宽、众多核来“硬怼”边缘芯片没有这个条件。功耗、面积、价格每一样都在卡脖子。你如果不在架构阶段就把软件运行时的行为方式想清楚后面大概率要返工。1.2 把运行时开销当“一等公民”这里有个很关键的点要特别提一下我们平时估算算力习惯只看TOPS、算MAC数但这只是理论天花板。真正决定端到端性能的是数据在片上怎么流动。常见的运行时开销包括启动一个kernel的指令下发延迟通常几十微秒级别看似不多但小算子一多就露馅DMA传输的地址对齐限制导致不能按最紧凑的方式搬数据多核任务分配不均某些核闲着某些核排队等锁操作系统调度引入的抖动这在实时推理场景尤其致命。这些开销在做性能模型时都要按“每一层算子”去细算。我见过不少团队性能模型里只写了计算时间片内带宽写了一笔带过等到芯片回来才发现搬运速度跟不上计算速度连回炉重做的机会都没有。所以我建议任何AI芯片项目从Architecture Spec的第一版开始就要有“数据流预算表”这种文档逐层列出输入大小、权重大小、计算量、搬运量、理想耗时、实际耗时。后面做硬件裁剪、做软件调度全都拿这张表说话。2. 硬件设计里最容易被软件“反攻倒算”的四个决策点2.1 算力宏大的幻觉MAC阵列利用率不是白来的很多新的AI芯片架构师喜欢一上来就堆MAC阵列觉得MAC越多算力越高。但在实际网络中MAC利用率往往低得吓人。典型的例子是3x3卷积和1x1卷积的混跑3x3的乘累加是9次1x1只有1次如果硬件数据通路按9次设计跑1x1时硬件资源会大量闲置。而且不同层的输入通道数不一样有的层是32通道有的是64通道阵列宽度和输入通道对不齐就会出现一堆“无效填零”的cycle。我的经验是在你规划MAC阵列规模的时候一定要拿真实网络统计一遍各层的通道分布、卷积核尺寸分布然后再决定阵列的宽度和高度。否则你会设计出一个纸面数据很漂亮、实际效率只有30%的“费电大户”。2.2 数据进不了计算单元一切都是白搭芯片设计里有一句老话你买的DRAM带宽不是为峰值准备的而是为平均需求准备的。边缘芯片的DDR带宽本来就可怜再加上片内SRAM容量有限数据复用就成了关键。具体怎么做呢主要是靠“数据重用”。卷积有两个天然的重用方向输入重用的权重、权重重用的输入。如果你在写硬件架构时不把Dataflow数据流的方向说清楚编译器就不知道怎么生成DMA描述符。我们当时定的方案是小网络走“权重固定”的Output-Stationary大网络走“输入滑动”的Row-Stationary。然后编译器根据网络统计结果自动在两种模式之间切换。这需要硬件在寄存器级支持数据流模式切换而不是光在软件里做。这个决定对后续编译器实现是决定性的。2.3 片内存储的“欢愉”程度决定了调度器能有多激进片内SRAM不足时软件调度器就会变得特别保守因为不敢把大tensor都放在片上怕在计算过程中出现缓存溢出。结果就是频繁地搬数据、频繁地等待DMA完成。我们实测过如果片内缓冲减少一半调度器保守程度会大幅上升端到端性能可能下跌25%以上而不是“按比例跌”。这一点经常被硬件团队低估。所以如果你在做芯片规格我建议在定片上Memory大小时直接让软件团队参与“评审”把他们要用的ping-pong缓冲、中间结果暂存、权重预取的预算表拿出来一项一项对着加直到两边都点头为止。这也是软硬件协同设计最见功夫的地方。2.4 片内互连设计必须为“非规则访问”留后路边缘AI芯片现在不光是跑CNN还经常要跑点Transformer、语音前端这些网络里有不少非规则的操作比如对序列做索引、做动态形状的算子。如果片内互连只做了规则DMA搬运遇到这种操作就会瞬间拉胯。我们后来在互连设计里加了一条“小型随机访问通道”专门给这类非规则访问用代价是面积多花了不到3%但换来的是软件侧不用把所有模型都改写成一堆强制规整的算子。这个妥协非常值。我自己心里一直记着这个原则硬件上每多一分灵活性软件就少一堆补丁每少一分灵活性编译器就把它的丑陋暴露在功耗和时延上。3. 指令集设计与编译器一场“互相迁就”的婚姻3.1 少即是多指令集不要什么都想做AI加速器常常会陷入一个陷阱看到某个新算子很火就往ISA里加指令。加着加着指令集膨胀得不像样高密度模式反而不好优化。我们当时定的规矩是ISA的核心指令尽量少控制在120条左右新算子尽量用组合指令实现只有那种“稳定高频且组合开销过大”的才会单开一条指令。例如“卷积BNReLU”这种融合在ISA上就是一个融合指令编译器负责把它识别出来并映射上去。这样做的原因很简单指令越多验证越难编译器优化也越难软件开发者学习成本越高。在AI芯片这种快速迭代的领域指令集太复杂往往是延期最大的隐性杀手。3.2 编译器不要再背“性能不好”的锅了很多芯片公司的软硬件矛盾最后都归结为一句“编译器写得不好”。但我见的实际情况是很多时候是硬件约束太强编译器根本腾挪不开。比如数据对齐要求是128字节但你的某一层输出是通道数为10的tensor映射到硬件阵列上必然要填充到16的整数倍于是多了20%的死存储。这种浪费不是编译器优化能解决的而是硬件架构定义时就该考虑到的东西。我们后来做了一个调整在数据排布上支持“非对齐起始地址”的DMA描述编译器才有机会做“最小填充”排布。从效果来看这一条改动让不少小模型的片上存储占用下降了15%~20%对端到端时延有实实在在的帮助。反过来编译器团队也要向硬件团队透明地传递“哪些代码模式是硬的、哪些是软的”。我们每周的例会上软件组都会列出一张“硬件阻塞点清单”里面写着诸如“片内带宽足够但DMA描述符生成开销太大”“算子融合遇到中间层尺寸不匹配”这样的具体问题硬件组逐条去打勾。这种清单比任何KPI都管用。3.3 仿真器与性能模型越早越“土”越好在芯片RTL还没冻结时软件团队就开始写内核、调算子库是一个很反直觉但非常正确的做法。要在硬件还没影儿的情况下跑软件靠的就是仿真器。我们不搞特别复杂的二进制翻译而是先做了一个带Cycle近似计数的指令级模拟器能配上真实的Flash/Cache模型先让软件在指令流水线上“走起来”。这个模拟器精确度大约在±15%左右但对于早期架构探索和算法评估完全够用。到RTL快可用时再切换成更精确的RTL级仿真。我印象很深的一次是某个在模拟器上评估很好的网络在真正的RTL上只快了一点点一查原因是模拟器里忽略了缓存替换策略的惩罚模型。从那以后我们在模拟器里把缓存替换策略和页表行为都做成可配置的别再让这种低级差异骗过所有人。4. 从FPGA到流片验证策略的“软硬兼施”4.1 不要等到流片后再后悔没有做原型验证AI芯片设计里最贵的事情不是设计而是发现设计错了。晚发现一天可能就是几周的进度损失、几百万的流片费打了水漂。不管是FPGA原型还是emulation平台最好在RTL阶段就搭起来让软件团队能够在接近真实的硬件环境里开发。我们做过一个算力在20TOPS左右的边缘芯片FPGA原型频率大约只有目标频率的1/20但胜在接口行为完全真实。软件团队靠这个平台提前三个月就把固件层驱动、电源管理、中断处理都做完了等芯片回来物理层的适配只花了不到两周。这种提前量是真金白银换不来的。4.2 覆盖率别只看行覆盖率要看到“协议覆盖”验证CPU和验证AI加速器有个很大的差别AI加速器里的数据路径完全受软件控制覆盖率要看的是数据流模式、地址冲突模式、DMA重试场景、多核同时发起搬运这些上下文。行覆盖率低不代表没测全行覆盖率高也不代表数据调度就对。我的习惯是在验证计划里单列一类“协议覆盖率”把DMA描述符的各种组合方式、地址对齐的各种组合、不同尺寸tensor的组合都列成矩阵逐项打勾。这类矩阵其实比行覆盖率更能反映软硬件接口的真实完备性。4.3 可观测性设计长在芯片里的“手术灯”做芯片调试最怕的就是黑盒子。我们在芯片里专门放了一组调试观测总线可以实时观测各级缓存命中率、命令队列深度、DMA忙闲度以及MAC阵列的利用率。这些观测点不参与功能只是用来给软硬件团队一个真实数据。芯片一回来整套软件栈跑起来大家看到的第一反应几乎都是“哇性能计数器和模拟器里的预估差距这么大”。例如实测MAC利用率只有42%代码看起来并没有瓶颈但观测总线显示在卷积层输出后接了一个“取整除法”的非融合算子这个算子导致数据在cache和DRAM之间来回搬家。这种问题要是不带观测总线排查起来至少要双倍时间。5. 流片归来实测阶段的三板斧5.1 第一板斧电源域与时钟域芯片回来别急着跑最大的网络。先做电源域和时钟域的自检。很多AI芯片有多个电压域和多个时钟域如果DVFS调错了计算阵列会出现周期性的计算错误而且这种错误不是必现的时好时坏最不好查。我们用了一个“软件时钟控制”的方法把每个电压域可以动态升压的步进都暴露给固件让固件在烧机阶段逐个域、逐档位去跑压力测试。这个压力测试不是跑推理而是跑“CPU DMA MAC同时满载”的混合场景测的是电源噪声。电源噪声导致的时序违例只能靠这种组合场景逼出来。5.2 第二板斧端到端的模型量化虽然编译器支持低比特推理但从流片回来的芯片上跑量化模型还是会有一堆意外。最常见的是“部分通道饱和”网络里某些层的激活值分布不均而硬件加速器的量化参数是整层共享的用一层全局scale去量化就会导致个别通道精度雪崩。软件组的对策是在做量化训练时就把“逐通道”的scale支持到位而在硬件上为了控制面积只做了“全局scale 少数通道例外”的机制。这两者一结合基本能覆盖绝大多是实际模型。说句实在话AI芯片落地项目里七八成的问题最后都出在量化精度上而不是算力不够这个方向值得多花人力。5.3 第三板斧功耗特性与温升曲线边缘AI芯片的功耗跟跑什么网络、用什么数据分布关系非常大。如果不实测你根本不知道一款8W封装的芯片在跑某个大模型时峰值功耗能冲到多少。我们实测的项目里有一款芯片在DRAM带宽触顶时核心温度比估算值高了将近10℃就是因为内存控制器的开关功耗被低估了。从那以后我们在功耗模版里一定会单独列出“DRAM带宽占比”这个变量把它和芯片温升做成一张二维表格方便散热设计做参考。软件团队也会在运行时监控温度超过阈值就自动降频。这已经成了我们默认的最后一道保险。6. 复盘清单与设计文化6.1 每次流片后一定要做一次“软硬件合议”芯片行业有种不太好的文化就是硬件、软件分工太清除了在会议上互相甩锅平时很少真正合在一起设计。我的经验是每次流片回来之后不管结果好坏一定组织一次全团队的合议。合议不是看PPT而是直接把性能计数器、功耗曲线、编译器日志、网络层延迟表格摊在桌上一行一行地过。我们靠着这种合议把“看似正常但跑得慢”的模块揪出来好几处有一些是调度器策略太保守有一些是硬件状态机不是真并行。全组合议之后下一轮迭代才会真正把本轮学到的东西固化进设计。6.2 软硬件设计的“约定优先生效”任何芯片项目软硬件接口文档都会写得非常厚。但真正起作用的往往是几个核心约定。我们在项目开始之前先定这几个约定指令下发的最小粒度、缓存一致性的窗口模型、多核同步的协议以及异常处理的上报路径。这四个约定决定了大半个软硬件协作的方式。每周例会上都盯着它们看如果哪个约定要被破坏就要立刻启动变更评审。这是我见过最容易让大团队保持一致的做法。6.3 允许恶心的妥协但必须有文档记录做AI芯片没有完美处处是妥协。问题是有些妥协当下看起来不起眼过了半年却成了致命伤。所以我们的原则是任何软硬件之间的临时妥协都要在代码注释和设计文档里写清“为什么这么干”“约束是什么”“未来如果想改进应该从哪里下手”。我见过太多芯片团队硬件留了一个奇怪的地址映射软件为了适配又包了一层古怪的地址重映射后面的人根本看不懂。文档一页页写下来后面接手的工程师才能真正站在巨人肩膀上。结尾段落个人经验收尾≥150字做了这两年AI芯片我越来越觉得软硬件设计没有那么高深它本质上就是一个“互相留白、彼此托底”的过程。硬件多留一点灵活性软件就少一点补丁软件早一点介入硬件就少一些返工。我个人的体会是真正能让项目活下来的往往不是某一个惊艳的架构创新而是几十个看起来不起眼的软硬件妥协是否都被认真记录、被认真对待。如果这篇系列第9篇能让你在规划下一颗芯片或者下一版编译器时多想一次数据流、多看一眼片上带宽、多开一次软硬件合议那它就有价值了。大家在做AI芯片软硬件设计时还有什么踩坑经验欢迎一起聊聊。
RELATED READING

延伸阅读

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