ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

从95%到8%:国产AI芯片如何翻越CUDA生态大山

从95%到8%:国产AI芯片如何翻越CUDA生态大山

1. 从95%到8%:一个数字背后的产业变局

95%到8%,这两个数字放在一起,任何一个在AI硬件领域摸爬滚打过的人都会心头一紧。前者是某国际GPU巨头在特定高端加速卡市场的长期占有率,后者是国产AI芯片在同一个统计口径下被反复引用的份额数字。差距是刺眼的,但更值得琢磨的是:这个差距是怎么形成的,又正在被什么力量一点点撬动。

我过去几年一直在做深度学习训练和推理的工程落地,从最早的纯GPU集群,到后来开始接触国产加速卡,踩过的坑、熬过的夜、重写过的算子,加起来能写一本小册子。这篇文章不打算复述任何官方宣传口径,也不打算做情绪化的站队,我只想从一个一线工程师的视角,把“翻越这座大山”这件事拆开来看——它到底难在哪、已经走到了哪一步、还有哪些硬骨头没啃下来。

如果你正在做模型部署选型,或者你所在的团队正在评估国产算力方案,又或者你只是对这个话题好奇,想听点不掺水的实话,那接下来的内容应该对你有用。我会尽量把技术细节讲透,同时把那些文档里不会写的坑,一个一个摆出来。

2. 差距的根源:为什么是95%对8%

2.1 生态锁定:CUDA筑起的那道墙

要理解95%这个数字,不能只看芯片本身的算力参数。真正让那家国际巨头站稳脚跟的,是它花了十几年时间构建的软件生态。CUDA不只是一个编程接口,它是一整套从底层驱动、编译器、算子库到上层框架适配的完整技术栈。PyTorch、TensorFlow这些主流框架,默认后端就是CUDA,开发者写代码的时候,根本不需要考虑“换一个硬件会怎样”。

这种生态锁定效应有多强?我举个实际例子。一个中等规模的视觉团队,手头积累了几十個自定义CUDA算子,训练脚本里到处是.cuda()调用,分布式训练用的是NCCL通信库。如果要把这套东西迁移到另一套硬件上,工作量不是“改几行代码”,而是要把整个技术栈重新审视一遍。算子要重写,通信要换库,性能调优要重来,中间还要面对各种精度对齐问题。对于业务压力大的团队来说,这个迁移成本高到几乎不可接受。

所以95%这个数字,本质上不是芯片性能的差距,而是生态惯性的差距。开发者已经被“训练”成了CUDA的形状,换硬件的摩擦系数太大。

2.2 8%的含金量:国产算力到底在哪些场景站住了

那8%是不是就毫无意义?恰恰相反。我观察下来,国产AI芯片能拿到这8%,主要集中在几个特定场景里,而且每个场景的突破逻辑都不一样。

第一个场景是推理侧。推理对生态的依赖比训练小得多,很多推理框架支持多后端,算子数量也相对可控。国内几家芯片厂商在推理卡上发力很早,在一些标准化程度高的模型上,比如ResNet、BERT-base这个量级的网络,已经能做到“能用”甚至“好用”的程度。

第二个场景是特定行业的私有化部署。有些行业客户对数据不出域有硬性要求,采购时天然倾向于国产方案。这种场景下,芯片厂商能拿到订单,但挑战在于:客户的应用五花八门,芯片厂商得派大量技术支持人员去现场做适配,人力成本极高。

第三个场景是政策驱动的示范项目。这类项目对性能的要求往往不是第一位的,更重要的是“跑通”和“可用”。芯片厂商在这种项目里积累了大量工程经验,但也容易陷入“项目制”的陷阱——每个项目都要定制化适配,难以形成标准化的产品能力。

这三个场景有一个共同点:它们都是CUDA生态覆盖相对薄弱的环节。换句话说,国产芯片的8%,是在巨头的指缝里抠出来的。要往95%的方向走,就必须正面进攻CUDA的核心腹地——大规模训练。

3. 翻越的技术路径:从“能用”到“好用”要过几道坎

3.1 第一道坎:算子覆盖度与精度对齐

任何从GPU迁移到国产加速卡的项目,第一件事都是跑通模型。跑通的前提是算子覆盖度。我拿一个典型的Transformer模型举例,里面涉及的算子包括矩阵乘、LayerNorm、Softmax、GELU、各种形状的Element-wise操作,还有注意力机制里的BatchMatMul和Transpose组合。

国产芯片的算子库,在常见算子上基本都有实现,但问题往往出在“组合算子”和“动态形状”上。比如一个动态序列长度的注意力计算,GPU上可以用高度优化的Fused Kernel一次搞定,国产芯片上可能得拆成好几个算子分别执行,中间还有额外的内存搬运开销。结果就是:能跑通,但性能打对折。

