标题:关于大模型训练和推理的一些框架
最近不少朋友私信问我,说现在大模型相关的框架满天飞,今天冒出来一个vLLM,明天又火了一个DeepSpeed,后台还有个叫LangChain的东西也在刷存在感。光看名字就晕了,更别说搞清楚它们到底是干嘛的。我当年入坑的时候也这样,今天聊点实在的,把大模型训练和推理阶段常用的框架梳理一遍,讲清楚它们各自解决什么问题、相互之间是什么关系,以及你该怎么选。这篇文章适合刚接触大模型、正准备搭建训练或推理环境,以及在框架选型上犹豫不决的开发者。我尽量不堆名词,用大白话把原理和实操经验讲透。
1. 先看清全局:训练和推理框架到底在解决什么问题
在聊具体框架之前,有必要先想清楚一个事情:我们折腾这些框架,到底是为了解决什么痛点?
大模型从无到有,本质上是两段工作。第一段是训练,也就是把海量文本数据喂给一个巨大的神经网络,让它通过反向传播算法不断调整参数,最终形成“智能”。第二段是推理,也就是把训练好的模型部署到服务器上,接收用户的请求,实时生成回答。听起来很简单,但实际做起来,这两段工作都会遇到极其恶心的工程问题。
训练阶段的核心痛点,说白了就是“装不下”和“算不动”。一个动辄几百亿参数的模型,显存根本放不下;就算放得下,单张显卡算到天荒地老也训练不完。这时候就需要各种并行策略,把模型切到多张卡上,让它们协同工作。但多卡协同涉及通信开销、显存管理、梯度同步,随便哪个环节出错,训练就崩了。这些脏活累活,就是训练框架要帮你解决的。
推理阶段的核心痛点则变成了“响应慢”和“吞吐低”。训练好的模型你得让它跑起来服务用户,但大模型的推理是自回归式的,一个token一个token地往外蹦,天然就慢。而且传统深度学习推理框架(比如TensorRT)是为固定尺寸的CNN模型设计的,对大模型这种动态、变长的生成式推理支持得很差。再加上GPU显存带宽有限,如果每个请求都单独加载一遍模型权重,并发一高服务器直接就瘫了。推理框架要解决的,就是如何让模型在GPU上跑得更快、更稳、并发更高。
所以你看,训练和推理虽然都叫大模型框架,但解决的是完全不同的问题。训练框架比的是谁能让几千张卡训练得更稳定、效率更高;推理框架比的是谁能让模型响应更快、吞吐更高、显存占用更少。理解了这一点,再去看看这些框架,你就能很清楚它们各自的价值在哪。
2. 训练框架的主力阵容:DeepSpeed、Megatron-LM与PyTorch生态
2.1 从PyTorch说起:为什么大家都站在它的肩膀上
现在市面上几乎所有主流大模型训练框架,底层都是基于PyTorch构建的。这并非偶然。PyTorch的动态图机制让研究者可以非常灵活地定义模型结构,不用像TensorFlow 1.x时代那样先构建静态图再执行。对于大模型这种结构复杂、经常需要修改的研究场景,这种灵活性太关键了。
但PyTorch本身只是一个深度学习库,它提供了自动求导、张量计算、神经网络层这些基础能力。当你只有一张卡,模型也不大的时候,用PyTorch原生API就可以搞定训练。问题在于,一旦模型超过单卡显存,你就需要额外的工具来处理“如何在多卡间切分模型、如何同步梯度、如何节省显存”这些问题。
PyTorch自带了一个叫DistributedDataParallel(DDP)的工具,它能实现数据并行——就是每张卡都放一份完整的模型,然后喂不同的数据,最后同步梯度更新。但DDP只解决了数据并行的问题,模型还是得完整放进一张卡里,对于大模型还是无能为力。所以,我们就需要更高级的训练框架来补足这些短板。
2.2 DeepSpeed:训练优化中的多面手
DeepSpeed是微软开源的一套深度学习优化库。我用它训练过不少模型,最大的感受就是“显存优化手段极其丰富”。它有一个核心特性叫ZeRO(零冗余优化器),思路非常巧妙:既然一个模型参数在训练过程中需要保存优化器状态、梯度、参数本身这三份数据,而这三份对于每张卡来说都是完整副本,那为什么不让每张卡只存一部分,用的时候再通信取回来呢?这种“存零头、用时再聚合”的思路,硬生生把原来需要显存的地方省出了一个数量级。
举个例子,训练一个70亿参数的模型,如果用普通的DDP方式,光参数、梯度和优化器状态就要占掉好几百GB显存,想都不敢想。但用DeepSpeed的ZeRO Stage 3,你可能只需要8张80GB的A100就能跑起来了。除此之外,DeepSpeed还提供 offload 功能,可以把优化器状态甚至参数暂时挪到CPU内存里,进一步降低显卡显存压力。对于个人开发者只有一两张显卡的情况,这个功能几乎是救命稻草。
不过DeepSpeed也不是银弹。它的配置项非常多,什么zero_optimization、gradient_accumulation_steps、train_batch_size这些,稍不留神就配置错了。我自己调试的时候经常因为train_batch_size没算对导致OOM。而且它和不同版本的PyTorch、Transformers之间有兼容性问题,升级版本的时候经常得一起升。
2.3 Megatron-LM:大集群训练的工程天花板
如果说DeepSpeed是灵活多数派,那Megatron-LM就是针对超大规模训练的重武器。它是英伟达开源的,专门为几千张卡的集群训练设计。Megatron有一套自己的张量并行和流水线并行实现,在集群环境下的通信效率优化得非常好。所谓张量并行,就是把一个Transformer层里的矩阵运算拆成多个小块,让不同的卡分别计算再拼起来;流水线并行则是把网络的不同层分配到不同的卡上,数据像流水线一样依次经过。
这套东西听起来简单,但工程实现极其复杂,涉及通信原语、显存调度、负载均衡各种细节。所以业内普遍做法是:DeepSpeed和Megatron混合使用——用Megatron处理模型切分的逻辑,用DeepSpeed的ZeRO处理优化器状态和数据并行。HuggingFace的Megatron-DeepSpeed就是一个现成的整合方案,我自己跑实验的时候也基本是在这个基础上改。
那么问题来了:我一个小团队就几张卡,有必要上Megatron吗?我的经验是没必要。Megatron的配置复杂度比DeepSpeed还要高一个档次,而且它更倾向于为固定大小、固定结构的模型服务优化。如果你的模型结构经常变化,那在Megatron上改代码的成本会让你怀疑人生。建议单机多卡、模型参数量在百亿级别以下的时候,把DeepSpeed吃透就够了。
2.4 PyTorch原生的FSDP:大模型训练的又一选择
除了DeepSpeed和Megatron,PyTorch这两年也发布了官方原生的FSDP(Fully Sharded Data Parallel)。它的设计思路其实和DeepSpeed的ZeRO Stage 3非常接近,也是把参数、梯度、优化器状态分片到不同的显卡上。区别在于,FSDP是PyTorch原生的,所以它跟torch.nn.Module的结合更自然,代码侵入性更低。你只需要把原先的DDP包装改成FSDP包装,很多代码几乎不用动。
我在实际使用中对FSDP的体验是:它在单机多卡场景下的表现其实挺惊艳的,性能不比DeepSpeed差,而且因为少了一层第三方库的封装,出问题的时候排查起来更“贴近底层”。不过FSDP也有一些限制,比如它对模型结构和动态图的支持不如DeepSpeed那么灵活,某些需要自定义切分策略的场景下,DeepSpeed还是会更顺手。
所以我的建议是:如果你是PyTorch的重度用户,且主要跑单机多卡训练,可以优先尝试FSDP,因为它更干净、更原生,在社区的新版本迭代里也很活跃;如果你的目标是做大规模集群训练,或者需要用到DeepSpeed独有的某些高级特性(比如offload到NVMe),那还是老老实实选DeepSpeed。
3. 推理框架的应用主力:vLLM、TensorRT-LLM、SGLang和其它选择
模型训完了,接下来就是把它跑起来服务用户。跟训练相比,推理阶段要考虑的东西其实是反过来的,模型参数已经固定不变了,这时候框架拼的就是谁能把模型塞得更紧、算得更快、并发撑得更高。
3.1 vLLM:我目前最常用的推理框架
先说vLLM,这也是我目前最推荐的入门推理框架。它开源之后迅速成了大模型部署的事实标准之一,GitHub星标涨得飞快。vLLM的核心优势在于:第一,它实现了一个PagedAttention机制,可以把显存里的KV Cache像内存分页一样动态管理,避免传统方式里因为预分配导致的浪费。第二,它内部实现了连续批处理(continuous batching),不用等一个请求完全生成完再处理下一个,而是可以在生成过程中不断插入新请求,充分利用GPU算力。
用vLLM跑起来一个模型非常简单,只需要几行代码。如果你只是想快速验证模型效果,直接用官方提供的命令行就可以起一个OpenAI兼容的API服务。我经常是先在本地的几张卡上用vLLM把模型部署好,然后写个脚本发几个请求测试输出质量和吞吐,确认没问题再放到正式环境上。
vLLM有一个config文件,里面可以配置很多推理参数,比如最大输入长度、采样策略、tensor parallel size等等。对于大部分场景,你只需要关注两个维度:一个是模型大小和显存的匹配关系,另一个是并发请求量的预估,据此调整gpu_memory_utilization和max_num_seqs这两个参数。前者决定了缓存KV Cache能占多少显存,后者决定了batch的最大并发度。
3.2 TensorRT-LLM:追求极致性能时的第一梯队
如果说vLLM是“方便好用”,那TensorRT-LLM就是“极致压榨”。它是英伟达推出的推理框架,基于TensorRT做深度优化,能对模型进行编译、量化、层融合等一系列操作。简单说,它能把模型的计算图优化到极致,推理延迟能做到最低,吞吐能做到最高。
但是,它有个明显的缺点——使用门槛比较高。TensorRT-LLM需要你先将模型转换为TensorRT的engine文件,这个过程包含图优化和量化校准,可能耗时很长时间,而且一旦模型结构或推理配置有变化,整个转换流程就得重跑一遍。另外它对HuggingFace模型的支持虽然一直在完善,但总有些“水土不服”的情况需要自己调试。
所以我个人的习惯是:如果你的业务就是追求极致的推理性能和成本优化,且模型相对固定、不需要频繁更新,那花时间搞定TensorRT-LLM是值得的;如果你处于快速迭代阶段,还是先用vLLM把业务跑起来更务实。
3.3 SGLang:在隐性推理能力和复杂场景上更具优势
SGLang是一个相对较新的推理框架,它的定位很有意思,主打的是高性能复杂推理场景。SGLang对结构化输出和复杂提示词的处理更优秀,并且支持一些新兴的推理技巧,比如压缩上下文、并行解码等。如果你做的是Agent类应用,或者需要频繁与外部工具交互、执行复杂逻辑,那SGLang比vLLM在这些高级特性上更占优。
我在一些多轮对话和代码生成任务中对比过两者的表现,vLLM在常规场景下够用,但SGLang在长上下文场景里对显存的管理更精细,响应速度也相当不错。不过SGLang的社区规模和成熟度目前还不如vLLM,用的时候遇到问题,可能需要自己翻源码排查。
3.4 其他值得留意的推理引擎
除了上面三个,还有一些值得留意的推理引擎。比如HuggingFace的Text Generation Inference(TGI),它是HuggingFace自家推出的推理服务,和Transformers库的兼容性最好,在HuggingFace生态里使用起来最顺手。还有针对特定硬件的方案,比如英伟达的FasterTransformer(已被TensorRT-LLM整合)、针对苹果芯片的MLX、针对CPU的llama.cpp等等。llama.cpp让我印象很深,它能把模型量化后在纯CPU机器上跑起来,虽然速度慢,但胜在随处可用、零门槛,适合拿来研究模型行为特性。
整理一张表格让大家直观感受一下:
| 框架 | 核心优势 | 适用场景 | 上手难度 |
|---|---|---|---|
| vLLM | 吞吐高、部署快、生态成熟 | 通用大模型在线服务 | 简单 |
| TensorRT-LLM | 延迟最低、极致性能 | 模型相对固定、追求极致性能的线上生产 | 较复杂 |
| SGLang | 复杂推理、结构化输出、高级特性 | Agent应用、复杂逻辑推理 | 中等 |
| TGI | 与HuggingFace生态无缝集成 | HuggingFace用户快速部署 | 简单 |
| llama.cpp | 轻量、无GPU依赖 | 本地CPU推理、边缘设备 | 简单 |
4. 微调与对齐场景:LoRA训练和Agent框架的关键配套
现在跑大模型,很少有人直接从头预训练一个模型,更常见的做法是拿一个大模型做微调(Fine-tuning)或者对齐(Alignment),让它适配特定的领域或任务风格。在这个环节,框架的作用也相当关键。
4.1 LoRA训练:用极低的成本微调大模型
先聊LoRA(Low-Rank Adaptation)。它的核心思想是:在训练大模型时,冻结原始模型参数不动,额外在模型的某些层旁边加一组低秩矩阵。训练的时候只更新这些低秩矩阵,大大减少需要训练的参数量。举例来说,一个70亿参数的模型,全量微调要更新70亿个参数,显存占用巨大;但用LoRA,可能只需要更新几千万个参数,显存占用一下降到了原来几分之一甚至更低。
LoRA训练目前已经跟训练框架紧密整合在一起。最常见的技术栈是:用PEFT(Parameter-Efficient Fine-Tuning)库定义LoRA配置,用Transformers库加载模型和数据,用DeepSpeed或FSDP来支撑多卡训练。这套组合拳是如今大模型微调的“标配动作”。如果你想用LoRA微调一个本地模型,我建议直接用这种标准化路径,不要自己造轮子。
我个人在LoRA训练中踩过的坑主要有两个。一是Rank值的设置,Rank太小会限制模型的学习能力,Rank太大又容易过拟合且占显存,通常从8、16、32这几个值开始实验比较稳妥。二是目标模块的选择,LoRA默认通常加到query和value层上,但如果任务比较难,有时还需要加到key和output层上,需要根据实际效果调整。
4.2 Agent框架:让大模型在推理中会使用工具
除了传统微调,现在大量应用其实是大模型+外部工具的Agent模式。大模型负责理解用户的意图、拆解任务、生成决策,Agent框架则负责让模型真正去调用工具、访问外部知识库、执行代码。这类框架非常多,从最著名的LangChain,到AutoGPT、MetaGPT,再到各大厂商自家的API工具调用方案。
从技术实现角度看,Agent框架本质上是在大模型的推理循环外面包了一层“工具调度系统”。它会把用户的请求传给模型,让模型决定需要调用哪个工具、传什么参数,然后框架负责实际执行工具并返回结果,再把结果交给模型做下一步决策。这个过程反复迭代,最后生成完整的回答。
这套东西和大模型推理框架之间的关系其实非常紧密。Agent应用的特点是高并发、短上下文、频繁的工具调用,对推理引擎的稳定性和吞吐要求非常高。我做过一个实际项目,用vLLM部署了一个模型来支撑一个Agent服务,刚开始发现只要工具调用一多,推理服务的并发就上不去,后面把vLLM的最大并发数调大、调整了KV Cache的复用策略之后才有明显改善。所以如果要做Agent,务必把底层推理框架的性能参数调优也纳入考虑。
5. 框架选型的理性建议:从场景和资源出发做决策
聊到这里,你应该发现了,大模型训练推理框架的选型,本质上没有一个“最好”的答案,只有“最合适”的方案。我根据自己实际跑过的场景,梳理一套选型的思路供你参考。
5.1 个人开发者和实验室场景
如果你只有一两张消费级显卡(比如RTX 4090或A6000),主要目的是跑实验、做验证、写论文,那我的建议最简单:训练用PyTorch + DeepSpeed就好,最多再加上FSDP做对比实验;推理用vLLM就足够了。这套组合的社区资料最全,出问题能搜到大量现成的解决方案。消费级显卡的显存有限,建议把DeepSpeed的CPU offload和量化技巧学好,能帮你在有限的硬件上跑起更大的模型。
5.2 创业团队和中小型业务团队
如果你的团队要搭建一个面向真实用户的模型服务,而且业务有一定的并发压力,我的建议是:训练阶段继续沿用DeepSpeed + FSDP的组合,保持模型迭代的灵活性;推理阶段则要精细化一些,优先用vLLM把服务跑稳定,监控好显存、吞吐、延迟这几个核心指标。如果后面发现延迟成为瓶颈,再考虑用TensorRT-LLM做专项优化。另外一定要把量化方法(比如AWQ、GPTQ)纳入考察,同样一张卡,4 bit量化后能撑起的模型大小和并发数,会给你惊喜。
5.3 大模型原生业务和资源充足的团队
如果你的团队资金雄厚,拥有几十上百张卡,而且业务对性能有极致要求,那就值得在训练阶段上Megatron-DeepSpeed,在推理阶段上TensorRT-LLM和SGLang的组合拳。对这种情况,我反而会提醒一句:把时间花在业务需求理解上,而不是一味追求新框架。大规模集群的运维复杂度已经很高了,框架用得越复杂,隐性维护成本就越高。很多时候,一个从“够用”出发的简单方案,反而比一个从“炫技”出发的复杂方案更能带来商业价值。
5.4 几个“避坑”心得
最后分享几个我在实际选型和使用中总结出来的经验,希望能帮你避开一些坑。
第一个是关于版本管理的。大模型框架的迭代速度极快,而且框架之间往往存在依赖关系——比如Transformers版本会影响PEFT,PEFT会影响DeepSpeed的兼容性。我强烈建议你现在就用conda或者venv把不同项目的环境彻底隔离,并且把requirements.txt或者environment.yml文件严格记录好。不要相信“先升级一下试试”,很多时候一升全部就要重新调,损失的时间成本非常大。
第二个是关于显存评估的。很多人上来直接跑,结果发现OOM。我一般建议在部署模型之前,先按参数总量估算显存占用:模型参数占用的显存大致是参数量乘以字节数,比如一个70亿参数的模型用FP16格式,权重大约占14GB;但推理时还有一个“大头”——KV Cache,它跟并发的序列数量以及上下文长度成正比,稍不留神就会把显存挤爆。所以配置vLLM时,gpu_memory_utilization这个参数我一般会留出8%~15%的余量,避免系统不稳。
第三个是关于数据格式的。训练框架吃的是token id序列,推理框架输出的是token id序列再解码成文字,所以分词器必须和模型严格匹配。很多人图省事,用不同的分词器去加载模型,结果出来的中文多多少少有乱码或者语义漂移。用模型原本训练时的分词器,是最基本原则。
6. 从实际项目看训练与推理框架的打通
前面讲了很多框架的分工,但实际项目中训练和推理必须形成一个闭环。我拿一个自己最近做的实际项目来串一串。
项目的背景是自己收集了一批领域语料,想基于一个开源基座模型微调出一个领域内问答助手。训练阶段我用的就是DeepSpeed ZeRO Stage 2加上LoRA,8张老款GPU凑合着扛下来了。整个训练跑下来最花时间的是排查数据质量问题,框架本身倒没出什么大岔子。训练完之后,我先把LoRA的权重合并回原模型,导出成一个完整的HuggingFace格式模型,再拿vLLM加载并启动一个OpenAI兼容的服务。
这个过程中我踩了一个坑:刚开始直接把LoRA模型用vLLM加载,结果vLLM报错说模型结构不匹配。后来才知道,vLLM加载LoRA需要通过它自己的适配机制,而不是直接加载PEFT训练产物。最简单的办法是先合并权重,再加载完整模型。改了之后,服务秒起,效果也正常。
所以说,训练和推理框架虽然各管一摊,但模型格式、分词器、权重结构这些环节是它们之间的“高速公路”。打通这条高速公路,项目的交付才算是真正完成。
最后再分享一个小技巧:如果你想把本地部署的模型接入到自己的应用、脚本或者办公工具里,一定要优先选支持OpenAI接口协议的框架部署方式。因为现在的生态工具(比如各类Agent框架、脚本库)几乎都默认兼容OpenAI接口格式,你起一个本地OpenAI兼容服务,就能无缝接入现有工具,省去大量适配工作。我目前给所有本地模型起的服务,全是走这条路。
大模型训练和推理框架这个领域还在快速演进中,今天聊的这些很可能过不了多久又有新变化。但底层的那几条主线——显存怎么省、并行怎么做、吞吐怎么提——短时间内不会变。把这几个核心点吃透,不管框架怎么换,你都能快速上手。