
做AI平台的人早晚会碰上一个尴尬局面训练任务把几块显卡吃得干干净净推理服务的延迟却在同一台机器上飙到不可接受或者反过来线上推理还算平稳一启动离线评测任务关键服务直接被打挂。“隔离”两个字听起来简单但真去落地既要分算力又要分显存还要管存储带宽和网络通道麻烦得很。这篇文章就从“AI 模型训练与推理的资源隔离”说起聊一聊我在这类场景里验证过的做法、踩过的坑以及一些值得提前想清楚的规划原则。我会把视角放在一个真实可操作的层面上先在单机上解决进程和容器的边界再在集群里靠标签、配额和优先级把两类负载分开最后落到GPU显存和算力怎么切、存储和网络怎么管。无论你是平台运维、算法工程师还是偶尔要接管集群的团队负责人这篇文章都能提供一个判断框架让你知道该在什么场景下用什么隔离方案。1. 训练和推理的资源画像两种工作负载根本不在一个频道上1.1 训练要“占坑”推理要“快进快出”先想清楚一个事实模型训练和在线推理对资源的口味几乎完全相反。训练任务一旦启动往往以小时甚至天为单位持续占用GPU、内存和存储带宽它不在乎单次请求花多少时间只在乎单位时间内能灌进去多少数据、能算出多少梯度。推理任务恰恰相反每个请求都是短小细碎的可能只占几十毫秒的GPU时间但它对延迟极其敏感尤其是线上服务P99一涨产品侧立刻就能感觉到卡顿。这种差异决定了我们做资源隔离时不能简单地“把显卡分成两半你一半我一半”。因为训练任务的资源占用是波动的batch大小、模型并行策略、数据加载快慢都会让显存和算力需求不断变化推理任务则相对稳定它更怕的是别人突然冲进来抢走几百毫秒的算力导致一次超时。我见过不少团队一开始图省事把训练和推理放到同一批机器上理由是“反正GPU那么贵不用白不用”。前几周确实风平浪静因为训练任务还没到峰值阶段。可一旦开始跑大规模预测或模型调参显存和算力同时被拉满推理服务的响应时间就会像过山车一样起伏。这时候才意识到有些资源争抢是可以在设计阶段就避免的没必要靠事后救火。1.2 显存、算力、带宽三方面都不同画一张简单的对比表能更直观看出两类负载的差异维度离线训练在线推理单次任务时长小时到天毫秒到秒GPU利用率往往接近满载往往只有个位数到十几显存变化随batch和动态shape大幅波动相对稳定峰值较可预测延迟敏感度低更看重吞吐高P99是生死线网络需求大量梯度同步、数据拉取小包高频跨节点请求多故障容忍度可断点续跑容忍重试单次失败直接影响用户为什么训练任务会把GPU利用率打满因为它本质上是在“榨取”算力来减少训练时间多等一分钟都是成本。推理服务则不一样大部分模型在推理阶段根本用不满GPU很多时间花在数据预处理、网络传输和序列化上计算只占一小段。这就造成一种很典型的场景推理任务显存占了几个GB算力却只在请求进来那一瞬间被使用其他时间都是空的。如果这时训练任务想要“顺便”用这块卡就会导致推理请求进来时GPU的运算单元正在为训练服务推理计算只能排在后面延迟自然失控。1.3 隔离前先做负载画像很多人跳过这一步直接开始配容器限流或调度规则结果方案总是隔靴搔痒。我的建议是动手隔离之前先给当前集群做一次至少七天的负载画像。怎么做把每个容器或进程的GPU利用率、显存占用、CPU使用率、磁盘读写、网络吞吐都按分钟级别记录下来同时记录业务侧的延迟指标。重点不是看平均值而是看峰值重叠的概率。比如训练任务每天凌晨跑定时评估推理服务正好也在凌晨有大流量波动两者峰值一旦重叠就是隔离方案必须覆盖的边界条件。负载画像还能回答一个关键问题到底需不需要物理隔离。如果训练和推理的任务类型都偏轻量峰值重叠很少逻辑隔离可能就够了如果发现训练任务几乎整天占满GPU那就别再纠结什么优雅共享方案了直接考虑节点池分离成本虽然高但稳定性收益是确定的。没有数据支撑的隔离规划最后多半要靠运气。2. 单机内部的资源隔离先守住进程和容器边界2.1 进程级隔离只能解决浅层问题单机层面最朴素的做法是通过进程管理工具把CPU亲和性、内存上限、GPU设备编号绑定到特定任务上。例如给训练进程绑定2到7号CPU核给推理进程绑定0到1号核再用内存限制防止训练任务把系统内存吃到触发OOM。这套方法应付一两台机器、一两个模型的时候是够用的手工操作也不复杂。但进程级隔离有几个明显缺陷。一是GPU显存和算力无法通过Linux原生机制真正分割你只能用设备可见性变量让不同进程看到不同显卡如果多个进程被分配到同一块卡它们的算力争抢是控制不住的。二是维护成本太高每加一个任务都要人工确认绑定关系一旦有人配置错排查起来非常痛苦。三是操作系统层面的缓存、页表、中断处理仍然是共享的训练任务大量读写文件时系统缓存抖动也会拖累推理进程。所以我的建议是进程级隔离只适合做临时止血不适合作为长期方案。真正要稳定运行至少得把任务放进独立的容器或虚拟机里。2.2 容器边界的组合限制怎么写容器方案的好处是可以在创建任务时一次性声明资源上限。下面是一个典型的组合限制声明我用通用字段来表示不管底层用的是哪种容器运行时思路是一致的resources: cpu: 8 memory: 32Gi gpu: 1 gpuMemory: 40Gi storageRead: 200MB/s storageWrite: 100MB/s关键细节是CPU和内存的限制相对标准真正容易忽略的是GPU。如果容器平台不支持显存字段那就需要在GPU分配层面额外加一道校验否则可能出现一个只申请了4GB显存的任务实际把整张卡的显存都占了。早期我们遇到过类似情况某个数据预处理容器不小心跑到了GPU卡上模型服务瞬间OOM整条链路雪崩。配置容器边界还要注意“限制不等于隔离”。CPU限额能防止任务占用超过设定核数但多个容器依然共享同一批物理核时调度器的上下文切换、缓存争抢仍然存在。要想做到比较彻底的隔离单机层面还需要在系统配置上动手脚比如把不同任务划分到不同的NUMA节点让训练任务的CPU访问内存路径不会干扰推理任务。这个操作并不复杂但需要在上线前确认硬件拓扑临时改很难。2.3 容器隔离也盖不住的两个盲区即便容器配置写得再完善有两个盲区仍然存在。第一个是共享GPU导致的算力争抢。两个容器即便各自限制显存只要它们被调度到同一张卡上GPU的计算单元就仍然是共享的。训练任务可以轻松把流处理器占满推理任务的计算请求只能排队这个排队时间会直接变成推理延迟。显存限制从来不等于算力隔离这是最容易误解的一点。第二个是存储和网络带宽的不可控。容器默认只限制CPU内存对磁盘IO和网络吞吐往往没有硬性限制。一个训练任务疯狂写检查点可以把整块磁盘的IO能力拖垮一个训练集群在做梯度同步时也能把网卡带宽打满让推理服务跨节点通信出现大量重传。要解决这两块必须把存储和网络纳入隔离方案后面我会单独展开。3. 集群调度的隔离策略节点池、标签与配额3.1 机器打标签物理池是最大前提单机隔离做得再好也架不住调度器把任务随机分配到不该去的地方。所以集群层面第一件事就是把机器按用途打上标签分成训练池、推理池、评测池、开发调试池。调度器只允许对应标签的任务在对应池内运行这是所有隔离方案里最粗暴也最有效的一层。有人会问难道不能直接用一个池子靠容器配额来保证不越界吗答案是如果你胆量够大可以试但代价往往很惨痛。因为即便任务数量不算多一旦某个训练框架的分布式同步环节写得不够克制它会把集群所有网络节点的带宽都打满推理服务的跨节点调用全部受阻。物理池的好处是即使训练池把资源用尽了推理池的机器依然干干净净不会受到波及。节点打标签的操作本身不难难的是后续治理。新节点加入如果没有自动化初始化流程很容易漏打标签然后被默认调度器当成公共池分配任务。我见过不止一次运维同学开开心心加了台新机器结果当晚就被训练任务跑满第二天推理服务延迟告警。建议把标签校验放在节点准入阶段做不到准入校验也要写清楚入网前检查清单。3.2 配额和命名空间防住“撑死胆大的”给机器分好池子之后还要给每个业务团队设置资源配额。没有配额约束最直接的后果就是一个团队把池子占满其他团队排队等到天荒地老。很多时候大家把配额字段一写就觉得完事了但实际上配额至少要考虑三层CPU和内存、GPU卡数、总显存容量。GPU显存配额尤其容易被忽略。某些任务申请1张GPU卡但模型很大实际的显存需求可能超过一块卡的一半。如果只看卡数不看显存两个大模型任务被调度到同一张卡后就会争抢显存甚至触发OOM。我在实操中会把每个业务团队的显存配额单独列一项由调度器在分配时校验。校验不了的场景就在镜像里内置一个显存预检步骤启动时先探测显卡剩余显存不够就自动退出并返回排队原因。配额还会引出一个公平性问题离线训练任务可以排队等待在线推理服务却不能等。因此推理团队通常需要独占高优先级配额训练团队则使用可抢占配额。这个在分配上要提前约定不能全池共享一个默认值。3.3 优先级和抢占在线推理必须被保护即便做了节点池和配额依然可能出现某个训练任务通过预留资源的方式把推理池挤占的情况。所以隔离策略里还必须包含优先级机制在线推理服务在整个集群里拥有最高的优先级训练和评测任务可以被VIP调度器挂起、抢占、重新排队但推理服务永远不能被训练任务挤掉。这里有个容易被忽略的点被抢占的训练任务需要能够恢复进度否则强行抢占只会导致训练计算浪费。训练任务的监控检查点要足够频繁至少每十分钟保存一次模型状态。否则被抢占一次重启就要从头再来团队之间的仇恨值会迅速飙升。优先级机制的具体实现可以在调度器里为不同服务类型定义不同的优先级阈值再配合抢占策略。例如推理服务的优先级写10训练任务写5当训练任务和推理服务同时申请同一池内资源时调度器优先满足推理服务。如果是配额已满且训练任务长时间运行调度器可以将其挂起等推理服务完成资源释放后再恢复。4. GPU算力与显存隔离从逻辑分片到硬件级切片怎么做4.1 第一档按显存上限隔离的局限很多深度学习框架提供了限制显存使用的参数例如设置显存占用比例或者通过特定环境变量让进程认为自己只看到一部分显存。这种做法的价值在于防止任务越界占满整卡让同一块卡上能同时跑多个小模型。但它的局限非常明显显存和算力是两个维度。一个训练任务就算只分到20GB显存它的计算指令仍然可以塞满整个GPU的计算单元让旁边同样卡在显存限制里的推理任务排队等算力。所以如果你只依赖显存限制做隔离那只能在“不同任务互不干扰”的幻想里睡上一段时间等到峰值流量一来就会被现实叫醒。我的建议是显存限制只作为一道兜底线防止OOM级灾难不要把它当作真正的算力隔离方案。4.2 第二档时间片共享的代价GPU时间片隔离是另一条常见路线。它的思路是当一个任务用不到全部算力时把GPU算力按时间片分给多个任务轮流使用。这样每个任务都能分到一定的计算资源且不会让GPU空闲。代价也很明确任务切换会产生开销。对于训练任务来说时间片切换可能让有效计算时间下降对于推理任务来说时间片带来的抖动非常致命。推理请求通常在几十毫秒内完成如果轮到它时正好被切出去等待下一个时间片回来延迟可能直接翻倍甚至更高。所以我的经验是时间片适合用在低优先级的评测任务、统计算法调试任务不适合给在线推理服务使用。另一种变体是按算力比例进行软隔离比如让某个任务最多只能使用30%的计算单元。这种方式比纯时间片平滑一些但仍然受限于任务的调度粒度。如果你希望推理服务的P99长期稳定还是别依赖这一档。4.3 第三档硬件多实例分片的硬边界如果硬件支持优先考虑硬件级多实例分片方案。它把一张物理GPU切割成多个独立实例每个实例拥有独立的显存、独立的内存控制器、独立的计算单元实例之间在硬件层面天然隔离互不抢占。这套方案比任何软件层的逻辑分片都可靠因为一个实例里的任务跑得再疯也不会影响另一个实例里任务的延迟。硬件分片的坑在于切分粒度是固定的无法根据每个任务的实际需求动态调整。比如一张卡显存共80GB硬件方案通常支持切成7个实例或8个实例但每个实例的显存大小是固定的。如果推理模型需要30GB显存而切分方案里没有恰好对应的实例大小你就只能用一块更大的实例浪费掉一部分显存。另一个坑是分片方案必须在显卡初始化时配置好后续运行时不能随意修改。修改配置往往需要重启GPU如果集群里正有训练任务在跑这会引发大范围重启。所以硬件分片方案更适合长期稳定的推理服务不适合频繁变化的实验环境。4.4 三种方式的选型对照这里给出我自己的选型建议方便你直接抄作业隔离方式隔离强度额外开销适合场景显存限制弱只能防止OOM低小模型混部、临时兜底时间片共享中但延迟抖动明显中离线评测、批量调参硬件多实例分片强稳定可靠低但灵活性差在线推理、关键生产链路我在实际项目中更倾向这样的组合半张物理卡给推理服务预留确保延迟可控剩下能力切给训练任务但不能让训练任务和推理服务混用同一片硬件实例。如果业务量不大就用一块卡专门跑推理另一块卡专门跑训练物理隔离永远是最省心的。5. 存储与网络的隐性隔离吞吐、带宽和缓存都是资源5.1 磁盘IO队列不能混用GPU隔离解决的是计算和显存问题但AI任务从来不只是算GPU。训练任务要拉取数据集、写检查点、缓存中间特征推理服务要加载模型、写访问日志、读配置文件。这两类IO模式放在同一个存储系统里就会互相拖累。训练任务通常会产生大量顺序写比如每跑完一轮就写一次模型检查点。这个写操作如果和推理日志的随机写落到同一块磁盘磁盘调度器会频繁切换寻道方向整体IO效率急剧下降。更严重的是推理服务的日志丢失和模型加载超时会直接影响线上可用性。我的建议是至少把训练和推理的存储卷从物理上分开。训练挂载高性能大容量盘推理挂载低延迟SSD两者之间不要共享同一个文件系统挂载点。如果条件允许还可以给不同目录设置不同的IO优先级让推理服务的磁盘请求优先获得处理。这一步很多人会忽略等到磁盘IO被打满才发现问题那时候再迁移数据就很痛了。5.2 缓存目录和临时文件必须划分边界AI训练和推理都有缓存机制。训练会把预处理后的数据缓存到本地临时目录推理则会把模型文件缓存起来以便快速加载。如果这两类缓存目录没有被严格划分就会发生一件特别戏剧化的事清理磁盘的定时任务把推理服务的模型缓存当成垃圾清掉了然后所有推理服务在第二天流量高峰时冷启动加载模型延迟集体飙升。这听起来像是低级错误但我确实遇到过不止一次。根本原因就是大家只关注了计算GPIO隔离忘了文件系统层面的边界。一次性规划好训练缓存目录、推理模型缓存目录和临时文件目录并在清理脚本里明确白名单能省掉很多半夜被叫醒的机会。5.3 网络流控训练同步别挤占推理链路分布式训练对网络的消耗远超很多人想象。几十张卡同步梯度的时候数据量可以达到每秒几十GB如果和推理服务的跨节点请求共享同一张网卡和同一条网络链路推理服务的延迟会直线上升。要处理这个问题第一步是区分网络平面。训练和推理的流量最好走不同的网段或不同的物理链路做不到物理分离也要在虚拟网络层面做隔离。第二步是对网络流量做带宽限制例如给训练任务的同步流量设置上限让它不能把网卡带宽全部占满。设置阈值时要注意训练任务的网络性能下降最直接的影响是GPU利用率也会下降因为数据喂不过来所以阈值不能设得太低要在吞吐和隔离效果之间找一个平衡点。网络隔离还有一个细节容易被忽略管理面和数据面的流量要分开。如果集群管理工具使用的主机通信链路和训练数据链路互相争抢GPU任务会在调度时出现莫名其妙的超时。建议把管理网络和训练网络独立出来至少保证管理流量有独立的优先通道。6. 隔离效果的验证与监控把争抢变成看得见的数字6.1 关键指标表按进程看还是按容器看做隔离规划时很多人只盯着GPU利用率这一个指标这是远远不够的。GPU利用率高到底是被哪个容器拉高的显存占用高是什么时候涨上去的响应延迟变大是算力不足还是IO拖慢要回答这些问题监控粒度必须细化到进程或容器而不是只盯着节点级图表。我通常会关注以下几类指标类别关键指标为什么重要GPU利用率、显存占用、温度、降频状态判断是否算力打满或显存不足CPU使用率、软中断、上下文切换判断CPU是否成为瓶颈存储IO等待时间、读写带宽、队列深度判断磁盘争抢是否严重网络吞吐、丢包率、重传率判断是否因网络拥塞影响延迟业务P50、P99、错误率最终衡量隔离是否生效重要的一点是不要只看平均值要看峰值曲线和重叠状态。训练任务可能平均GPU利用率只有60%但每10分钟会有一个同步阶段把利用率拉到95%。如果在监控图上只看平均你会误以为还有40%算力可用然后把推理服务调度上去结果每次同步阶段推理延迟就飙一下。6.2 上线前的隔离压测流程任何隔离方案落地后都要用压测来验证不能凭感觉说“看起来没事”。我常用的流程很简单第一步先给推理服务打一段稳定的基准流量记录它的P99延迟和错误率作为对照基线。第二步在隔离环境下启动一个模拟训练任务让它以接近真实的负载运行。第三步观察推理服务的延迟曲线如果P99仍然在业务可接受范围内则说明隔离方案有效如果P99明显恶化就需要逐步排查是算力、显存、存储还是网络出了问题。压测时有一个容易遗漏的点模拟训练任务要包含数据加载和检查点写入。只跑纯GPU计算是测不出存储争抢的。我在压测中会把训练任务的数据加载频率调高让它的IO模式接近真实场景。这样压出来的结果才可能原样映射到线上。6.3 一次混跑事故的排查复盘最后分享一个排查实例帮助你把前面所有隔离原则串起来。某团队有两类服务一个离线训练任务一个在线推理服务。上线初期业务量小混在同一批机器上风平浪静。后来训练数据量变大某天下午推理延迟突然冲到三秒以上。排查链路是这样的先看GPU利用率的节点级图表发现整台机器GPU利用率并不高只有50%左右于是很疑惑。再按容器维度拆开看发现训练容器和推理容器被调度到了同一块GPU上训练容器在大部分时间只占少量算力但每当它的数据加载阶段结束GPU利用率会瞬间冲到90%以上推理请求正好在这个窗口被堵住。再往深挖发现训练容器的GPU设备编号没有限制调度器也没有强制绑定导致它可以在整台机器的任何一张卡上运行。最终修复方案很简单把训练任务固定到专用GPU上并将推理服务所在的池子设成不允许训练任务调度进去。整个过程最大的教训是如果从一开始就按节点池分离并严格校验GPU设备编号这次故障完全可以避免。我自己做隔离规划时习惯先回答三个问题业务峰值会不会重叠推理服务对延迟到底多敏感隔离付出的成本是否可以接受。能接受混跑就用逻辑隔离加配额不能接受就物理分离加节点池。合理的隔离不是消灭资源争抢而是把争抢控制在不会影响关键业务的范围内。