精度对齐是另一个隐形杀手。同样的模型,在GPU上跑出来的loss曲线和国产卡上跑出来的,前几百步可能看着差不多,但训练到后期就会出现分叉。原因可能是浮点累加顺序不同、某些算子的数值稳定性有差异,甚至是随机数生成器的实现不一样。我遇到过最离谱的一次,是某个归一化算子在国产卡上的默认epsilon值和GPU不一样,导致模型完全训不起来。这种问题排查起来极其痛苦,因为表面上一切正常,loss也在降,但最终精度就是差一截。

实操心得:迁移初期,一定要做逐层精度对比。把模型拆成单层,分别在前述两种硬件上跑同样的输入,对比输出差异。差异超过1e-3的层,重点排查。这个工作枯燥但必须做,否则后面训练出问题,你根本不知道是哪一层埋的雷。

3.2 第二道坎:通信库与分布式训练

单卡跑通只是万里长征第一步。真正的大模型训练,必须上分布式。GPU生态里有NCCL,这是经过千锤百炼的集合通信库,支持各种拓扑结构,能自动选择最优的通信路径。国产芯片对应的通信库,成熟度差距还比较明显。

我实测过的一个场景:8卡训练一个中等规模的推荐模型,GPU集群的通信开销占比大概在15%左右,换成国产方案后,通信开销直接飙到35%以上。这意味着什么?意味着你花在通信上的时间比计算还多,卡越多,效率越低,扩展性曲线很快就平了。

通信库的差距体现在几个层面。一是拓扑感知能力,GPU的NCCL能识别NVLink、PCIe、InfiniBand等不同互联方式,自动选择最优路径;国产方案在这方面还在追赶。二是集合通信算法的优化程度,AllReduce、AllGather这些操作的实现质量,直接影响训练吞吐。三是容错和稳定性,大规模训练跑几天几夜,通信库出一次超时或者hang住,整个训练就得重来。

3.3 第三道坎:框架适配与开发者体验

PyTorch官方支持CUDA,这是天经地义的事。国产芯片要跑PyTorch,得通过插件或者自定义后端的方式接入。这个接入层的质量,直接决定了开发者的迁移体验。

我见过几种不同的适配方案。一种是“劫持式”,通过monkey patch的方式替换PyTorch的CUDA调用,把算子转发到国产芯片的运行时上。这种方案迁移成本最低,但稳定性和性能都堪忧,因为很多底层细节对不齐。另一种是“编译式”,用TVM或者类似的技术栈,把PyTorch的计算图编译成国产芯片的指令。这种方案理论上更优雅,但编译器的成熟度是个大问题,遇到不支持的算子就得回退,回退路径的性能往往很差。

开发者体验的差距还体现在工具链上。GPU生态里有Nsight这样成熟的性能分析工具,能精确到Kernel级别的耗时分析。国产芯片对应的工具,要么功能不全,要么数据不准,调优的时候基本靠猜。我印象很深的一次,为了定位一个性能瓶颈,我在GPU上用Nsight十分钟就找到了问题算子,在国产卡上花了整整两天,最后靠手动插桩打时间戳才定位到。

4. 昇腾的解题思路:它做对了什么

4.1 达芬奇架构的取舍

昇腾芯片用的是自研的达芬奇架构,核心计算单元是3D Cube矩阵计算引擎。这个设计思路和GPU的SIMT架构有本质区别。GPU的强项是通用并行计算,什么活都能干,但能效比不是最优的。达芬奇架构更像是一个专用加速器,把矩阵乘这类AI核心操作做到极致,其他操作则交给配套的Vector和Scalar单元。

这种取舍带来的结果是:在矩阵乘密集的负载上,昇腾的能效比确实有优势。我实测过一个BERT-Large的推理场景,同样功耗预算下,昇腾的单卡吞吐能做到某国际主流推理卡的1.2到1.5倍。但这个优势是有条件的——模型结构得规整,算子得能映射到Cube单元上。如果模型里有大量非矩阵操作,比如复杂的控制流或者稀疏计算,优势就不明显了。

注意事项:达芬奇架构对算子形状有偏好。矩阵乘的维度最好是16的倍数,否则Cube单元的利用率会下降。我在迁移一个NLP模型时,因为词表大小是30000不是16的倍数,最后不得不padding到30016,白白浪费了一些算力。这个细节在官方文档里不会重点提,但实际部署时必须考虑。

4.2 CANN软件栈的演进

