☰
大模型背后的AI Infra:从算子优化到GPU显存管理
2026/10/14 7:45:15 网站建设 项目流程

前阵子有朋友问我,你们那群做AI Infra的人一天到晚到底在忙什么?我说,大部分时间我们不是在琢磨怎么把模型调得更聪明,而是在跟GPU显存、网卡带宽、算子调度这些“看不见的东西”较劲。他说他不信,说训练大模型不就是写写网络结构、喂喂数据,然后等Loss往下掉吗?我说你要真这么想,那说明你还没见过一个40GB的模型怎么硬塞进只能装24GB显存的卡里,也没见过训练跑到第七天突然节点宕机、整个进度归零的崩溃现场。

这篇文章我想把这些“看不见的人”的工作讲清楚。从最小的“算子”优化,一路拆到大模型训练和推理背后的AI Infra系统,聊聊我们平时到底在忙什么、为什么这些活不能省、以及如果你也想往这个方向走,哪些东西最值得啃。内容会比较干,但都是我踩过坑之后的真实理解,应该能让你对“大模型背后”这四个字有个完全不同的认识。

1. 从“算子”说起:模型跑起来之前,有人先跟数学打了个招呼

1.1 算子不是算法,是GPU的“精确动作”

很多做业务开发的同事第一次听到“算子”这个词,都会愣一下。算子对应的英文是Operator,在深度学习里,它指的不是“算法策略”,而是计算图上的一个基本运算节点。比如矩阵乘法是一次算子,ReLU激活是一次算子,LayerNorm是一次算子,Softmax是一次算子。你写一行x @ W,看起来只是调用了PyTorch的matmul,但这一行背后对应的是一个经过高度调优的CUDA kernel,它要在NVIDIA GPU上把输入矩阵切块、调度线程、组织共享内存、压满Tensor Core,才能跑出接近理论峰值的性能。

这里面的差距可以有多大?同样的一个矩阵乘法,Pytorch默认调用的通用实现和专门针对形状做特化的实现,性能可以差出3到5倍,如果你用的是FP16或者FP8格式,差距还能拉得更大。很多人在调优的时候发现模型跑得慢,第一反应是加卡、换显存更大的GPU,但往往真正的问题出在算子层面:kernel没有融合、访存模式不友好、或者根本没把Tensor Core用起来。换句话说,你在GPU上花的每一分算力,最后都要落到一个个算子头上,算子不快,别的都是空谈。

1.2 从裸算子到AI Infra,中间隔着三层分工

我自己的理解里,“大模型背后的人”大致可以分成三层,虽然很多公司边界模糊,但思考问题的方式完全不同。

第一层是算法工程师,他们关心的是模型结构怎么设计、数据怎么清洗、Loss怎么收敛。他们工作在“计算图”之上,很少关心GPU指令长什么样。第二层是框架与编译工程师,他们做的事情介于算子和算法之间,比如把PyTorch的nn.Module变成可以高效执行的中间表示,做算子融合、图优化、内存规划。第三层才是真正意义上的AI Infra工程师,负责把模型放到大规模集群里训练和推理,这包括并行策略、显存管理、通信优化、调度系统、容错恢复、推理加速等等。

我见过最典型的误解是:算法同学觉得自己改个网络结构,AI Infra的人就能让它在任何规模的集群上自动跑起来。但现实是,并行切分方式要跟着模型结构走,显存占用要一层一层算,通信拓扑要跟网络结构匹配。你改了模型的某个维度,后面整个分布式方案可能都要跟着调。所以这些年“AI Infra”火的背后,本质上是因为大模型的规模和复杂度已经超出了“单机调包”能处理的范围,它需要一整套系统工程来兜底。

2. 一个算子的自我修养:为什么一行乘法背后要优化半天

2.1 先测再调,不要靠感觉优化

我不太建议谁一上来就埋头读CUDA代码,做算子优化的第一步永远是Profiling,也就是量化瓶颈。以前我在某个做推理加速的项目里接手过一个服务,情况是单卡吞吐上不去,领导怀疑是模型太大、显存不够。我拿Nsight System跑了一遍,发现GPU的SM占用率只有30%,大部分时间都花在了等待数据从CPU侧拷贝到GPU侧,根本就不是显存容量的问题。

后来我把数据预处理的后处理部分从Python换成了异步加载,再把连续的小kernel合并成两三个融合kernel,吞吐直接翻了一倍。这个例子很老套,但我每次讲给新人听都有效,因为它说明了一个道理:算子优化的第一步,不是“我要写一个更牛的kernel”,而是先搞清楚瓶颈到底在计算、访存、还是通信。用PyTorch的话说,就是先看看torch.profiler的输出,kernel time、GPU utilization、Memcpy的占比,哪个占了头名,哪个就是要下手的地方。

