“数据有两亿条,要不要上分布式?”这是大规模机器学习里最容易问错的问题。两亿条稀疏样本训练一个线性模型,可能一台机器流式读取就够;一个几百亿参数的模型,即使只有少量样本,也可能因为单卡放不下而必须切分。规模化没有统一门槛,它至少包含三种不同压力:数据放不下、模型放不下,或者在业务截止时间内算不完。
这一章不从“堆机器”开始。我们先把目标函数、批量梯度和吞吐指标对齐,再判断瓶颈究竟在数据读取、计算、显存还是通信。之后逐步进入同步数据并行、模型切分、MapReduce、在线学习、流式监控和故障恢复。最后用一个带延迟标签的广告预估案例,把离线训练与在线更新接成完整链路。
本章用 表示训练样本数, 表示一次更新使用的 mini-batch 大小, 表示数据并行 worker 数, 表示梯度累积步数。若每个 worker 的本地批量都是 ,则常见的有效批量为 。对变长序列任务,更准确的尺度往往是有效 token 数,而不是样本条数。
大规模训练首先是一个诊断问题。我们真正想缩短的是“达到目标质量所需的时间”,不是单纯把每秒样本数做高。一套吞吐翻倍但需要更多更新步才能达到同样验证指标的方案,未必更快;一套训练很快、数据却已经过时的方案,也没有解决业务问题。
可以先把现状归入下面三类。它们可能同时出现,但解决办法不同。
扩展不是第一反应:先确认瓶颈来自数据、模型、时限还是吞吐,再决定优化单机或增加设备。
先做一个单机基线,并把每个 step 拆成至少四段:取数、主机到设备传输、前向与反向、优化器更新。GPU 利用率低时,直接加 GPU 常常只是让更多设备一起等数据。模型还没跑满单卡时,上多机还会引入梯度同步和故障处理,系统反而更慢。
数据量增加只有在“新增样本带来新的、与部署分布相关的信息”时才有帮助。重复记录、错误标签、严重偏置或来自过时策略的日志,会把存储和训练成本放大,却不一定改善泛化。
判断是否值得扩数据,可以做三件事:
高偏差模型的训练误差与验证误差都很差,继续堆同分布数据通常帮助有限;高方差模型或长尾切片样本不足时,新增高质量数据更可能有效。即使学习曲线仍在改善,也要把采集、标注、存储和训练成本写进决策。
大系统会放大小错误。正式扩容前,应让同一训练代码在一小份可人工核对的数据上完成:损失下降、梯度检查、过拟合小样本、断点恢复,以及固定评估集上的结果复现。否则,分布式环境里的通信抖动会掩盖本来只是标签错位或损失归一化错误的问题。
设每个样本 的损失为 ,经验风险为:
如果一次使用全部 个样本,得到完整梯度:
批量梯度下降每次都沿这个方向更新。它的单步方向稳定,但每次更新要扫描全量数据;数据很大时,等很久才发生一次参数更新,而且很难让每条样本都高效参与同一个设备上的计算。
随机梯度下降严格来说使用一个随机样本:
mini-batch 则对一个大小为 的集合 求平均:
三者并没有优化三个不同目标。它们的主要区别是如何估计同一个完整梯度,以及每次更新用多少计算换取多大噪声。
三种方法估计的是同一个总体梯度,差别在于每次更新投入多少计算、承受多少随机噪声。
单样本 SGD 能更早做第一次更新,也不要求把全部数据放进内存。但在 GPU 或 TPU 上,batch size 为 1 往往不能填满矩阵计算单元,内核启动和数据搬运开销会占很大比例。mini-batch 通过向量化一次处理多条样本,墙钟时间通常更有优势。
因此至少要区分三个量:
batch 变大可能提高吞吐,却降低每看一条样本所产生的更新次数。最终要比较的是 time-to-quality,而不是只比较 step/s。
若数据量不能整除 batch size,最后一个批量可能只有 个样本。损失和梯度应该按实际有效样本数或有效 token 数归一化。把分母固定写成 会让最后一批权重偏小;在分布式场景中,各 worker 样本数不等时,简单平均 worker 梯度也可能让样本权重失真。
mini-batch 梯度为什么能替代完整梯度?关键不是“样本少也差不多”,而是抽样机制给出的期望关系。
如果每个样本被均匀随机抽到,且抽样没有依赖当前标签或损失,那么:
这说明梯度估计在重复抽样的平均意义上指向完整梯度。它不保证每个 batch 都方向正确,也不保证训练损失逐步下降。某次 batch 恰好包含异常样本,更新完全可能暂时上坡。
小批量梯度在平均意义上无偏;增大批量主要降低方差,学习率还要结合损失归约方式一起调整。
在独立同分布的近似下,若单样本梯度协方差为 ,batch 平均梯度的协方差大致为:
不放回地从有限训练集均匀抽样时,还会有有限总体修正。直观上,batch 越大,随机方向越稳定,但方差不会无限带来线性收益:样本梯度之间相关、硬件容量有限,而且超过某个范围后,新增样本主要重复已经知道的方向。
无偏也有条件。如果数据按类别排序后直接顺序读取、只从活跃用户抽样,或 hard-negative 采样没有做相应修正,那么训练梯度对应的可能是另一个加权目标。加权采样不一定错,但要把它写成明确的优化目标,不能继续声称是在均匀优化原数据集。
更新写成:
较大学习率能快速移动,也会放大梯度噪声;较小学习率更稳,但可能在平坦方向上走得很慢。训练早期通常允许更大步幅,后期逐渐衰减,让参数在最优区域附近稳定下来。对深度模型,warmup 会先从小学习率升到目标值,避免初始化阶段的激烈更新。
学习率不能脱离 batch、损失归一化和优化器实现讨论。若代码从“batch 内求平均”改成“batch 内求和”,梯度大小会随 batch 成倍变化;原学习率直接复用就失去比较意义。
一个 epoch 通常指训练流程消费了一遍定义好的训练集合。它是数据遍历单位,不等于一次优化更新。若 、batch size 为 100,一个 epoch 大约包含 1000 次更新;使用 8 个 worker 时,只要分片正确,全局仍应合计看完约 100000 个样本,而不是每个 worker 都重复看全量。
日志数据常按时间、用户或类别聚集。若连续 batch 高度相似,梯度噪声会带有长周期偏差。常用做法是在每个 epoch 开始时重新打乱索引,或者对流式数据使用足够大的 shuffle buffer。
buffer shuffle 不是全局均匀打乱。buffer 太小,只能在局部窗口交换样本;若原始文件按类别分块,输出仍可能长时间只看到一个类别。可以先随机化文件分区顺序,再在分区内打乱,并检查连续 batch 的标签与关键特征分布。
同步数据并行中,每个 worker 应拿到互斥的数据子集。常见流程是先用同一个 epoch 种子产生全局排列,再按 rank 切片。每个新 epoch 都要更新采样器的 epoch 状态,否则每轮可能重复同一顺序。
若样本数不能整除 worker 数和本地 batch,有两种常见选择:
二者都可以使用,前提是记录策略,并在度量和权重里考虑影响。不能让某个 worker 提前结束、其他 worker 仍进入 all-reduce,否则集体通信可能一直等待。
无限数据流没有天然“遍历一遍”。这时应改用已处理样本数、token 数、事件时间窗口或优化器更新步数描述进度。学习率调度器也应跟随真正稳定的尺度。例如流量每天波动时,“一天一个 epoch”会让同样的学习率阶段包含不同样本量。
随机梯度带来的训练损失天然会抖。一次 batch 损失上升,不足以证明发散;一段训练损失下降,也不足以证明泛化改善。监控要把短期优化信号和固定验证集上的质量信号分开。
对每步损失 ,指数移动平均可以写成:
越接近 1,曲线越平滑,但响应越慢。训练初期若 ,可以做偏差修正:
移动平均适合判断大方向,不能替代原始分布。最好同时记录 batch 损失分位数、梯度范数和学习率;均值下降时,少量 batch 的极端损失可能仍在恶化。
判断是否收敛不能只看单个 batch:把原始噪声、平滑趋势、验证表现与实际耗时放在一起。
固定验证集不应跟着在线训练不断变化,否则曲线变化可能只是评估样本变了。对于有时间漂移的系统,可以同时保留一个固定回归集和一个滚动近期集:前者查代码与训练回归,后者看当前业务适配。
每一步在全训练集上算损失,会把大规模训练重新拖回全量扫描。可以每步记录本 batch 指标,每隔若干步聚合移动平均,每隔更长周期在固定验证集上评估。评估间隔应按故障成本决定:昂贵训练若两小时后才发现 NaN,省下的监控成本并不划算。
原始 SGD 只用当前梯度。动量会累计一段时间的方向,减少狭长谷底里的左右摆动:
Adam 一类自适应优化器还会估计梯度的一阶矩和二阶矩,为不同参数调整有效步长。它们可能让早期训练更省调参,但不会消除 batch、学习率、权重衰减和验证质量之间的关系。更换优化器后,要把达到同一质量的时间和最终指标都重测。
把有效 batch 从 放大到 时,常见经验起点是把学习率从 调到 ,并在训练开头 warmup。它的直觉是:原本连续做 次小 batch 更新,现在用一次大 batch 近似它们的合计移动。
但这个近似假设 次更新期间参数变化不大。当 batch 很大或学习率越过稳定上限时,近似会失效。真实任务还受模型结构、归一化层、优化器、数据增强和损失尺度影响。某个 ImageNet 配方成功,不代表文本、推荐或强化学习任务可以原样套用。
batch 从小变大时,梯度方差下降,可能在相同样本数下更稳定;达到某个任务相关范围后,进一步扩大 batch 对统计效率帮助很少,却减少了每个 epoch 的更新次数。此时即使硬件吞吐继续增加,达到目标质量所需 epoch 或样本可能上升。
实践中可以做一组短跑实验:固定数据顺序、目标质量和总样本预算,比较多个有效 batch 的训练曲线。若曲线在“已看样本数”坐标上开始明显落后,就接近或越过了当前配方的有效边界。
不要只改 batch 和学习率,却忘了学习率调度周期、权重衰减语义、动量缓冲区、BatchNorm 统计或梯度裁剪阈值。大批量实验应把完整训练配方版本化,并与小批量基线做同协议比较。
分布式之前的优化通常更便宜,也更容易验证。一个实用顺序是:先用性能分析器找空闲,再解决输入管线和小算子,最后处理精度与内存。
让读取、解码与计算重叠,通常比在数据供应不足时盲目增加 GPU 更有效;混合精度与梯度累积解决的是另一组瓶颈。
理想状态下,设备在计算 batch 时,CPU 已经解码并准备 batch 。常用手段包括:
预取不是越多越好。队列太大会占用内存,并让训练继续消费已经过时或无法追踪的数据;worker 太多也可能争抢 CPU、磁盘和网络。应测输入等待占 step 时间的比例,而不是按经验把线程数拉满。
把逐样本 Python 循环改成批量张量操作,常常比换分布式框架更有效。还可以合并细碎算子、使用编译图、让张量形状更稳定,并减少训练循环中的同步取值。每次把 GPU 张量转回 CPU 打日志,都可能强制等待前面所有异步计算完成。
混合精度通常让适合的矩阵计算使用 FP16 或 BF16,同时保留部分权重、归一化或归约为 FP32。FP16 动态范围较窄,反向传播中的小梯度可能下溢;loss scaling 会先放大损失与梯度,更新前再缩回,并在检测到 Inf/NaN 时跳过或调整缩放因子。BF16 有更大的指数范围,通常不需要同样的 loss scaling,但尾数精度更低。
开启自动混合精度后,要比较验证指标,并监控 Inf/NaN、梯度范数和被跳过的更新。速度提升不能替代数值验收。
如果目标有效 batch 放不进显存,可以连续处理 个 micro-batch,只累积梯度,第 次后再更新:
optimizer.zero_grad(set_to_none=True)
for micro_step, (x, y) in enumerate(loader, start=1):
with autocast_context():
loss = model(x, y) / accumulation_steps
scaler.scale(loss).backward()
if micro_step % accumulation_steps == 0:
scaler.unscale_(optimizer)
clip_grad_norm_(model.parameters(), max_norm=1.0)
scaler.step(optimizer)
scaler.update()
除以 是为了在等长 micro-batch 且损失求平均时保持梯度尺度。若各 micro-batch 有效 token 数不同,应按总有效 token 加权。梯度累积还会改变 BatchNorm 更新、dropout 随机序列和数据增强,因此只能说“梯度平均在一定条件下等价”,不能宣称整条训练轨迹完全相同。
当模型能放进单个设备、单机也已经跑得较满,而时间仍不满足要求时,同步数据并行是最直接的扩展方式。每个 worker 保存完整模型,读取不同的本地 batch,独立完成前向与反向,再把梯度聚合。
设第 个 worker 的本地 batch 为 ,每个 batch 大小相同。全局平均梯度是:
All-reduce 会让各 worker 获得相同的聚合结果;随后每个 worker 用同一优化器状态执行同样更新,模型副本继续保持一致。
同步数据并行让每张卡处理不同样本,再聚合梯度;扩展效率取决于计算能否覆盖通信等待。
若每个 worker 的本地 batch 是 64,使用 8 个 worker、累积 2 次再更新,有效 batch 通常为:
但“通常”不是“永远”。若不同 worker 的有效 token 数不同,先在每个 worker 内求平均、再平均 worker,会让短 batch 和长 batch 权重相同。更稳妥的做法是分别 all-reduce 损失或梯度总和与有效计数,再除以全局计数。
框架通常把参数梯度装入多个 bucket。反向传播算完较后层的一个 bucket 后,就可以开始归约,同时继续计算前面层的梯度。bucket 太小会产生许多通信启动开销,太大又推迟第一次通信。性能分析应查看计算与通信时间线,而不是只看网络带宽峰值。
同步训练的 step 速度由最慢 worker 决定。某台机器磁盘慢、发生热降频,或拿到异常长序列,所有 worker 都会在集体通信处等待。数据长度分桶、健康检查和慢节点剔除,往往比继续加节点更有用。
固定同一个工作量,单设备时间为 , 个设备时间为 ,加速比与并行效率为:
8 张卡跑快 6 倍时,效率是 。继续扩容若只能把时间从 10 小时降到 9 小时,就要评估多出的设备费用和工程复杂度是否值得。
数据并行会在每个设备复制完整模型。模型参数 、梯度、优化器状态和激活共同决定内存;Adam 的一阶、二阶矩还会再占多份参数规模。模型本身放不下时,增加普通数据并行 worker 没有帮助。
并行策略由模型是否放得下、网络拓扑、数据位置和同步要求共同决定,不是设备数量越多越好。
完全分片数据并行会把参数、梯度和优化器状态切到多个 rank,只在前向或反向需要某层时临时 all-gather 对应参数,再释放完整副本。它保留了“不同 rank 处理不同数据”的数据并行语义,却用更多通信换取更低单卡内存。
适合场景是:模型结构仍能按数据并行训练,但完整训练状态无法在每卡保存。代价包括通信更复杂、checkpoint 变成分片格式,以及小层频繁聚合可能降低效率。
张量并行把同一个大矩阵乘法按行或列切到多设备。每个设备只保存和计算一部分权重,但层与层之间需要 collective 通信来拼接或归约结果。它适合单层就很大的模型,通常要求高速、稳定的设备互联。
切分计划必须和模型算子对应。任意把一个不支持分片的算子拆开,可能产生大量数据重分布,通信成本超过计算收益。
流水线并行把不同层放到不同 stage,再把一个 batch 拆成多个 micro-batch,让不同 stage 同时处理不同 micro-batch。开始和结束阶段会出现流水线气泡;stage 计算不均衡时,快 stage 仍要等慢 stage。
提高 micro-batch 数可以减少气泡比例,却会增加调度和激活管理复杂度。切分点应让计算、内存和通信尽量平衡,而不是机械地按层数平均。
参数服务器架构把变量放在一组 server 上,worker 读取参数、计算梯度并提交更新。异步模式不必让所有 worker 每步对齐,对慢 worker 更宽容;但某个 worker 提交的梯度可能基于很旧的参数,这就是梯度陈旧。热点参数、网络瓶颈和失败重试也会影响一致性。
参数服务器并不是 all-reduce 的“旧版同义词”。前者适合某些稀疏参数、弹性 worker 或异步任务;后者更适合同步的密集梯度训练。选择依据应是参数形态、网络拓扑、容错需求和可接受的优化偏差。
MapReduce 把大规模计算约束成两类函数:Map 独立处理输入键值对并产生中间键值对,Reduce 合并同一键的中间结果。运行时负责数据切分、调度、重试和跨机器传输。
它很适合下面这些任务:
例如线性模型在固定 下的梯度和可以分片计算。Map worker 输出局部梯度总和 和有效样本数 ,Reduce 得到:
梯度下降需要反复执行“读取数据—计算梯度—更新参数”。如果每一步都启动一个 MapReduce 作业,并把中间状态写到持久存储,再在下一步重新调度,作业启动、磁盘 I/O 和 shuffle 会占据大量时间。深度网络还需要频繁传播大张量,远超传统键值聚合的舒适范围。
MapReduce 的思想仍能帮助我们识别可并行和可归约部分,但训练系统通常使用内存中的 collective、参数服务器或专用数据流引擎。不要因为一个计算能写成 map 和 sum,就认定完整训练都适合传统 MapReduce 执行模型。
Map task 失败后可能重跑。若任务只生成确定的中间结果,重复执行通常安全;若 Map 中直接扣费、写外部数据库或递增不可回滚计数,重试可能产生副作用。大数据任务应让输出按输入分区和版本确定命名,先写临时位置,再原子提交,并对重复事件去重。
在线学习不只是把离线训练循环放进 while True。数据到达、标签确认、参数更新和模型发布发生在不同时间;只要其中一条链路没有版本与去重,模型就可能用错标签或重复学习同一事件。
假设广告在 10:00 展示,用户 10:03 点击,第二天购买,七天后仍可能退款。训练记录至少需要区分:
用事件时间、稳定 ID 和可回放日志把“预测发生时”与“标签抵达时”分开,才能避免错误负例和重复更新。
曝光后五分钟没有购买,可能只是标签尚未到达。若立刻记为负例,模型会系统性低估长决策周期用户。可以设置成熟窗口、使用延迟反馈模型,或把未成熟样本保持为“未知”。训练与评估都要采用一致的标签截断规则。
只比较特征分布不能发现所有概念漂移,因为 可能稳定,标签关系却改变。反过来,输入漂移也不必然造成质量下降。监控的作用是发出调查信号,是否重训仍要结合成熟标签和切片指标。
如果每次只用最新事件更新,短时热点和类别不平衡会让参数剧烈偏移。回放缓冲区可以混入近期、历史、稀有正例和关键切片样本。采样比例要明确,必要时用权重修正训练目标。
回放不是无限保存全部历史。可以按时间衰减、分层水库采样或业务窗口控制大小,并保留一份固定回归集,防止新模型在长期重要场景上遗忘。
消息系统常采用至少一次投递,同一事件可能出现多次。训练样本应有稳定事件 ID;写入特征、标签和更新队列时按 ID 与版本去重。模型发布也应使用不可变版本和原子指针切换,让重试“得到同一个结果”,而不是重复更新一次参数。
在线或频繁训练系统不能只画一条 loss。模型可能正常收敛,但输入列已经全为默认值;吞吐可能正常,标签队列却延迟两天。监控应沿数据链路逐层定位。
对延迟标签任务,还要监控标签成熟曲线:曝光后 1 小时、1 天、7 天分别能观察到多少最终标签。否则,近期 AUC 突然升高可能只是最难确认的样本还没到。
“点击率下降 10%”缺少窗口、分母和基线,无法行动。流式指标应明确:事件时间还是处理时间、滚动 1 小时还是自然日、与昨天同时间还是过去四周同星期比较,以及迟到事件如何补算。
同一总体指标也要按高风险切片拆开。新用户、某地区或某设备流量只占 2%,总体均值几乎看不见它们的故障。切片不是越多越好,应围绕部署风险和业务承诺预先定义,并控制多重告警噪声。
每次模型发布应绑定代码版本、配置、数据快照、特征 schema、checkpoint 和评估报告。线上预测日志记录模型版本,才能在故障时回答“哪批请求受影响”“回滚到哪版”“这版模型由哪些数据训练”。
告警还需要动作:数据 freshness 超阈值时暂停更新,NaN 时保存触发 batch 并回滚,线上护栏恶化时停止放量。没有自动或人工响应路径的告警,只会形成无人处理的红点。
分布式训练运行数小时甚至数天,节点故障不是例外。一个能恢复的 checkpoint 不只是模型权重,而是一张“从哪里、以什么随机状态继续”的快照。
只保存权重往往不能继续同一条训练轨迹;可恢复检查点还要记录优化与数据处理的全部状态。
只保存模型权重可以用于推理,却不保证训练无缝继续。缺少优化器状态会丢掉动量;缺少调度器步数会让学习率回到错误阶段;缺少数据游标可能重复或跳过大量样本。
若各 rank 在不同训练步保存分片,把它们拼起来会得到从未真实存在过的模型。可以在一致的全局 step 建立保存屏障,让各 rank 写入带版本的临时目录;全部成功后再提交 manifest 或原子切换“latest”指针。失败的半成品不应被恢复程序选中。
checkpoint 必须定期做恢复演练。文件能写出不代表能读取,读取成功也不代表训练能继续。最小演练是:从 checkpoint 恢复,运行若干步,检查学习率、样本游标、参数变化和验证指标是否符合预期。
随机种子能控制一部分随机性,但不同硬件、框架版本、并行归约顺序和非确定性内核仍可能产生差异。浮点加法不满足结合律,改变 all-reduce 顺序就可能带来细小数值变化,之后被长训练放大。
开发与回归测试可以启用确定性算法、固定数据顺序和版本;生产追求最高吞吐时,允许受控的非确定性,但要用多次实验、容差和稳定的验证指标验收。确定性模式常会变慢,它是一种调试与审计选择,不是免费的开关。
规模化方案至少有三类延迟:训练作业完成时间、单个 step 延迟,以及在线模型从新数据到可服务的端到端新鲜度。把它们混在一起,会出现“step 更快,但模型发布更晚”的假优化。
可以建立如下验收表:
吞吐分母要排除 padding、重复补齐和失败重试造成的虚假工作量。语言模型若按“序列/秒”比较,短序列方案看起来会更快;使用有效 token/s 才更公平。
强扩展固定总任务,增加设备,看完成时间能缩短多少。它适合回答“这次训练能否从 12 小时降到 3 小时”。
弱扩展让每个设备工作量保持近似不变,设备增加时总工作量也增大,看系统能否维持吞吐。它适合回答“数据增长十倍后,集群能否近似线性承载”。
报告扩展结果时必须说明是哪一种。把数据量和设备数同时扩大,再宣称“速度线性提升”,并不能证明固定任务真的更快。
一台设备每小时便宜,但训练时间翻倍,可能消耗更多总费用,也拖慢实验迭代。反过来,昂贵高速互联只在通信确实是瓶颈时才值钱。成本模型还应包括失败重跑、空闲等待、存储、跨区网络和工程维护。
一个实用决策是画 Pareto 前沿:横轴为成本,纵轴为 time-to-quality,只保留“没有另一个方案同时更便宜又更快”的配置。再根据发布时限和预算选择,而不是迷信最大集群。
最后看一个端到端案例。某广告系统每天产生两亿次曝光,要预测点击与七日转化。当前单机训练需要 19 小时,模型每天发布一次,标签最晚七天成熟。团队希望把训练降到 4 小时,并让突发流量变化能在两小时内被发现,但不接受重复扣数、未成熟标签污染或故障后从头训练。
每次曝光生成唯一 prediction_id,记录用户与广告特征快照、位置、候选策略、模型版本和事件时间。点击通过同一 ID 回连;转化保留发生时间与回传时间。训练表不把“尚未回传转化”直接写成负例,而是按七日成熟窗口生成稳定标签。
离线评估采用按时间切分:较早窗口训练,随后窗口验证,更晚且标签已成熟的窗口测试。固定回归集检查代码变化,滚动近期集观察漂移。总体 AUC 之外,还报告校准、PR-AUC、新广告、低频用户、地区与设备切片。
单机剖析发现 35% 时间在读取大量小文件,15% 在 Python 特征拼接,GPU 只有 48% 利用率。团队先把事件整理成较大分片,批量向量化特征、并行预取,使单卡训练降到 10 小时。开启 BF16 后验证指标保持在容差内,时间降到 7.5 小时。
此时 GPU 已持续繁忙,模型能放进单卡,才扩到 4 卡同步数据并行。本地 batch 为 512,全局 batch 为 2048。短跑实验显示线性放大学习率加 warmup 后,time-to-quality 为 2.6 小时;扩大到 8 卡虽然吞吐更高,但验证曲线按样本数落后,成本也上升,因此 4 卡成为日常配置。
数据作业按事件 ID 去重,检查 schema、到达延迟、缺失率和标签成熟曲线。任何关键列异常都会冻结新训练,不让坏数据自动发布模型。
四个训练 rank 使用同一全局 shuffle 种子按 rank 分片。每个 rank 只读自己的数据,梯度按全局有效样本数归约;日志记录样本吞吐、输入等待、通信占比、梯度范数和混合精度异常。
每 20 分钟在一致的全局 step 保存分片 checkpoint,包括模型、优化器、调度器、随机数与数据游标。全部分片写完后才提交 manifest,并每周自动做一次恢复演练。
训练结束后,固定集、近期集和关键切片必须同时通过。候选模型先走影子流量,再小比例发布;在线点击、成熟转化、校准、P95 延迟和错误率都有护栏。
这个案例里,真正有效的规模化不是从 1 卡扩到 8 卡,而是先把数据管线从 19 小时压到 7.5 小时,再用合适的 4 卡同步训练达到 2.6 小时,并补齐标签、监控、checkpoint 与回滚。机器数量只是结果之一;可验证、可恢复和可持续运行,才是大规模机器学习系统的完成条件。
在线输入漂移或标签先验变化触发调查,而不是直接改参数。若成熟标签也显示质量下降,再启动增量训练;更新时混入分层回放样本,避免只追随最近热点。
新版本使用不可变模型 ID 原子切换。护栏越界就回滚到上一版;prediction_id 与模型版本让团队能定位受影响流量并重建训练样本。