一、先分清“在忙”与“在算”
1.1 三个容易误判的现象
第一个现象是利用率数字很高,产出却不高。面板上显示的“占用”只说明算力部件被任务占着,并不说明这些部件在做有用的计算。等待数据、等待同步、等待保存,都可能让占用维持在很高的水平。
第二个现象是卡在跑,任务却不推进。任务进程活着、日志在滚,但每一步的耗时远高于预期,整体看起来像在原地打转。这种情况往往是某个环节拖住了整条链路,而不是算力本身出问题。
第三个现象是加卡不加速度。从单卡扩到多卡,从一台机器扩到多台机器,期待的是接近成倍的提速,实际拿到的可能只有小幅改善。差距就来自协同开销,它随着卡数增加而增长。
1.2 判断该按什么顺序
一个实用的顺序是:先确认数据供给是否跟得上,再确认单卡是否跑满,然后看在多卡场景下通信占了多少时间,最后才判断任务与规格是否匹配。这个顺序的价值在于,越靠前的问题越常见、越好改,而越靠后的判断越容易被误当成“算力不够”而直接去加卡。
二、三个需要先弄懂的名词
2.1 算力利用率
算力利用率描述的是在某段时间里,算力部件有多大比例处于工作状态。但它回答不了“工作得有没有用”。同样显示较高的利用率,一种情况是每一步都在实打实地计算,另一种情况是大部分时间在等数据搬进来。判断后者需要另一个指标:单位时间内处理完的样本数量。这个数字上不去,利用率再高也只是空转。
2.2 数据供给与预处理流水线
2.2.1 为什么读数据会成为瓶颈
模型每一步计算需要的样本,要先从存储里读出来、解码、做变换,再送到算力部件。这一步如果慢于计算速度,算力部件就只能等着。样本文件很碎、单个文件很小、解码步骤很重、读取只用一个通道,任何一种情况都会让这条供给线变成瓶颈。值得注意的是,这类等待在利用率上未必看得出来,它表现为“每一步都慢一点”,而不是“算力闲着”。
2.2.2 三个见效较快的做法
①把零散的小文件合并成较大的连续文件,减少读取时的寻址开销;②把重复出现的解码与变换结果提前算好并缓存,避免每一步都重做;③让读取与计算并行推进,读取下一批的同时计算这一批,而不是串行地读完再算。
2.3 扩展效率
扩展效率是把卡数翻倍之后,实际得到的提速与理论提速之比。从一张卡加到两张,理论上应该快一倍,实际可能只有七成多;从八张加到十六张,比例通常还会再降。下降的部分没有消失,它变成了卡与卡之间交换数据的时间。这个比值是判断“该不该继续加卡”的关键依据,比单看总数直观得多。
三、损耗最常出现在四个地方
3.1 第一处:数据喂不饱
表现为每一步都停顿一下,或者算力占用呈锯齿状起伏。常见成因有三个:样本存放在读取带宽有限的路径上;预处理开了很少的并行通道,解码成为串行瓶颈;批的大小设得太小,每批的数据搬运开销摊不薄。
改进方向也很直接:把训练数据放到读取更快的存储位置,靠近计算;适当增大批的大小,让每次搬运摊到更多样本上;把预处理拆成并行的多个通道。这三件事都不需要额外算力,却常常能带来最明显的改善。
3.2 第二处:单卡没跑满
有些任务的耗时不在计算上,而在计算的间隙里。检查点保存过于频繁、每一步都写大量日志、每一步都把结果同步回主机侧,这些动作会把时间切得很碎。还有一种容易被忽略的情况:模型或数据精度设置与算力规格不匹配,本该更高效的路径没有走通,白白多花时间。
处理这类问题的思路是“先看单卡能跑多快”。先用一份数据、一张卡跑出基准速度,再逐步加上各种功能,看是哪一项让速度掉下来。基准速度是后续一切判断的参照,没有它,多卡阶段的任何异常都无从比较。
3.3 第三处:多卡协同开销
多卡并行时,卡与卡之间要不断交换梯度或中间结果。交换量随模型规模增长,而交换速度受节点内部互联与节点之间网络的双重限制。当交换时间接近甚至超过计算时间,加卡就失去了意义。
这一处最容易被误判。团队看到进度慢,第一反应是再加几张卡,结果协同开销同步上涨,整体反而更慢。稳妥的做法是先在小规模上测扩展效率,比如从一张到四张、从四张到八张各测一次,看比值掉到什么程度,再决定是继续扩,还是改用别的并行方式。
3.4 第四处:任务与规格不匹配
规格与任务不匹配有三种典型形态:一是小模型占着大规格的算力,计算很快结束,剩下的时间都在等数据与通信;二是需要大显存的任务被塞进显存偏紧的规格,只能靠频繁换入换出勉强跑起来;三是把一件本可以批量完成的事拆成许多小任务逐个提交,每次都重新加载环境与模型。
判断方法不复杂:看任务吃的是什么。吃显存的,优先看能不能装下;吃计算的,优先看单卡速度;吃协同的,优先看互联条件;吃数据吞吐的,优先看存储位置。四类需求对应的规格侧重点不同,按最主要的那个来选,比面面俱到更有效。
四、天翼云息壤平台GPU算力如何减少这些损耗
4.1 让数据靠近计算
平台提供面向训练场景的存储选择,可以把数据集放在读取更快的存储上,并与计算资源就近部署,减少长距离搬运。对于反复使用的公共数据集,缓存机制能避免每次任务都从远端重新拉取。这一项直接影响前面说的第一处损耗。
4.2 规格与任务对得上号
平台提供多种规格的算力,在显存容量、计算能力、卡间互联条件上各有侧重。按任务的主要需求挑规格,是减少第四处损耗最直接的办法。同一份任务在匹配的规格上跑,往往不需要额外优化就能拿到更好的单位时间产出。
4.3 环境预置,少一段隐性等待
环境准备本身也是损耗的一部分。依赖装不上、版本冲突、编译耗时长,这些时间不会体现在算力面板上,却实实在在拖慢项目。平台预置了常见训练框架与依赖环境,也支持把调试好的环境保存为自定义镜像反复使用,团队里第二个人启动任务时不必从头再来。
4.4 把“在忙”拆成“在算”和“在等”
平台提供的观测信息里,除了算力占用,还包括任务运行状态、存储读取情况与资源使用记录。把这几项放在一起看,才能区分算力是在计算还是在等待。当等待占比明显偏高时,改进方向自然指向数据与协同,而不是继续加卡。
4.5 中断之后不必从头再来
长任务跑到中途被中断,重跑一次等于把前面用掉的算力全部作废。平台支持检查点保存与续训,任务恢复后从最近的检查点接着跑,把意外中断带来的损失控制在一个可接受的范围内。对动辄需要跑上数天的训练任务来说,这一项的实际价值往往超过再添几张卡。
天翼云在智算方向的持续建设也获得过公开认可,包括央企十大超级工程、算力中国·年度突破成果、十大硬核科技、世界互联网大会杰出贡献奖等评价,相关表述可通过官网与官方渠道查询。对使用者而言,这些信息的参考意义在于平台的资源规模与运营经验经过了较长时间的检验,遇到规格与调度上的具体问题时,更容易找到有实践依据的建议。
五、四条可以直接照做的自查建议
1、把每秒处理的样本数量记下来,而不是只盯利用率。这个数字是判断算力有没有用起来的唯一硬指标,也是比较不同配置、不同优化手段的唯一基准。
2、先用一张卡跑出基准速度,再谈多卡。单卡都没跑满,加卡只会把同一个瓶颈复制若干份,问题从“慢”变成“更贵地慢”。
3、扩卡之前先测扩展效率。从一张到四张、四张到八张各测一次,看实际提速与理论提速的差距。差距过大,说明该改并行方式或通信路径,而不是继续加卡。
4、把预处理从主流程里挪出去。让读取与计算同时进行,并提前把可复用的中间结果算好。这一步往往是同等算力下提升最明显的改动,而且不需要额外资源。
回到开头那个别扭的感受:息壤平台GPU算力已经开起来,卡一直在忙,进度却不动。它提示的不是算力不足,而是有效计算的比例偏低。四处损耗里,前三处都能在不增加资源的前提下改善,第四处则可以通过换一个更匹配的规格来解决。把这几件事按顺序做完,再看算力够不够,得到的结论会比一开始就申请扩容可靠得多。