2.2 Kernel融合:把十次数据搬运合并成一次

为什么要做kernel融合?我经常跟非技术同事打一个比方:想象你在厨房做饭,每次要拿一种调料都要从冰箱走到灶台再走回去,十种调料就要来回十趟。如果一次把所有调料都拿齐,菜一下子就做完了。GPU的世界里,每一次kernel launch都意味着数据要从显存读进寄存器、算完再写回显存,尤其是中间结果还要经过全局内存的往返。你做十个elementwise操作,就是十次读写全局内存;如果能把它们合并成一个kernel,读写次数就省成了两次,延迟和带宽压力全部降下来。

最典型的例子是LayerNorm,它本身有求均值、求方差、归一化、缩放偏移好几个步骤,但现代的实现早就把这些步骤合在了一个kernel里面,中间结果直接留在寄存器和共享内存里,完全不用绕到全局内存。再比如残差连接、Dropout、激活函数这三件事,在实践中也经常融合成一个算子。这样的小优化在单层网络里感觉不明显,但放到几千层的Transformer里,省下来的是实打实的训练时长。

2.3 FlashAttention这类“重写”才是算子的更高境界

比kernel融合更高一档的算子优化,是改变算法的访存复杂度。这里最出名的例子就是Attention的优化。标准Attention的复杂度是序列长度的平方,要计算完整的注意力矩阵,这个矩阵如果序列长度是4096,那就是1600万个数,存下来就是一堆显存开销。而FlashAttention的思路是:不把完整的注意力矩阵写出来,而是对Q、K、V做分块切分,让每一个计算块尽量在SRAM(即GPU上的高速缓存)里完成,通过重计算的技巧,把对HBM的访问量从O(N²)降到O(N)级别。

我第一次看完FlashAttention的论文时最大的震撼是,它没有改变数学结果,但通过精细的访存调度,把一个看似不可能省掉的O(N²)访存开销给打掉了。这类工作做多了以后你会发现,算子上限的突破很少靠硬件凭空变快,更多是靠“数学重排”加上“硬件调度”的双重配合,这也是为什么很多人觉得算子优化更像“在GPU上做算法设计”,而不是简单写写内核。

3. 训练大模型时,显存管理是精打细算的“物流调度”

3.1 一张显卡装不下的大模型

聊完了算子这个微观层面,我把镜头拉高一点,看看训练大模型时最头疼的问题:显存。你可能听过一个说法,训练一个7B参数的模型,光参数在FP16下就要14GB显存。但实际训练时你还要放梯度,梯度跟参数一样是14GB。然后是优化器状态,Adam优化器要为每个参数存一份一阶动量、一份二阶动量,加在一起又是28GB。你还没算激活值呢,光这三样就已经56GB了,一张80GB的卡看着好像能放,但真正放上激活值、中间缓冲区、通信缓冲区以后,马上就会爆。

而且这只是7B,放到70B、几百B参数的模型上,单卡装下整个模型这件事本身就是天方夜谭。这就引出了AI Infra最核心的一个命题:一个放不下的模型,怎么拆开放在很多张卡上,还能高效地一起干活?这里的“拆”是分很多维度的,每个维度都有不同的代价,这是所有做训练系统的人躲不开的“显式管理的折磨”。

3.2 反向传播的元凶:激活值才是显存大头

很多人以为大模型训练占显存最多的是参数,这是错的。我自己实测下来,激活值(activation)才是那个“会呼吸的显存杀手”。前向传播的时候,你把每一层的中间输出保存下来,是因为反向传播的时候要用它计算梯度。Transformer每层中间要存的东西不仅包括Hidden State,还包括Attention矩阵、Softmax的中间结果、LayerNorm归一化之前的输入等等。序列长度是4096、批大小一小,每层加起来就是好几个GB,层数一多直接指数级膨胀。

所以业界最常用的一招叫激活重计算,英文叫Activation Checkpointing。原理特别朴素:前向传播的时候不再保存每一层的激活值,只保存一小部分关键节点,反向传播需要某层激活值的时候,临时从保存的节点重新算一遍前向,再把需要用到的值算出来。它本质上是拿“计算时间”换“显存空间”,一般能省掉60%到70%的激活显存,代价是训练速度下降10%到20%。在很多场景下,这是唯一能跑起来的方案,你别嫌它慢,没有它模型根本塞不进卡里。

3.3 Offload与“换页”策略:GPU吃不下,CPU来兜底

激活重计算还是没解决问题怎么办?那就得把一部分状态“借”到CPU内存里,这就是Offload。很多做训练的同学一开始很排斥Offload,因为CPU和GPU之间的PCIe带宽比NVLink带宽差了一个数量级,频繁拷贝会把训练拖慢。但在显存不够用的硬约束下,Offload往往是从“跑不起来”到“能跑起来”的差别。

