每次有大模型亮相,大家的目光基本都黏在榜单上:分数涨了多少、推理快了几倍、参数是不是又大了。但我一直觉得,真正值得追问的是另一件事:这些模型到底是怎么被“练”出来的。几千张卡同时开工,谁来保证它们不打架、不空转、不互相拖后腿?模型训练完,要上线扛住几百万用户,又是谁在跟显存、并发、延迟较劲?答案都指向同一群人——做 AI Infra 的工程师。
AI Infra 这四个字听起来云里雾里,通俗讲就是“AI 的基础设施”。算子优化、分布式训练框架、数据流水线、推理引擎、资源调度、监控告警,都在这个范畴里。这些活很少出现在论文里,却会在每一次模型发布时被默默检验。模型跑得顺,没人会想到他们;模型崩了,第一个被叫醒的也是他们。这篇文章我就把这群“看不见的人”到底在忙什么,一层层拆开讲清楚。做算法的人看完能明白下游发生了什么,做应用的人能知道性能瓶颈在哪,刚接触大模型的新人也能对整个底层有个完整轮廓。
1. 先画地图:AI Infra 到底在忙哪几摊事
1.1 算法和硬件之间,差了一座桥
很多人的认知里,大模型 = 模型结构 + 训练数据 + 算力。这句话没错,但它默认了一个前提:从你写的模型结构到 GPU 真正执行,中间是顺畅的。实际根本不是。
打个比方,算法工程师是餐厅里设计菜单的人,他们决定了菜品长什么样、口味如何。但菜单设计得再好,后厨动线混乱、炉灶不够、传菜员跟不上,出餐照样崩。AI Infra 工程师干的就是后厨设计师的活:规划灶台怎么摆、传菜路线怎么走、食材怎么备、高峰期怎么调度出餐顺序。
落到技术上,一层完整的链路是这样的:
模型结构定义 → 深度学习框架把它翻译成一张计算图 → 框架调度器把图里的每个计算节点交给底层算子库 → 算子最终在 GPU 上以并行方式执行。
算法工程师通常只碰第一层和最后一层之间的很小一段。框架层怎么解释这张图、算子库怎么在硬件上高效执行、多张卡之间怎么通信同步,这些才是 AI Infra 的主战场。这也是为什么很多算法工程师自己写模型没问题,一上多卡训练就各种“玄学问题”——因为你没看见中间那座桥。
1.2 四块核心战场
我做过的、接触过的 AI Infra 工作,基本可以归成四类:
算子层。模型里所有计算的最小单元,矩阵乘法、注意力、归一化、激活函数,每个都是一个算子。GPU 执行算子的速度决定了模型训练和推理的下限。优化好一个热点算子,整个训练速度可能直接提升 10% 甚至 30%。
分布式层。模型大到一张卡装不下,或者数据多到一张卡跑不完,就需要把任务切到多张卡、多台机器上。这里最难的不是“切”,而是切完之后的通信与同步。数据并行、张量并行、流水线并行、混合并行,都是在解决“切”和“合”的平衡。
推理与服务层。模型训练完只是第一步,对外提供服务是另一套完全不同的工程。怎么把模型压缩到能上线、怎么管理 KV Cache、怎么让几百个并发请求互不阻塞、怎么在延迟和吞吐之间选平衡点,全是这里的活。
数据与存储层。这个方向经常被忽略,但出问题的时候能急死人。训练数据读取慢、预处理跟不上 GPU 消费速度,再好的算子优化也白搭。数据流水线、缓存、格式转换、样本调度,都是实打实的工程问题。
这四块可以用一张表看得很清楚:
| 方向 | 核心问题 | 主要指标 | 常见产物 |
|---|---|---|---|
| 算子层 | 单个计算怎么执行最快 | 算子耗时、显存占用 | 算子库、融合内核、通信算子 |
| 分布式层 | 多卡怎么协作不拖后腿 | 加速比、通信占比、显存峰值 | 并行策略、调度器、通信库 |
| 推理服务层 | 模型怎么对外稳定服务 | 首字延迟、吞吐、稳定性 | 推理引擎、量化方案、压测工具 |
| 数据存储层 | 数据怎么喂得又快又稳 | 吞吐、延迟、重复率 | 数据管线、缓存机制、格式优化 |
1.3 为什么这些活总“看不见”
一个很现实的原因:AI Infra 的成果不以“新方法”的形式出现,而是以“模型跑得更快了”“成本降下来了”“系统没出事故”这样的形式出现。前者不可见,后者只有在出事时才被感知。就像电网,你只会注意停电那天,从来不会因为今天没停电而感谢电力工人。
还有一个原因:这行的人长期处于“性能指标”的世界里。同样一个模型,训练时间从两周压到十天,外行看起来毫无差别,内行知道这意味着几十万成本节省。很多 AI Infra 工程师习惯了跟数字打交道,不善也不愿意包装自己的成果。他们不站台、不发文、不解释自己做了什么。于是“看不见”就成了这行的常态。
2. 算子是模型里最小的“动作”,为什么值得死磕
2.1 一行代码在 GPU 上到底发生了什么
先聊算子。你在框架里写一行矩阵乘法,比如A @ B,背后发生的事情比你想象的多得多。
框架先要把这个操作记录到计算图上,然后调用底层库。底层库会检查输入的形状、数据类型,选择合适的 kernel 实现,再把数据从显存搬进寄存器,GPU 上几千个核心同时开工计算,最后把结果写回显存。这一整套流程,核心的“执行单元”就是算子。
一个深度学习模型的训练,一次迭代可能要执行几百上千个算子。每个算子的耗时哪怕只差零点几毫秒,乘上训练步数和卡数,结果就是几小时甚至几天的时间差。这也是为什么算子优化永远有市场——你优化的是全模型都绕不开的公共路径。
这里有个很关键的概念:kernel launch 开销。GPU 上执行一个算子,并不是瞬间完成。CPU 要先把指令和参数准备好,再提交给 GPU,这个过程本身就耗时。小算子的计算时间可能只有几微秒,但启动开销也差不多是几微秒,于是有一大半时间浪费在“调度”上。这类问题靠优化单个算子解决不了,得靠算子融合——把多个小算子合成一个大算子,减少启动次数。
2.2 算力再强,也要等“传菜员”
很多刚转行做 AI Infra 的人有个误区:觉得 GPU 算力强,算子就应该很快。实际上现代 GPU 上绝大多数算子跑不满算力,真正的瓶颈是数据搬运。
拿访存来说,GPU 内部的寄存器、共享内存速度极快,但往下一层是显存,也就是 HBM,速度差了大概一个数量级。算力单位是 TFLOPS,显存带宽单位是 GB/s,两者一除,你会发现一个残酷的事实:如果计算不能重复使用已经搬进来的数据,算力再高也白搭。
我用传菜员的类比解释过很多次:算力是一个厨艺极好的厨师,显存带宽是传菜员。厨师一分钟能炒三十道菜,但传菜员一分钟只能端十盘食材进来,那厨师就得干等。算子优化的本质,就是让食材尽量一次多端进来、在厨房里反复使用。
具体手段就那么几种套路:
分块(Tiling)。把大矩阵切成小块,让每一块能塞进 GPU 的共享内存,反复使用后再换下一块,减少对显存的访问次数。
向量化。让一次内存访问尽量多带几个数据回来,提高访存效率。
利用专用计算单元。现代 GPU 有专门加速矩阵运算的单元,算矩阵乘的时候能用上,算力比普通核心高出不少。但要用上它,数据格式、分块方式都得配合。
流水线调度。让数据搬运和计算重叠,一边搬下一块数据,一边算当前这块。听起来容易,写起来全是细节。
2.3 算子融合:少搬一次数据就快一截
AI Infra 里最常用也最好用的优化手段,就是算子融合。原理不复杂:相邻的几个算子如果中间结果不需要保存,就把它们合成一个算子。
训练里最常见的一串操作:输入 → 加残差 → LayerNorm → Dropout → 输出。如果你用朴素实现,每一步都要把中间结果写回显存,再读出来给下一步。残差一个中间张量、LayerNorm 一个中间张量、Dropout 再一个,光搬运开销就占了很大比例。
融合之后,整个过程在共享内存里完成,只在最开始读输入、最后写输出。数据搬运量能减少一半以上,kernel launch 次数也少了。这类融合现在很多框架已经自动做了,编译器层面也有自动融合的能力。但底层推理引擎、自定义算子里,手写融合仍然是家常便饭。
2.4 一个注意力机制的重写,给整个行业上了一课
这几年 AI Infra 圈子里最有代表性的案例,就是 FlashAttention 这类工作。它的价值不在于单纯把算子写快,而是把一个工程问题重新变成了算法问题。
标准的注意力计算,要先生成一个 N×N 的分数矩阵,N 是序列长度。序列长度一长,这个矩阵的显存占用是平方级增长,很快就把显存吃光了。过去大家的处理方式就是省着用、或者干脆限制序列长度。
FlashAttention 的思路是:那我不生成完整的 N×N 矩阵了,分成一块一块算,每一块的中间结果用完就丢,反正在反向传播时还能再算一遍。结果显存占用从平方级降到了线性级,序列长度可以成倍拉长,而且因为利用了更快的内存层级,整体速度还提升了。
这件事给整个行业最大的启示是:优秀的优化不是死磕微操,而是重新审视计算模式。算子优化的天花板,往往取决于你对这个算子背后数学本质的理解。很多人觉得 AI Infra 就是调参和写写内核,实际上真正的高手是在算法层面做“重新设计”。
2.5 什么时候才值得自己写算子
我在项目里见过不少新人,上来就想手写 CUDA 算子,觉得官方库不够快。我的建议一直很直接:先别写,拿数据说话。
完整的流程应该是这样:
先用分析工具跑一遍,看时间花在哪个算子上了。如果这个算子只占总耗时的 2%,手写优化的收益再高也无非 2%。反过来,如果注意力占了 40% 的时间,那这里的每一分优化都值钱。
确认热点之后,优先用低成本的方案:算子融合、混合精度、调整数据布局。这些改动小、风险低。只有这些做完还不够,才值得投入人力去手写内核。而手写的时候,一定要先看官方库做了什么、为什么慢,再动手。我看过太多人写出来的自定义算子,因为没处理好数据对齐和边界,跑得比官方库慢一倍还多。
3. 分布式训练:当“一张卡装不下”成为日常
3.1 三种切法:切数据、切权重、切层级
模型规模涨到今天,单卡显存已经不可能装下一个完整的百亿级模型。分布式训练是必经之路。核心就一个词:怎么切。常见的切法有三种。
数据并行是最直观的:每张卡放一份完整的模型,训练数据切成多份分给每张卡。大家各自算自己的梯度,然后通过通信把梯度汇总,再同步更新参数。问题在于,模型太大的时候,单卡装不下模型本身,数据并行就不成立了。
张量并行是把一个算子的计算切成多块。比如一个大矩阵乘法,按行切分给多张卡,每张卡算自己那一块,最后拼回完整结果。这种方式能装下超大模型,但算一层要通信一次,通信压力大。
流水线并行是另一种切法:按模型的层来切。前几层放第一张卡,中间几层放第二张卡,后几层放第三张卡。数据像流水线一样从前到后流过去。好处是每张卡只存一部分层,坏处是流水线会有“气泡”——前面的卡算完了,后面的卡还在忙,空闲等待不可避免。
现实中基本没人只用一种切法。大模型训练几乎都是混合并行:外层用数据并行,内层用张量并行和流水线并行,比例根据集群拓扑和模型结构调。这个“调”的过程,就是分布式 AI Infra 工程师最常做的事。
3.2 通信才是“多卡不快”的元凶
很多人第一次跑多卡训练,期待加速比接近线性——两张卡就快两倍。现实往往是一张卡变两张卡,只快了 1.6 倍;四张卡只快了 2.5 倍。问题出在哪?通信。
数据并行里,每一步训练结束都要做一次全量梯度同步。这个操作的学名是 AllReduce,所有卡的梯度要汇聚成一个整体,再分发回去。最经典的实现是 Ring AllReduce:所有卡排成一个环,数据沿着环流动,每张卡不断跟邻居交换梯度碎片。理论上通信量是总梯度的两倍除以卡数,听起来还行,但通信时间跟消息大小、集群带宽直接相关。
这里有个残酷的数学现实:通信时间随卡数增长,计算时间随卡数下降,两者一叠加,加速比必然趋于饱和。到了几百张卡的规模,你可能看到的是:计算只占 50% 时间,剩下全在等通信。就好像一个团队开会,人越多,每个人发言时间越短,但“汇总大家意见”的协调成本反而越高。
做分布式优化的核心工作,就是想尽一切办法让通信和计算重叠。计算梯度的时候同时开始通信,梯度算完直接发出去,不用干等。这需要精细的流水线调度,也是为什么框架层面的优化能带来实打实的收益。另外,模型越大,单次通信的数据量越大,这时候用更高速的互联网络、或者优化通信算法本身,比增加显卡数量更管用。
3.3 显存的极限省法
模型装不下,除了并行切分,还有另一路思路:把显存里的东西省着放。
训练时显存主要被四样东西占着:模型参数、梯度、优化器状态、中间激活值。很多新人不知道,优化器状态才是最大的开销。每次更新参数,优化器要记录每个参数的历史动量和方差。用 Adam 的话,每个参数要额外存 8 个字节的状态,模型参数本身还不到 4 个字节。换句话说,光优化器状态就占了显存的大头。
ZeRO 系列的思路就是抓住这一点:既然优化器状态占得多,那就把它切开分到所有卡上,每张卡只存自己那一份,用时再临时汇总。效果立竿见影,显存占用直线下降,而且通信量也比朴素的张量并行小得多。
另一招是激活重计算。前向传播的时候,中间每一层的激活值都会被存下来,供反向传播使用。这是一大块显存开销。重计算的思路是:前向时不存,反向时重新算一遍。代价是计算量增加,收益是显存直接省掉一大块。对大模型来说,这是一个非常划算的交换。我记得有次给一个训练任务开了激活重计算,显存峰值降了接近一半,训练时间只涨了不到三分之一。用时间换空间,在显存就是钱的场景里,这笔账很划算。
3.4 一组训练参数是怎么算出来的
分布式训练的配置不是随便拍的。我给你拆一个实际场景。
假设一个模型要训练 2000 亿 token 的数据,集群有 2048 张卡,每张卡一次能处理 2 个样本(每个样本约 4096 token),那每一步喂进去的 token 数是:
2048 × 2 × 4096 ≈ 1677 万 token/step
整个训练需要的步数就是:
2000 亿 / 1677 万 ≈ 11927 步
如果每步耗时 8 秒,纯计算时间大概 11927 × 8 ≈ 95416 秒,也就是差不多 26.5 个小时。当然,这个计算非常理想化,实际还要加上通信开销、数据加载、checkpoint 保存、故障重启带来的时间损失。但做基础设施的人心里必须时刻有这本账:每一步、每一秒、每一块显存,最终都要换算成训练时间和成本。
配置里的另一个常见参数是梯度累积步数。很多时候单卡单步能放的样本数很少,为了让全局 batch size 达到要求(比如为了训练稳定性要保持 400 万 token 一个 batch),就得累积多步的梯度再更新。公式很简单:
全局 batch = 单卡 batch × 卡数 × 梯度累积步数
把需求倒推回去,步数自然就出来了。多了浪费训练时间,少了模型可能不稳定。这里没有标准答案,完全取决于你手头的硬件和模型特性,容易踩坑,需要慢慢试。
4. 推理部署:模型“学会”之后,还得学会“接客”
4.1 量化:让模型变瘦的代价与收益
训练完的模型,适合在训练环境跑,但不适合直接对外服务。推理部署要解决的第一件事,就一个字:省。省显存、省带宽、省钱。
量化是最常见的手段。训练时模型参数一般用 16 位浮点数存储,推理时可以压到 8 位整数甚至更低。效果非常直接:显存占用少一半,数据搬运带宽少一半,有些场景算力还能提升。一个 70B 级别的模型,FP16 光参数就要 140GB 显存,单卡根本装不下;压到 8 位之后只要 70GB,一张大显存卡就能跑起来。
但量化是有代价的。精度降低可能带来生成质量下降,尤其在小模型、低资源、高难度任务上更明显。我自己踩过最大的坑是:不能只测一个指标就上量化。你得跑一批覆盖各种场景的测试题,对比量化前和量化后的输出质量差距,还得看极端情况。一个稳妥的路线是:先只量化权重保留高精度计算,确认没问题后,再尝试连计算也量化。一步一步来,出了问题才好定位是量化哪一步造成的。
4.2 KV Cache 与连续批处理:推理引擎为什么不能照搬训练
用训练框架直接跑推理,性能会很难看。原因在于训练和推理的工作模式完全不同。
训练是批量、固定形状、重吞吐;推理是实时、动态长度、重延迟。尤其生成式模型,每个请求的输入输出长度都不一样,如果用固定的 batch 等待所有请求一起算完,最慢的那个请求会拖住所有人,其他人只能干着急等着。这就是朴素批处理的致命问题。
大模型生成还有一个特别的开销叫 KV Cache。模型每生成一个 token,注意力计算都要用到之前所有 token 的键值矩阵。如果每次都从头算,计算量随长度增长很快,所以推理引擎会把已经算好的 K 和 V 缓存下来,新的 token 直接复用。KV Cache 占显存的速度非常惊人。
我给你算笔账:一个 7B 级别的模型,假设 32 层、隐藏维度 4096,每生成一个 token,KV 缓存需要的显存大约是 2(K 和 V 两组)× 32 层 × 4096 维度 × 2 字节 ≈ 512KB。如果上下文长度为 4096,单个请求就要吃掉约 2GB。同时服务 16 个请求,光 KV Cache 就是 32GB 显存。这还没算模型本身。所以 KV Cache 的管理,直接决定了推理服务能同时扛多少并发。
现代推理引擎为此做了两件很关键的事。一是连续批处理:不再等一个 batch 统一结束,而是谁算完谁走,新请求随时插进来,GPU 利用率大幅提升。二是KV Cache 分页管理:把缓存按固定大小的块来分配和管理,就像操作系统的虚拟内存,按需分配、不够再换,避免浪费和碎片化。
4.3 压测三板斧:延迟、吞吐、稳定性
推理服务上线前,压测是逃不掉的。压测不能只测一个数字,至少三组指标要一起看:
首 token 延迟(TTFT)。用户发一句话到收到第一个字的间隔。模型是流式输出的,首 token 延迟是最直接的用户感知。一般要做到几百毫秒以内,超出了用户就会觉得“卡”。
单 token 生成延迟(TPOT)。后续每个字生成的间隔。这个决定输出流畅度,最好稳定在几十毫秒量级。我见过有服务首 token 很快,但后面的字一会儿快一会儿慢,用户体验照样崩。
吞吐量。单位时间能处理多少请求、每秒能生成多少 token。它和延迟是跷跷板,并发越高,单请求延迟越拉胯。压测的意义就是找到那个平衡点——在延迟达标的前提下,把吞吐打到最大。
压测之外还有一项测试经常被忽略:长稳测试。跑一两个小时看不出问题,跑十几个小时,显存碎片、网络抖动、缓存淘汰策略的问题全出来了。我吃过这个亏,压测半小时全绿,上线第二天半夜就开始延迟飙升。从那以后我们所有推理服务上线前必须跑一整晚长稳。
5. 一次真实优化现场:从 profiling 到上线
5.1 先花半天时间,搞清楚时间都去哪了
我处理过一个典型任务:某个训练任务,2048 张卡,但加速比远低于预期。组里新来的工程师第一反应是“要不要换并行策略”,我拦住了。我说先别猜,跑一把 profiling 看看。
用一个分析工具跑一个训练 step,把每一步的耗时切开看:计算占多少、通信占多少、数据加载占多少、等待占多少。结果出来我们都愣了——通信只占 18%,数据加载占 12%,看起来都还好。真正的问题是有 35% 的时间 GPU 在“空转”,它既没在算也没在等通信,而是在等 CPU 把数据准备好。
这就是 profiling 的价值:它让你用数据替代猜测。没有这一步,我们很可能去优化通信,但真正的问题在数据管线,优化方向全错了。做 AI Infra 这些年,我最深的体会是,所谓“性能玄学”,大部分是你没用对工具就急着下结论。
5.2 按 ROI 排序,从“无损优化”动手
拿到 profiling 结果之后,我习惯把优化项分个类,按“收益/风险”排序。
排在最前面的永远是无损优化:算子融合、通信与计算重叠、调整数据加载的预取策略、开启混合精度。这些改动不动模型逻辑,收益确定性高,风险低。
比如那次诊断出来的 CPU 瓶颈,方案是给数据管线加预取和缓存,让 GPU 在算当前 batch 的时候,CPU 已经在后台准备下一个 batch 的数据。改动不复杂,但训练吞吐直接提了 22%。这种优化听起来不酷,恰恰是 AI Infra 最值钱的日常。
第二梯队是中等风险优化:调整并行策略、开启激活重计算、调整全局 batch。这些会改变显存和通信模式,需要重新验证训练稳定性,但也往往是突破性能瓶颈的关键。关键是要一个个来,一次只改一个变量,别把两个改动混在一起上线,否则出了问题你都定位不到是哪个改坏了。
5.3 上线不是部署,是验收加回滚
优化合入之后,很多人以为跑通了就是完事。我这边有套固定的验收清单,跑完才算数:
功能正确性。跑一批固定测试样本,和优化前比输出数值差异在可接受范围内。
性能达标。达到预期的提速目标,不能只快在单个 step 上,要连续跑几百个 step 看平均效果。
稳定性。长时间运行不掉点、不抖动。
成本核算。算清楚提速带来的成本降低和新增的复杂度是否匹配。
最后是上线策略。任何优化都有风险,所以回归步骤和回滚方案要先准备好。我见过因为一次性能优化没做回滚预案,结果模型训练到一半出问题,回滚又花了几天,整个排期全乱了。基础设施圈有句老话:优化失败不可怕,可怕的是没留后路。每次上线前把“如果出问题怎么办”想明白,比追求极限性能更重要。
6. 这些坑我都踩过:AI Infra 问题排查实录
6.1 显存 OOM,但不知道被谁吃了
训练任务跑着跑着报显存溢出,第一反应是调小 batch size,但很多时候调小了照样炸。正确的姿势是搞清楚谁在吃显存。
我常用的第一步是看进程实际占用,再用分析工具看训练 step 的峰值显存,看它发生在哪个阶段、对应哪个算子。还有一种很常见的情况:框架的缓存分配器会预占大量显存,运行的时候空闲块和已用块交错,看起来数字很高,实际碎片化严重。这种情况就不是调小 batch 能解决的,要么换更大的显存粒度管理,要么查一下是不是连续分配导致的碎片。
一个很实用的排查手段:逐段注释法。把模型分成几段,分别打印每段的显存峰值,很快就能定位是哪个模块在吃显存。这个办法土,但异常有效。
6.2 GPU 使用率低,是“闲”不是“空”
监控面板上 GPU 利用率只有 30%,很多人第一反应是加任务。但利用率低不等于 GPU 在休息,它可能是在等数据、等在通信、或者在执行一堆小算子导致频繁启动切换。
排查顺序我一般这么定:先看 CPU 侧是不是瓶颈,数据是不是喂不过来;再看是不是通信等待;最后看是不是算子太小太碎。每一步都有对应的指标可以看,都确认过之后,才好判断是改调度、改数据管线还是做算子融合。
6.3 多卡加速比上不去
多卡训练加速比不及预期,这是最多的咨询问题。排查思路也是先量化:用分析工具看一个 step 里计算时间和通信时间的占比。如果通信占比超过 30%,优先优化通信,比如调整通信与计算重叠、增大通信粒度、检查卡间互连的拓扑布线是否合理。
有个容易被忽略的坑:慢卡效应。集群里只要有一张卡因为散热、坏道或者被别的任务占了资源而变慢,整个训练步都要等它。这种问题看平均指标看不出来,得看每张卡的耗时分布。我现在养成一个习惯,多卡训练巡检时必看 max 和 min 的差距,超过 5% 就要警惕了。保证集群内所有卡的状态尽量一致,比调任何优化参数都重要。
6.4 推理服务延迟抖动
压测正常,上线就抖动,头大。排查时先区分抖动的来源:是首 token 延迟抖还是后续 token 延迟抖?是某个时刻突然整体变慢,还是个别请求特别慢?
常见原因就那么几类:并发波动导致队列积压、KV Cache 不够用导致频繁换出换入、其他任务抢占资源、显存碎片导致分配变慢。定位的办法是给服务加细粒度的监控指标,按时间段切分延迟,把异常时刻和当时的系统状态对齐。排查延迟问题最忌讳瞎猜,把时间线和指标对齐,原因才会自己浮出来。
6.5 排查问题之前,先立三面“规矩”
经验多了之后,我发现大部分排查事故,不是技术问题,是流程问题。先立规矩再干活,能省掉一半麻烦。
第一,所有改动留记录。谁、什么时候、改了什么、为什么改,写清楚。排查的时候先看最近改动,多半问题出在最后那一次变更。
第二,一次只改一个变量。同时调 batch、开混合精度、换并行策略,出了事你根本不知道是谁导致的。每次改一个,跑一步看效果,再改下一个。
第三,先测量再优化。没有分析工具数据支撑的优化,都是玄学。先量化,再动手,这是 AI Infra 这行最重要的工作方法。
这三条规矩立起来之后,我这边的问题平均定位时间至少缩短了一半。很多看起来“诡异”的性能问题,最后发现就是某个改动的副作用,有记录、有对比,一眼就能看出来。
7. 一点个人体会
做了几年 AI Infra,我最大的变化是,看一个模型的眼光不一样了。别人看它效果多好,我会想它训练时每步耗时多少、显存用了多少、上线要多少卡才扛得住。这个视角一旦建立了就回不去,因为你清楚,那些看起来“理所当然”的模型能力,背后全是工程人员拿时间、成本和踩坑换来的。
最后分享一个小技巧:定期给训练集群出“体检报告”,一张卡一张卡地列利用率、显存峰值、故障频率。很多隐患在变成事故之前,都会在数据里露出苗头。基础设施的工作就是这样,不出事是常态,出事了是失职。把功夫花在事前,比天赋异禀的救火更重要。