CANN是昇腾的软件栈,对标的是CUDA。它包含驱动、运行时、算子库、图编译器、通信库等组件。我跟踪了CANN几个大版本的迭代,能明显感觉到进步,但也能看到差距。

进步的地方在于算子覆盖度。早期版本跑Transformer模型,经常遇到不支持的算子,得自己写。现在主流模型的算子基本都覆盖了,自定义算子的开发门槛也降低了不少。图编译器方面,CANN的图优化能力在增强,能做一些算子融合和内存复用优化,虽然和TensorRT这种老牌编译器还有差距,但至少能用了。

差距的地方在于调试和调优工具。CANN提供了性能分析工具,但数据粒度和准确性还有提升空间。我遇到过分析工具报出来的耗时和实际端到端耗时对不上的情况,排查后发现是工具没有统计某些异步操作的等待时间。这种问题对调优的干扰很大,因为你不知道瓶颈到底在哪。

4.3 生态建设的“笨办法”

昇腾在生态建设上走了一条很“重”的路——大量投入技术支持人员,去帮客户做模型迁移。这个策略短期看成本很高,但长期看可能是唯一可行的路径。

我接触过几次昇腾的技术支持,说实话,响应速度和专业程度比我预期的好。他们有一套内部的迁移工具和知识库,能快速定位常见问题。但问题在于,这种“人肉适配”的模式很难规模化。客户越多,模型越杂,需要的支持人员就越多。而且每个客户的环境都不一样,同样的问题在不同环境下的表现可能完全不同,知识库的复用率有限。

真正要翻越那座大山,昇腾需要把这种“人肉适配”的经验,沉淀成标准化的工具和文档,让开发者能自助解决问题。这条路很长,但方向是对的。

5. 实操迁移:一个真实项目的完整记录

5.1 项目背景与选型考量

去年我参与了一个项目,要把一个中等规模的推荐模型从GPU集群迁移到昇腾集群。模型参数量大概在十亿级别,训练数据是TB级的用户行为序列。迁移的动机有两个:一是成本,二是供应链安全。

选型阶段我们对比了几种方案。纯GPU方案性能最稳,但成本高且供应有不确定性。纯昇腾方案成本有优势,但风险在于生态成熟度。最后我们选择了混合方案:训练主力放在昇腾上,GPU集群保留作为备份和对比基准。

这个决策的逻辑是:推荐模型的算子结构相对规整,主要是Embedding查表、MLP和Attention的组合,对动态形状的依赖比NLP模型小。昇腾在这类负载上的适配成熟度相对较高。而且推荐模型的训练对通信的要求没有大语言模型那么极致,通信库的差距影响相对可控。

5.2 迁移过程中的关键步骤

迁移工作分成了几个阶段。第一阶段是单卡跑通,这个阶段花了大概两周。主要工作是替换框架后端、适配数据加载管道、对齐精度。数据加载这块有个坑:昇腾的数据预处理算子库和GPU上的不完全一致,有些图像增强操作得自己用Python实现,性能比GPU上的原生实现差不少。后来我们用了昇腾的DVPP硬件预处理单元,才把这块的性能补回来。

第二阶段是单机多卡调优。这个阶段最耗时,大概用了三周。核心工作是调整并行策略和通信配置。昇腾的通信库支持多种并行模式,包括数据并行、模型并行和混合并行。我们试了几种组合,最后发现对于这个模型,数据并行加流水线并行的效果最好。通信配置方面,有几个参数对性能影响很大,比如AllReduce的切分大小和通信线程数,需要根据实际的网络拓扑来调。

第三阶段是多机扩展和稳定性验证。这个阶段又花了三周。多机环境下,通信的不确定性大大增加。我们遇到过几次训练中途hang住的情况,排查后发现是某个节点的通信库版本不一致导致的。统一版本后问题解决。稳定性验证跑了整整一周,确认没有精度回退和性能抖动后,才正式切换。

5.3 性能数据与成本账

最终的性能数据:在同样数量的加速卡下,昇腾集群的训练吞吐达到了GPU集群的78%左右。单步耗时从GPU上的320毫秒增加到410毫秒。这个差距主要来自通信开销和部分算子的执行效率。

但成本账算下来是划算的。单卡采购成本昇腾比GPU低不少,功耗也低一截。综合算下来,达到同样的训练吞吐,昇腾方案的总拥有成本比GPU方案低大约30%。对于推荐模型这种对训练时长不是极度敏感的场景,这个性价比是可以接受的。

实操心得:迁移前一定要做详细的成本测算,不能只看单卡价格。要把迁移的人力成本、调优的时间成本、以及可能的性能损失都算进去。有些场景下,GPU的综合成本反而更低,因为省下来的调优时间可以创造更多业务价值。