我这边的实践经验是把参数扎成块,按需加载到GPU上,用完了再挪回去,本质上就是一个显存层面的“LRU缓存策略”。你可以把它想象成仓库放不下货,只好在隔壁借了个便宜仓库,但每次取货都要花时间在路上。所以Offload的工程设计核心就是“什么时候搬、搬多大块、怎么尽量少搬”,这些都是需要根据你实际模型和卡的数量去算的,没有一个放之四海而皆准的参数。

4. 把一坨上千亿参数拆开:并行策略是系统工程的主战场

4.1 四种并行之间的关系:切batch、切权重、切层、切序列

如果一个模型大到单卡放不下,就得走上分布式训练这条路。我经常用一句话概括并行策略的世界:把一个大活拆成很多小活,分给很多人同时干,关键问题是每个人怎么干、谁来传话、传多少话。工程上常见的切法有四种。

数据并行最简单,相当于每个人都拿着完整模型,但看不同的数据批次,每算完一步,大家把梯度同步一下,这就要用All-Reduce通信。张量并行是把一个权重矩阵拦腰切成多块,放在多张卡上,每张卡算一部分,这适合单卡放不下某一层的矩阵运算,但代价是每次计算都要做好几轮通信。流水线并行是按层切,把整个模型按层分成好几段,第一张卡算前几层,第二张卡算后几层,数据像工厂流水线一样流过去,缺点是会有流水线气泡,一部分卡在等待。序列并行则是大模型时代比较新的玩法,把超长序列的注意力计算拆开,让多张卡一起算同一个序列块。

实际训练一个千亿级模型,几乎都是组合拳:数据并行在外面套着,里面再叠张量并行,中间穿插流水线并行。这个组合顺序非常讲究,因为每一层并行都会改变通信流量和显存分布,排列顺序不对,通信量能差出好几倍。这些东西听起来简单,真正搭配起来全是排列组合的学问。

4.2 通信是一切痛苦的根源

在所有并行策略里,最让AI Infra工程师头疼的从来不是计算,而是通信。张量并行每做一次前向后向传播,都要在Tensor Core上算完局部结果以后,用All-Reduce把分块结果合并起来,这个All-Reduce本身就要走NVLink把所有卡的中间结果汇总后再广播回去。层数一多,通信叠加起来,训练效率就上不去。如果你租的集群里,几张卡不在同一个物理节点上,还得走跨节点的RDMA网络,那延迟和带宽问题更明显。

我有一次帮一个训练任务排查效率很低的问题,GPU利用率看着很高,但其实大量空闲时间在等网络同步。后来把张量并行的组网从跨节点改成了单节点内,也就是把通信最密集的几张卡尽量放在同一台物理机器里,训练速度立竿见影提升了两成。所以做AI Infra的人看一个训练任务,第一眼看的是“这组并行策略跟底层网络拓扑匹不匹配”,而不是“算力够不够”。

4.3 训练跑到第七天GPU挂了,怎么优雅地爬起来

最后一个绕不开的话题是容错。大模型训练动不动就跑几周甚至几个月,中间任何一张卡宕机或者网络闪断,都会导致训练中断。如果没有容错机制,所有的进度都得从头再来,那种感觉我只能说是“花钱买崩溃”。常见的做法是在训练过程中周期性保存checkpoint,故障发生后从最近的checkpoint恢复,但保存checkpoint本身也有代价,太频繁会拖慢训练,太稀疏又容易丢太多进度。

现代AI Infra在容错上做了很多文章,比如异步保存checkpoint、把checkpoint写到分布式文件系统而不是本地盘、甚至设计了环形内存备份来降低恢复时间。还有一个很容易被忽视的细节:恢复之后,还要把集群里所有节点的随机数状态统一重置,否则数据加载顺序和模型初始化的随机性都会乱掉,训练出来的结果可能跟中断前对不上。这些坑单靠算法同学是想不到的,全部属于AI Infra的活。

5. 训练只是上半场,推理侧的工作同样满地鸡毛

5.1 推理最大的敌人是KV Cache

模型训练好只是万里长征走完一半,真正把它变成一个低延迟、高吞吐的服务,推理系统同样一大堆问题。推理跟训练最大的区别是,训练可以拿时间换空间,推理不行,你要在几百毫秒内给出响应,还要尽量卡住成本。

推理侧的显存大头从激活值变成了KV Cache。Transformer做生成的时候,每生成一个token,都要把前文所有token的Key和Value重新参与注意力计算。如果每次都重新算前文,计算量会随着序列长度线性增长,所以工程上会把前面的Key和Value缓存下来,这就是KV Cache。序列长度一长,KV Cache也变成显存巨兽,一个支持4096上下文长度的模型,并发一高,显存瞬间就告急。我见过不少推理团队被这个问题折腾得够呛,最后的解决思路要么是限制并发、要么是量化缓存、要么是动态批处理来尽量复用已有缓存。

