先聊聊这套平台到底解决了什么问题。手头有几张卡,想把开源大模型在自己团队内部跑起来——既要微调,又要部署对外接对话,还得让不懂命令行的人也能上手用。这三件事单独做都不难,但要把它们揉进一个开源系统里,还能稳定支持多卡并行训练和推理,那就要费不少功夫了。所谓“支持多卡并行且具备WebUI的开源大模型训推平台”,本质上就是把模型仓库、训练调度、推理服务、浏览器界面四件事统一收口,让用户不再需要对着终端敲一长串分布式训练命令,也不用单独维护推理服务。对于做私有化部署、算法团队协作、高校实验室资源复用这些场景,这东西的实用价值非常直接。
这篇文章我会从架构选型、并行策略、训练与推理落地、WebUI设计、完整部署流程、真实坑点这六个维度,把我在实际搭建和使用中的经验和关键细节完整分享出来。适合准备自己动手搭训推平台的开发者,也适合正在选型或评估这类系统的技术负责人参考。内容会比较长,但我尽量做到每一步都能直接照着操作。
1. 整体设计与需求拆解:为什么非要做成“多卡+WebUI”的开源平台
1.1 先理顺需求:训练、推理、界面,到底先抓哪个
大多数团队在计划搭大模型训推平台时,第一反应往往是“先搞训练脚本”,然后发现推理又是另一套体系,最后再补Web界面,结果系统被拆得七零八落。我在实际推进这个项目时,第一件事不是写代码,而是把需求重新拆了一遍,最终拆成了三个核心诉求:
- 训练侧:要能在多张GPU上跑微调,显存不够就靠并行策略解决,不能只支持单卡玩具场景。
- 推理侧:训练完的模型要能快速部署成在线服务,支持多人同时请求,不能每测一次就重启一次脚本。
- 使用侧:团队里不是所有人都会用终端和分布式参数,必须有一个WebUI把任务提交、状态查看、对话测试、日志浏览这些操作收拢到一个界面上。
这三个诉求其实是分层关系:训练和推理是底层能力,WebUI是上层入口。很多开源项目只做好其中一块,比如只提供推理服务,或者只有训练代码没有界面。而“训推一体+WebUI”的最大价值是缩短了从训练到交付的链路,模型微调完可以直接在同一个平台里发布成推理服务,再在浏览器里聊几句验证效果,不用再经历“导出权重→写推理脚本→起服务→测试”这条冗长路径。
1.2 方案选型:为什么选择自建开源路线而不是用商业闭源产品
选型那阵子我们大概对比了三类方案:商业云平台、某些大厂开源工具、自建开源平台。商业云平台确实省事,但模型权重、训练数据、业务日志全在别人环境里,对数据敏感的场景直接就被排除了。大厂开源工具往往偏向某个环节,比如只做训练加速或者只做推理引擎,想要完整的训推一体界面,就得自己再去拼接多个组件,拼完之后维护成本不低。
最终选择自建开源路线,核心原因有三个:一是可控性强,训练脚本、调度逻辑、UI交互全在自己手里,遇到问题能直接改源码;二是数据不外流,整个平台跑在内网环境里,开源的属性意味着我们可以自己审计每个环节;三是成本更透明,不需要按API调用量付费,硬件资源是自己的,边际成本几乎为零。当然,选择自建有一个前提——团队里至少有一两个人熟悉深度学习框架分布式训练和Linux服务部署,否则后续踩坑排查会有些吃力。
1.3 多卡并行与WebUI之间的关系:这题没那么简单
多卡并行和WebUI表面上看是两件独立的事,实际上它们会通过“任务管理”产生强耦合。多卡并行意味着训练任务会占用多张GPU,而WebUI要实时展示每张卡的利用率、显存占用、训练进度,这就要求后端的任务调度系统必须把GPU状态、进程信息、日志流全部采集出来,并且提供给前端。反过来,WebUI收到用户提交的训练参数后,又要生成对应的分布式训练命令并分配到多张卡上执行。这是一个双向链路。
我在实际设计时把这条链路想得很清楚:WebUI只是壳,真正负责调度的是中间层。中间层拿到UI传来的模型名称、数据集路径、并行方式、Epoch数量后,组装成一条标准启动命令,再通过进程管理器在多卡环境上拉起任务。任务运行后,日志、指标、GPU状态都写入统一的数据通道,WebUI通过接口轮询或实时推送方式展示。只要这个双向链路不短路,平台用起来就会很顺。
2. 多卡并行的底层逻辑与架构设计
2.1 数据并行、张量并行、流水线并行,选哪个怎么配
多卡并行不是一个笼统的概念,它底下至少有三种经典策略:数据并行、张量并行、流水线并行。刚开始做选型时,我对这个问题的理解也比较粗,以为多卡训练就是“每张卡发一份数据然后AllReduce梯度”,后来踩过坑才发现,不同并行方式解决的是不同瓶颈。
- 数据并行(Data Parallelism):每张卡放完整模型副本,各自处理不同批次数据,定期同步梯度。实现简单,适合模型能塞进单卡显存但训练速度慢的情况。
- 张量并行(Tensor Parallelism):把单层权重按维度切分到多卡,计算时通过通信合并结果,适合模型大到单卡放不下的场景。通信量极大,对卡间带宽要求很高。
- 流水线并行(Pipeline Parallelism):按层切分阶段,不同阶段放在不同卡上,数据像流水线一样流经各阶段,同时降低显存占用和通信量,但存在气泡率问题。
三者的核心取舍可以看这张表:
| 并行方式 | 目标瓶颈 | 单卡显存需求 | 卡间通信量 | 实现复杂度 |
|---|---|---|---|---|
| 数据并行 | 吞吐量 | 高(完整模型) | 中 | 低 |
| 张量并行 | 显存容量 | 低(部分权重) | 高 | 中 |
| 流水线并行 | 层数与显存 | 低(部分层) | 中 | 高 |
实际项目中,绝大多数场景不会只用一种,而是组合使用。我的经验是:先把模型塞进一张卡试试,如果单卡能跑但速度不满意,优先加数据并行;如果单卡直接爆显存,再考虑张量并行或流水线并行。当前主流开源框架里常见的是数据并行加ZeRO优化,也就是把优化器状态、梯度、参数按需分片,相当于一种接近张量并行的效果,但实现层面更友好。
2.2 整体架构设计:控制面、训练面、推理面、展示面
整个平台我把它分成四个模块:
- 控制面(Controller):负责接收WebUI的用户请求、解析任务参数、调度GPU资源、拉起和终止训练进程。它同时维护一个任务状态表,是前后端通信的中枢。
- 训练面(Training Worker):跑分布式微调训练的实际进程集合,由控制面在多卡上拉起。训练逻辑基于常见分布式框架完成,支持断点续训和日志上报。
- 推理面(Inference Engine):模型训练或导入完成后,把它加载成在线推理服务。推理引擎要支持连续批处理和显存管理,否则并发量一旦上来就会严重卡顿。
- 展示面(WebUI):包含任务提交表单、训练日志面板、GPU监控面板、在线对话窗口、模型管理页面。它本身不直接操作GPU,只通过API与Controller通信。
这四个模块都部署在同一个内网环境中,服务间通过内部HTTP接口通信,训练进程与推理进程都各自占用独立GPU资源。这个架构最大的好处是边界清晰:控制面不碰模型,训练面不管界面,推理面不做调度,谁出问题都可以单独定位。
2.3 为什么用主从式的任务调度而不是乱序调度
一开始我图省事,希望WebUI提交的任务直接在后端进程里并发跑,谁先到谁先启动。但多卡资源是有限的,如果两个训练任务同时提交,都要求“用满8张卡”,就会出现资源竞争,运气差的甚至会把显存打爆导致进程直接被杀。后来改为主从式任务调度:Controller就是主节点,它维护一个全局GPU资源表,记录每张卡当前被哪个任务占用;新任务到达时,Controller先做资源预检,如果资源不够,就把任务丢进等待队列,等前面的任务释放资源再启动。
这种设计的价值在于可预测性。用户在WebUI上提交任务后,能明确看到“排队中”“运行中”“已完成”“失败”的状态变化,不用担心提交后到底跑没跑。主从式调度还方便做优先级控制,比如急用的推理服务可以设置为高优先级,抢占训练任务的部分资源。
3. 训练模块的落地细节与关键参数
3.1 多卡微调任务的完整启动流程
放在这个平台里,一次微调任务的操作在WebUI上只需填几个字段,但后端实际执行的动作链是这样的:
- 用户选择基础模型权重和数据集路径,设置学习率、批次大小、Epoch数、并行方式。
- Controller把参数组装成训练脚本的环境变量与命令行参数。
- Controller检查任务等待队列和GPU资源,分配指定编号的GPU。
- 在各GPU节点上同时拉起分布式训练进程,进程间初始化通信组。
- 训练进程实时把日志和关键指标(Loss、吞吐量、显存使用)推送到Controller。
- WebUI通过接口展示训练状态,用户可随时暂停或终止任务。
- 训练结束后自动保存最新权重,并可在WebUI上直接将其发布为推理服务。
如果你不用WebUI,直接在命令行手动启动一次多卡微调,核心的命令结构大致是这样的:
torchrun --nnodes=1 --nproc_per_node=8 --rdzv_backend=c10d \ train_script.py \ --model_name 基础模型路径 \ --data_path /data/train.jsonl \ --output_dir /models/finetune_v1 \ --batch_size 4 \ --learning_rate 5e-5 \ --num_epochs 3 \ --zero_stage 2 \ --gradient_accumulation_steps 8这里的--nproc_per_node=8表示单机8卡并行。如果跨机训练,还需要加--nnodes=2 --node_rank=... --master_addr=... --master_port=...这一组参数来建立多机通信。
3.2 训练参数背后的计算逻辑:不搞清楚会白等十几个小时
很多教程只会告诉你“把batch_size设为4,梯度累积设8”,但为什么不这么设,很少解释。这里我用实际例子讲清楚。
假设你选的基座模型权重对单卡显存占用约14GB(加载权重和激活值后的估算值),单卡是24GB显存,你希望用8张卡做数据并行微调。如果直接把batch_size设为4,单批次前向反向计算可能会让峰值显存冲到28GB,直接超限。这时候有两个选择:
- 把单卡
batch_size降到2,峰值显存约18GB,安全了,但每个step处理样本太少,梯度噪声大,模型收敛不稳定。 - 保持
batch_size=4,但用gradient_accumulation_steps做梯度累积,即连续算4个mini-batch的梯度但不更新权重,攒够4次后再统一更新一次参数。这样效果上等价于batch_size=16,又不会让显存爆掉。
计算实际参与更新的批次大小公式是:
实际批次大小 = 单卡batch_size × 卡数 × 梯度累积步数比如batch_size=4 × 8卡 × 8步 = 256。这个256就是每一次参数更新动用的样本数量。学习率的选择也要参考这个值,批次越大,一般学习率可以适当调高。这里我的建议是:如果实际批次从128涨到256,学习率可以从5e-5微调到1e-4左右,但不宜一次性跳太多。
3.3 ZeRO帮你拆显存:不是只有张量并行能省显存
提到多卡训练就绕不开ZeRO。ZeRO的全称是“零冗余优化器”,核心逻辑是:传统数据并行下,每张卡都保存了一份完整的优化器状态、梯度和参数,8张卡就有8份冗余。ZeRO把这些状态分片存到8张卡上,用时再通过通信集齐,从而把单卡显存占用降下来。
ZeRO有三个阶段,实际使用时我推荐从stage 2起步:
- stage 1:只分片优化器状态,显存省得不多,但实现简单,适合中等模型。
- stage 2:分片优化器状态和梯度,这是性价比最高的档位,很多微调场景都够用。
- stage 3:连参数也分片,显存省得最狠,但通信开销显著增大,训练速度会变慢。
我踩过的坑是:一开始为了省显存直接上stage 3,结果训练吞吐量掉了将近一半,卡间通信成了瓶颈。后来改回stage 2,配合合理批次大小,稳定性和速度都比较好。所以不要盲目追求“最省显存”,要结合卡间通信带宽、模型大小和单卡显存综合判断。
3.4 断点续训与监控:跑十几个小时的任务最怕中途失败
大模型微调任务经常一跑就是十几个小时,中途断电、显存溢出、进程被杀都是可能发生的。平台必须支持断点续训,否则任何一个意外都得从头再来,人力成本和时间成本都很高。
断点续训的实现思路其实不复杂:训练脚本在每个Epoch结束或固定步数间隔,把模型权重、优化器状态、学习率调度器状态、当前步数一并保存为checkpoint。重启训练时,先加载最近的checkpoint,把优化器状态恢复回来,从保存的步数继续训练。
我在项目里把checkpoint的保存频率设置为“每500步保存一次”,同时保留最近3个checkpoint,避免磁盘被填满。WebUI上还增加了断点列表页面,用户可以选择从某个checkpoint恢复,也可以单独导出某个checkpoint的权重用于推理服务。
4. 推理引擎的接入与在线服务优化
4.1 推理服务的核心诉求:吞吐量、延迟、显存波动
训练结束后,模型需要被部署为在线推理服务。很多人觉得“加载模型然后跑生成”而已,实际并不是这样。推理服务的评价维度完全不同于训练:
- 吞吐量(Throughput):每秒能处理多少请求,影响多人同时使用的体验。
- 延迟(Latency):单个请求从发起到返回的时间,对话场景尤其敏感。
- 显存稳定性:推理时显存占用会根据输入长度动态变化,如果设计不当,长文本请求会突然让显存暴涨并杀掉进程。
为了让推理服务稳定,我在后端做了三个处理:固定最大输入长度上限,对超过阈值的请求做截断或拒绝提示;使用连续批处理机制,把一个批次内多个请求按输出长度动态调度,避免批处理中短请求被长请求拖累;推理时对KV Cache做滑动窗口管理,防止缓存无限膨胀。
4.2 连续批处理与KV Cache:为什么并发一高就卡
关于推理性能,有两个核心机制必须理解。
第一个是KV Cache。模型生成每一个新token时,都需要重新计算前面所有token的Key和Value向量。如果每次都重算,计算量会随序列长度平方级上升。KV Cache把这些中间结果缓存下来,生成新token时只做增量计算。但KV Cache也吃显存,一个上下文窗口设为4096、层数为32的模型,单请求的KV Cache可能占用几百MB到几个GB显存。所以平台里要有一个KV Cache管理器,空闲时释放不活跃请求的缓存,才能支撑更多并发。
第二个是连续批处理(Continuous Batching)。传统批处理是“凑满一个批次再一起算,全部结束再进下一批”,短请求会卡在长请求后面。连续批处理允许新请求随时插入到正在执行的批次里,当一个请求生成结束,位置立刻让给下一个请求。这样吞吐量能提升数倍。我在项目里把这个参数设计成自适应模式,当GPU利用率低于60%时,自动加大并发注入量,利用率高时则回缩,避免过载。
4.3 推理服务与WebUI的对接流程
在WebUI上,推理服务的管理并不复杂但逻辑要闭环。用户选择模型后,点击“加载模型”,后端会先检查该模型权重文件是否存在,再检查GPU显存是否充足,然后启动推理进程并加载权重。加载完成后,状态变成“已就绪”,用户就可以在对话窗口测试。
我在实际操作中有一个建议要给到:不要把推理服务启动和“加载模型”做成同一个接口的超时等待。模型权重可能高达几十GB,加载需要一两分钟甚至更久,如果WebUI请求一直等,迟早超时。我的设计是:点击加载后接口立刻返回“任务已在后台运行”,同时WebUI每秒轮询一次状态,直到状态变为“已就绪”。这样用户体验流畅,后端也更健壮。
5. WebUI设计与操作实现
5.1 页面不是越复杂越好:守住三个核心页面
WebUI我用的是前后端分离的结构,后端是Python服务,前端是独立页面。很多项目把WebUI做成一个超大的多功能面板,结果用户根本不知道点哪里。我的经验是,训推平台真正需要的只有三个核心页面:
- 训练任务页:展示任务列表,提供新建训练任务的表单入口,支持查看日志、停止任务、断点恢复。
- 模型管理页:展示已有的基础模型和微调模型,支持导入权重、发布推理服务、删除模型。
- 推理对话页:选择一个已加载的模型,进行在线对话测试,并可查看推理延迟与吞吐指标。
这三个页面已经能覆盖绝大多数使用场景。想再增加高级功能时,我的建议是克制一些,先把主链路做稳。很多功能,比如模型对比测试、自动调参,会显著增加复杂度,后期扩展即可。
5.2 前后端交互的数据流设计
WebUI最容易被忽略的地方是“状态到底怎么更新”。我在做的时候设计了清晰的数据流协议,用一套统一的任务事件模型来组织:
- task_submitted:任务已提交,等待调度。
- task_queued:已进入等待队列,展示预计等待时长。
- task_running:任务运行中,展示实时日志和训练指标。
- task_completed:任务完成,展示产出模型路径。
- task_failed:任务失败,展示错误日志摘要。
前端拿到这些事件后,在训练任务页里渲染成状态标签和时间线。日志则不走业务接口,而是通过独立的日志接口增量拉取,避免每次刷新都拉全量日志导致页面卡顿。GPU监控数据是另一个独立接口,每2秒刷新一次,展示每张卡的利用率、显存、温度、功耗。
5.3 用户体验细节:权限、并发限制、操作反馈
作为一个团队共用平台,权限控制是必须的。我的设计里分成了管理员和普通用户两个角色:管理员可以创建任务、删除模型、管理GPU资源;普通用户只能查看任务状态和发起推理对话。这个权限模型虽简单,但足够撑起一个内部团队的使用。
另外还要处理一个并发限制问题。WebUI提交任务时如果不对并发做控制,用户很容易连点多次提交,造成资源重复占用。我在后端做了双重校验:Controller在任务提交时先查重(同参数加同数据集且在五分钟内提交的直接拒掉),同时前端在表单提交后立即禁用按钮并显示“已提交,正在排队”。
操作反馈也很重要。任何操作,不管成功还是失败,都要在界面上给出明确提示。尤其是失败场景,不能只显示“请求失败”,要把后端返回的错误摘要一并展示出来,比如“显存不足,请求的8卡中仅6卡可用”,用户才知道接下来该怎么调整。
6. 完整部署实操:从环境准备到真正跑起来
6.1 硬件与系统环境准备
先说硬件环境。多卡并行的前提是机器上有多张可用GPU,而且卡间要能正常通信。这里有一个很容易踩的坑:同一台机器上插了不同型号或不同算力的GPU,驱动兼容性没问题,但通信性能可能极差。我的建议是尽量保持同型号、同显存规格,否则并行时快的卡要等慢的卡,训练速度不升反降。
软件层面,我的推荐组合是:
- 操作系统:Ubuntu 20.04或22.04
- GPU驱动:与CUDA版本匹配的厂商驱动
- 容器方案:Docker + NVIDIA Container Toolkit
- Python环境:基于容器镜像的独立环境,避免污染宿主机
多卡并行训练对驱动和通信库版本相当敏感。我建议先用一个小测试程序验证多卡通信是否正常,比如在各卡间执行一次简单的数据交换操作。如果这一步就卡住,那么后续所有训练任务都会失败,排查起来更复杂。
6.2 一步一步部署平台
下面给出一套我实际使用的部署步骤,每一步都经过验证。假设你已经有一台8卡Linux服务器,并且已经装好Docker相关组件。
第一步,拉取基础镜像并创建容器:
docker pull 你的基础镜像地址 docker run -it --name llm-platform \ --gpus all \ --shm-size 32g \ -v /data:/data \ -v /models:/models \ -p 80:80 \ -p 8080:8080 \ 你的基础镜像地址 /bin/bash注意--shm-size参数,多卡训练的数据加载器会用共享内存做进程间数据传递,默认64MB经常会不够,我给到32GB是为了减少数据加载瓶颈。
第二步,在容器内安装训练与推理依赖:
pip install -r requirements.txt需要重点说明的是,requirements里需要包含分布式训练框架、数据加载库、Web服务框架等,版本号务必固定,否则升级带来的破坏性变更会影响整个平台稳定性。
第三步,修改配置文件。配置文件里需要填写模型存储路径、数据集目录、GPU列表、Web服务端口等关键信息。我的配置里有一个gpu_whitelist字段,用来限定平台可以占用的GPU编号,这样可以避免平台任务误占其他业务正在使用的GPU。
第四步,初始化模型仓库目录结构:
/models /base_models # 存放开源基座模型权重 /finetuned_models # 存放微调后的模型 /checkpoints # 存放训练断点一切路径规划好后再启动,免得后面因为路径混乱找不到模型。
第五步,启动后端服务以及前端页面服务。推荐先用进程管理器托管后端,保证崩溃后能自动重拉。实际启动命令大致是:
uvicorn backend_main:app --host 0.0.0.0 --port 8080 nginx -g "daemon off;"第六步,验证服务状态。浏览器访问服务器地址,如果能看到登录页面并且能正常登录,说明前后端联通。接着进入模型管理页,导入一个基座模型权重文件,等待解析完成。
6.3 首次功能验证:训练加推理走通全链路
部署完成并不代表项目就成功了,还需要走一遍全链路验证。我建议第一次验证用一个很小的模型和很小的数据集,跑通“上传数据→创建微调任务→查看训练日志→保存模型→发布推理服务→对话测试”这条完整链路。小步快跑的好处是,出问题时能快速定位,不会因为模型太大导致任务一启动就OOM,干扰你对平台本身问题的判断。
我当时的第一次验证数据集只有几百条训练样本,模型是最小尺寸的开源基座,预期几分钟就能跑完一个Epoch。任务启动后,我在WebUI训练任务页能看到日志持续滚动,GPU监控面板显示8卡利用率都拉起来了,那一刻才算真正确认多卡并行链路没断。随后我在模型管理页把训练产物发布成推理服务,再切到对话页测试,输入问题后得到回复,整个链路正常。
6.4 这类平台后续还可以怎么扩展
平台跑通之后,可以做的扩展方向其实很多。我在项目里后续加了三个东西,都很有实用价值:
- 模型评测模块:内置一批评测问题集,微调完成后自动跑一遍,输出得分,方便量化对比不同版本模型效果。
- 自动模型切换:推理服务支持“按版本灰度”,先切一小部分流量到新模型,观察效果再全量切换。
- 训练资源配额:给不同用户配置GPU使用上限,避免某个人一次性占满所有卡导致其他人任务无法提交。
扩展时还是那个原则:先保证主链路稳定,再逐步加外围功能,不要一开始就把系统做成一个臃肿的平台。
7. 常见问题与排查经验
7.1 多卡通信与资源方面的典型问题
下表整理了我在多卡并行训练中实测遇到的高频问题,以及对应的排查思路:
| 问题现象 | 可能原因 | 排查与处理 |
|---|---|---|
| 任务启动后立即报NCCL通信超时 | 卡间网络或PCIe通信异常、防火墙拦截 | 检查多卡互ping、关闭无关防火墙策略,先用单机小规模通信测试脚本验证 |
| 8张卡利用率差距过大,某张卡长期为0 | 数据加载不均、卡间通信负载不均 | 检查DataLoader的num_workers配置,确认是否存在某个进程阻塞 |
| 显存直接打爆,进程退出 | 单卡批次过大或并行配置不当 | 调低单卡batch_size,增加梯度累积步数,或开启显存优化选项 |
| 使用ZeRO stage 3后训练速度骤降 | 参数分片带来的通信开销过高 | 降级到stage 2,或检查卡间通信带宽是否符合要求 |
| 重启容器后GPU显存缓存未释放 | 僵尸进程占用显存 | 用nvidia-smi查看残留进程,手动kill后再启动任务 |
7.2 WebUI与后端服务的高频故障
WebUI侧的问题往往不会像训练进程那样直接崩溃,但排查起来也很耗时。最常见的问题和我的处理办法如下:
- 页面加载日志时卡死或内存暴涨。原因是单次请求返回全量日志。我后来改成增量拉取,每次只拉最新200行,前端再拼接展示。
- 模型加载过半时前端超时。根本原因是加载是同步阻塞接口。改成后台异步加载加状态轮询后解决。
- 推理对话一直转圈无响应。一般是推理进程崩溃或者显存不足。我在后端加了进程心跳检测,推理进程异常退出时能自动清理会话状态并提示用户重新加载模型。
- 多人同时提交任务导致资源冲突。我的做法是给提交接口加了一个互斥锁,处理请求时先对GPU资源表加锁,再执行分配,避免并发写导致资源重复分配。
7.3 实测独家心得
最后分享几个不太会写进文档里的经验。
第一,永远先验证“最小链路”。我在项目早期犯过一个错误:第一次就在8卡上直接跑完整的7B参数级模型微调,结果因为数据集格式有个小问题,所有进程跑起来后才发现数据加载直接失败。改成先用小模型和数据量跑通链路后,再上大模型,效率和成功率都高很多。
第二,日志是排查问题最重要的资产。把所有关键节点的日志都打上时间戳和进程号,尤其是任务启动、GPU资源分配、模型加载完成这些节点。没有日志的话,出了问题只能瞎猜,有了清晰日志,基本上10分钟内能定位到问题所在。
第三,WebUI虽好,别让它成为唯一的操作入口。我保留了底层脚本接口,这样遇到WebUI自身故障时还能用命令行兜底,不至于整个平台瘫痪。
第四,对磁盘空间要心里有数。多卡并行训练会同时写多个日志文件、多个checkpoint,如果日志和模型放在同一块磁盘上,把磁盘写满的情况很常见。我建议把日志目录、模型目录、数据集目录拆分到不同挂载点,并设置定时清理策略,保留足够冗余空间。
搭建这套“支持多卡并行且具备WebUI的开源大模型训推平台”,对我来说最大的感受就是:它不是一个单一模型或算法问题,而是一个系统工程。训练侧要理解并行策略和显存极限,推理侧要处理并发和缓存机制,WebUI要把复杂操作转化成简单可靠的交互,任何一个环节掉链子,整个平台的可用性都会打折扣。如果你正在做类似的事情,我的建议是分层推进,先从训练链路的可靠性做起,再逐步把推理和WebUI融合进来,最后再考虑高级功能。希望这篇文章里的经验和细节点能对你有实际帮助,哪怕是帮你少踩一两个坑,也算值了。