NPU升级为何通过编译却死在运行?

NPU升级为何通过编译却死在运行?
View on original source
Category: SciTech
Share
Archive
Like
[导读]NPU领域最危险的一类问题,就是编译阶段一切顺利,运行后却出现结果飘移、偶发超时或局部崩溃,因为固件、编译器和驱动实际并没有站在同一语义上。 很多升级事故不是模型本身有错,而是版本边界没被说清。NPU领域最危险的一类问题,就是编译阶段一切顺利,运行后却出现结果飘移、偶发超时或局部崩溃,因为固件、编译器和驱动实际并没有站在同一语义上。 编译通过并不代表运行兼容。离线编译器看到的,是一套算子描述、量化参数和调度能力假设;设备上真正执行的,则取决于固件里的微码、驱动协议和硬件步进。只要其中任何一层对某个算子的边界条件理解不同,比如 padding 取整规则、饱和舍入方式或张量布局对齐,模型仍能顺利生成二进制,却会在特定输入上输出不同结果。最麻烦的是,这类差异往往只在少数角落样本里暴露。 算子语义漂移比接口报错更难抓。接口字段不兼容通常会直接失败,团队还能立刻止损;语义漂移则让系统看起来能跑,只是慢慢变差。某次固件升级也许优化了某类卷积内核,却顺手改变了某个 fuse 规则的舍入路径;某个驱动版本也许增加了字段压缩,却让旧编译器生成的描述符在边界长度上被重新解释。现场只会看到'精度怎么突然差一点',很难第一时间想到是版本组合问题。 二进制缓存更会放大这种风险。为了缩短部署时间,很多平台会长期复用历史编译产物;若升级后没有强制核对编译器、固件和微码矩阵,旧二进制可能被新运行时继续加载。表面上省下了重新编译时间,实际却把不匹配的执行计划直接送到了现场。缓存命中本该是效率工具,一旦缺少版本签名,就会变成静默风险源。 量化参数格式变更也常被忽略。某些版本会调整 scale 存储顺序、零点打包方式或逐通道参数对齐规则,对应用层来说字段名没变,但解释方式已经不同。旧模型文件若没有明确 schema 标记,运行时就可能按新格式读取旧参数,结果不是完全报错,而是整层数值偏移。升级测试只看能不能加载,远远不够。 更稳妥的发布方式,是把驱动、固件、编译器和模型产物看作一组不可拆分的兼容矩阵。任何一层改动,都要触发最小回归集重新执行,并明确哪些旧产物必须失效。矩阵不一定要穷举所有组合,但至少要覆盖量产节点真实存在的版本路径,而不是只测最新全家桶。 回归样本也要针对边界条件选。普通样本往往测不出语义漂移,真正能暴露问题的是极端 padding、长尾激活、异常尺寸和多分支汇合输入。把这些样本纳入升级门禁,比单纯扩大样本数量更能发现风险。升级验证的目标不是证明大多数情况没事,而是尽早找出最容易出事的那一小撮。 发布后还应保留快速回退路径。若现场发现某批节点只在特定组合下异常,能够迅速锁定是固件问题、编译问题还是旧缓存未清,会比盲目整体回退更高效。版本信息、二进制签名和运行时计数器若都能随日志上报,定位速度会快很多。 所以,编译通过从来不是升级完成的标志。只有兼容矩阵、语义边界和缓存失效规则同时被管住,NPU版本演进才不会把问题留到运行现场再慢慢显形。

(0)Comments

 

A note on cookies

Newshunt uses essential cookies to keep you signed in and to remember your language and country, so the site works the way you expect. With your permission, we'd also like to use analytics cookies to understand how people use Newshunt and improve it over time.

Accepting only affects analytics. To learn more, view our Privacy Policy or Terms & Conditions.