夜里十一点,机房的风扇声是恒定的。监控面板上,一个训练任务卡在近似水平的损失曲线上,加速卡的利用率读数接近打满,进度条却迟迟不动。值班的人盯了一会儿,判断问题不在计算本身,而在等待——等另一张卡把梯度同步过来。
这类场景在集群规模变大之后越来越常见。谈「算力」时,人们习惯把它当成一个可以不断加码的数字,仿佛只要总量够大,任务就会按时完成。实际跑起来,这个数字只是起点。
一个被省略的分母
算力通常被表述为单位时间内可完成的浮点运算次数。这个定义本身没错,但它描述的是理想状态下芯片持续满载的能力。真实任务里,数据要先从存储读进内存,再从显存搬到片上缓存,计算完成的结果还要写回去。每一段搬运都要花时间,而且常常比计算本身更慢。
所以标称相同的硬件,跑不同规模的模型,表现会差出很远。模型小、批量小的时候,搬运和调度的开销占比高;模型大到一定程度,通信又成了新的天花板。
集群越大,等待越长
分布式训练并不是把任务切碎分给更多卡就完事。每一轮迭代结束,各张卡都要把各自算出的梯度汇总,再广播回去,参数才能继续更新。这个同步动作的频率随迭代次数增长,它的耗时随参与设备数量上升。设备越多,某一张卡偶发的延迟就越容易拖住整轮。
于是就出现一种落差:账面算力翻了几倍,实际吞吐只涨了一小截。多出来的部分没有消失,只是变成了排队和等待。工程上常见的做法是把通信和计算重叠起来,或者减少同步的频次,但这些手段都有代价,可调的空间也有限。
推理是另一种账
训练追求吞吐,推理追求响应。一个对话请求进来,用户等的是几百毫秒内的第一句话,而不是一秒钟处理几千条。这时候单卡的能力、显存的余量、批次的拼法,都比总量更能决定体验。把训练集群的思路直接搬到线上服务,经常得到一个昂贵、延迟不稳的系统。
反过来看,不少业务并不需要动用大集群。把模型压缩、把请求合并、把缓存做对,收益可能比申请更多卡来得直接。这不是否定规模的价值,而是提醒:规模解决的是特定类型的问题。
边界在哪里
当讨论从「要不要更多算力」转向「瓶颈在哪里」,问题就变得具体了。是带宽不够、显存不够、同步开销太大,还是任务本身并行度就低?不同答案对应完全不同的投入方向。买卡是最容易想到的一种,也常被当成唯一一种。
回到那个深夜的机房。真正让进度条重新走起来的,未必是再插上一排设备,而是有人发现某段数据加载没有预取,或者某个同步点可以延后几轮。这些改动手工、琐碎,写不进容量规划里,但它们确实在决定一块芯片有多少时间真正在算。