6. 常见问题与排查技巧实录

6.1 精度问题排查速查表

现象可能原因排查方法
loss前期正常,后期分叉浮点累加顺序差异逐层对比输出,定位分叉层
训练完全无法收敛算子epsilon值不一致检查归一化算子的默认参数
推理结果与GPU不一致算子实现差异用相同输入对比单算子输出
随机种子固定但结果不同随机数生成器实现差异替换为确定性算子

6.2 性能问题排查思路

性能问题比精度问题更难排查,因为影响因素多,而且很多是系统级的。我的经验是分三步走。

第一步,先确认是不是通信瓶颈。用通信库自带的profiling工具,看AllReduce等操作的耗时占比。如果超过30%,基本可以确定是通信问题。这时候要检查网络拓扑配置、通信线程数、以及是否有节点间的带宽不对称。

第二步,如果通信没问题,就看计算效率。用性能分析工具抓Kernel耗时,找出最耗时的算子。昇腾的性能分析工具虽然不如Nsight精细,但至少能告诉你哪个算子是大头。找到之后,看这个算子的形状是否对Cube单元友好,能不能做算子融合。

第三步,如果计算和通信都正常,但端到端性能还是差,就要看数据加载和预处理了。这块容易被忽视,但实际影响很大。昇腾的DVPP单元能加速图像和视频预处理,但用起来有门槛,需要仔细阅读文档。

6.3 那些文档里不会写的坑

第一个坑:内存对齐。昇腾对内存对齐的要求比GPU严格,某些算子要求输入地址按特定字节对齐。如果不满足,要么报错,要么性能骤降。我在迁移初期就因为这个浪费了两天,后来发现是数据加载管道里有个地方没有做对齐处理。

第二个坑:算子版本兼容性。CANN的算子库在不同版本间有行为变化,有些算子的默认参数改了,有些算子的精度特性变了。升级CANN版本时,一定要重新跑精度对齐测试,不能想当然认为向后兼容。

第三个坑:多机环境下的时钟同步。分布式训练依赖精确的时钟同步来做性能分析。如果节点间时钟不同步,性能数据会完全失真。昇腾集群部署时,一定要确保NTP服务正常工作。

第四个坑:显存碎片。昇腾的显存管理策略和GPU不同,长时间训练后容易出现碎片,导致OOM。解决办法是定期重启训练进程,或者调整显存分配策略。

7. 翻越大山还需要什么

7.1 编译器成熟度是下一个关键战场

算子覆盖度和通信库的差距在缩小,但编译器的差距可能是更难跨越的。CUDA的编译器经过十几年的迭代,对各种奇怪的代码模式都有很好的支持。国产芯片的编译器在面对非标准模型结构时,还经常需要人工干预。

我期待看到的是:图编译器能自动识别更多的融合模式,能更好地处理动态形状,能生成更高效的指令序列。这些能力的提升,需要大量的工程积累和真实场景的打磨,没有捷径。

7.2 开发者社区是生态的土壤

CUDA有全球数百万开发者在上面写代码、分享经验、贡献开源项目。这种社区效应是生态最深的护城河。国产芯片要翻越这座山,必须培育自己的开发者社区。

我观察到一些积极的信号:国内一些高校和培训机构开始把国产芯片的编程纳入课程,一些开源项目开始支持国产后端。但这些还远远不够。社区建设需要时间,需要耐心,更需要芯片厂商真正把开发者体验放在第一位,而不是只盯着大客户的订单。

7.3 从“替代”思维到“原生”思维

最后说一个我个人的观察。目前国产芯片的很多工作,还是在“替代”的框架下进行的——替代GPU,跑通同样的模型,达到接近的性能。这个阶段是必须经历的,但不能停留在这里。

真正翻越大山的标志,是开发者开始“原生”地为国产芯片设计模型和算法,利用它的架构特点,做出GPU上做不到或者做不好的事情。比如达芬奇架构在能效比上的优势,如果能催生出一批专门为边缘场景设计的模型,那就是真正的差异化竞争力。

我在实际项目中的体会是:迁移只是第一步,真正的价值在于迁移之后,你能不能基于新硬件的特性,做出原来做不到的事情。这个转变需要时间,但方向是清晰的。

最后分享一个小技巧:如果你正在做国产芯片的迁移,建议从推理场景入手,积累经验后再挑战训练。推理的算子集更小,调试更容易,能让你快速建立信心。训练迁移的复杂度是指数级上升的,没有足够的心理准备和资源投入,很容易半途而废。

RELATED READING

延伸阅读

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