5.2 吞吐与延迟之间的取舍:量化、投机解码、PD分离

推理优化的世界里,术语也多,但本质上都是在一个跷跷板上找平衡:延迟低,并发就少;并发高,延迟就容易炸。业界常见的手段有量化,把权重从FP16压到INT8甚至FP8,推理服务就能吃更多人;有投机解码(Speculative Decoding),先用一个小模型草拟好几个token,再用大模型一次验证,效果好的时候能接近两倍加速,但这个跟模型本身关系很大,不是所有模型都适合。

还有一个比较新的趋势叫PD分离,把Prefill阶段和Decode阶段分开部署。因为Prefill阶段是计算密集的,适合用高算力卡去算整段prompt;Decode阶段是访存密集的,适合用另一批卡专门处理逐步生成。两个阶段混在一起的时候,总会有人排队等,拆开以后整体吞吐能提升不少。这些方案听着都很酷,但每一个都要根据实际业务流量画像去调,不是装个包就能生效的。

6. 这群“看不见的人”的一天:定位卡、盯通信、背锅、拆雷

6.1 可观测性差是最要命的问题

说了这么多系统细节,我想再聊聊这群人日常的工作状态。其实AI Infra日常最多的时间不是写代码,而是“定位问题”。训练不收敛,是数据问题还是数值精度问题?GPU利用率低,是数据加载慢还是通信等待久?显存OOM,是哪一层激活值飙了?这些问题要回答,底层必须有一整套可观测性系统:GPU监控、通信时延监控、内存分配追踪、模型数据流profiling。

我自己最大的体会是,很多AI Infra团队的工作效率差,不是因为算法不行,而是因为监控不完善。出了问题全靠猜,这是最费时间的。所以我到一个新团队,第一件事永远是先把监控补齐:每个训练任务至少能实时看到GPU利用率、SM占用率、显存占用曲线、通信耗时占比、数据加载耗时。没有这些,所有优化都是瞎忙。

6.2 从“训练跑通”到“持续交付”的转变

以前做传统深度学习,Infra的压力主要在产品上线那几天;大模型时代不一样了,模型不是训完一次就完事,要持续迭代、持续调优,每次迭代都要重新评估算力集群的容量。模型越来越大,数据越来越多,成本压力也跟着上来,所以现在还要做容量规划、成本分析、混合调度。很多公司内部已经出现了GPU资源池的说法,模型训练占用多少卡、推理服务占用多少卡、临时任务能不能挤上去,全部要靠调度系统统一管理。

这个调度系统的目标已经不只是“把任务排上”,而是要能容忍异构GPU、混合并行策略、优先级抢占、自动扩容。今天早上领导说要跑一个500B模型的测试任务,晚上就有另一个团队说要上线一个低延迟推理服务,两边抢卡怎么办?这个博弈也是AI Infra日常的一部分,而且压力不小。

6.3 怎么跟“看不到这些事”的人协作

最后说一下那群“看不见的人”和其他岗位的沟通问题,这个我感触很深。算法同事提需求的时候,经常会说“你帮我多上几张卡不就行了”,但加卡不只是一个数字变大,要考虑数据并行的梯度同步会变慢、张量并行跨节点通信会变慢、显存分布要重新算,这些都会影响收益。不加卡吧,业务会觉得你不上心;加了卡吧,效果没达标,锅还是你的。

我后来总结出一条经验:跟不懂系统的人沟通,不要讲“通信开销”“并行切分”这些词,直接给预期收益和时间成本。比如“加两张卡最多提速10%,但要多花一天改配置,当前效率瓶颈是数据加载,不是算力”,这样业务侧一听就明白,也不会有不切实际的预期。AI Infra工程师本质上是在技术深度和业务期望之间做翻译,这个能力有时候比写代码还重要。

做AI Infra这些年,我自己最深的体会是:大家看到的是一个模型越来越聪明,背后其实是无数个俯身在GPU日志、网络拓扑和显存碎片里抠日子的人。他们做的活大多是别人看不见的,但缺了他们,所谓大模型就只是一堆压箱底的网络参数。如果你也对这套系统感兴趣,我建议从三件事入手:先把PyTorch的profiler用透,知道自己的模型瓶颈在哪;再去读一读FlashAttention和vLLM的源码,看别人怎么在硬件限制下把效率抠出来;最后找个训练任务,亲手盯几天监控图,把数据加载、通信、计算这三段彩带的时间分布背下来。这几个基本功练完,你再回来看大模型背后的系统,会发现每个“看不见的地方”,都藏着可以动手的活儿。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询