上周帮我爸整理他那间堆了二十年杂物的朝北小储物间,翻到个用透明胶带缠了三圈的移动硬盘,外壳磨得发白,上面用马克笔歪歪扭扭写了”2019 训练稿”。
压在工具箱最下层的硬盘
我本来以为是他当年给小区做门禁系统存的旧代码,插电脑才发现,全是我那时候跑模型留下的碎文件。有当时写的乱七八糟的Python脚本,有训练到一半崩了的模型 checkpoint,还有几张拍得模糊的照片,是我跟我爸蹲在机箱旁边,风扇吹得我头发全贴在脑门上,桌上放着半瓶喝剩的冰红茶。

2019年那会我刚毕业,没多少钱,租在他储物间隔出来的八平米小隔间里,想做个能识别小区流浪猫的图像模型。本来攒了三个月的钱准备买张新显卡,结果被冒充租房中介的骗子骗走了大半,只剩我爸从单位淘汰的工作站里拆出来的两张Tesla P40,每张24G显存。
跑不动。
单卡塞不下整个7B参数的小模型,一加载就爆显存,报错的红字跳满整个屏幕,我坐在小板凳上盯着屏幕发愣,连哭的劲都没有。那时候我爸天天蹲在我旁边看我折腾,他搞了一辈子工业控制,见多了这种单设备扛不住活的场面,敲了敲机箱说,你别把所有东西都塞一张卡上啊。
拆模型的那个夏夜
那是我第一次接触最朴素的模型并行逻辑。说白了就是把完整的模型拆成互不重叠的块,每张卡只负责计算自己对应的部分,算完了把中间结果传给下一块,最后拼出完整的输出。我们那时候根本没听过什么专业的分布式框架,就是凭着工业控制里学来的并行思路,自己写了几十行Python脚本,把模型的前12层放第一张卡,后12层放第二张卡,还专门加了个通信缓存区,怕两张卡计算速度不一样,出现等待卡顿。

那年夏天隔间里没有空调,只有个落地扇对着机箱吹,风把桌上的草稿纸吹得哗哗响。我穿个洗得发白的大裤衩,脚边堆了半箱矿泉水,调参数的时候手都抖——怕拆错了层,两张卡之间传数据的时候断连,又得从头等十几个小时。
有次调流水线并行的参数,跑了整整八个小时,眼看就要出第一版训练结果了,突然报了个通信超时的错误,进度条直接跳回零。我当时气得直接把鼠标砸在桌上,橡胶垫都被砸出个印子,差点把机箱踹翻。我爸从外面拎了两根冰棒进来,递了一根给我,说急啥,当年我们搞机床改造,拆了十几台报废机器的零件凑成一台能用的,哪有一次就成的。
那天我们蹲在地上啃冰棒,对着报错的日志找了两个小时的原因,最后发现是我写的缓存区大小设错了,留的空间太小,中间数据传一半就塞不下了。改完参数重新启动训练的时候,窗外的天已经蒙蒙亮了,机箱的风扇转得嗡嗡响,桌上的纸杯都被风吹得晃,我靠在墙上打哈欠,连外卖都忘了拿。
再也没打开过的旧脚本
过了半年,我终于攒够了钱买了新的显卡,单卡24G,能塞下整个7B模型,再也不用把模型拆成两半塞在两张旧卡上。那套写得乱七八糟的并行脚本,就被我存在那个缠了透明胶带的旧硬盘里,再也没打开过。
去年我去参加一个行业会,台上的工程师在讲现在的大模型训练集群,几百张高端显卡排成一排,用复杂的张量并行、流水线并行、专家并行逻辑,撑起几千亿参数的模型。台下坐满了穿正装的从业者,记笔记的笔唰唰响,我坐在最后一排,突然就想起当年在八平米的隔间里,跟我爸两个人对着两张从报废工作站拆下来的旧显卡,蹲在地上调脚本的那个晚上。
散场的时候我给我爸打了个电话,问他记不记得当年我们凑的那台老机器。他在电话那头笑,说咋不记得,你那时候砸了个鼠标,赔了我三十块钱,到现在还没给呢。
我挂了电话,把那个旧硬盘里的文件导出来,翻到当年写的并行脚本,注释里还歪歪扭扭写了几句吐槽:今天又崩了,明天再也不跑了。脚本的最后还有几行铅笔写的草稿,是我爸的字:拆成两块试试。
我后来试着把那套旧脚本改了两行参数,在现在的新机器上跑了一遍,居然还能通。窗外的梧桐叶被风吹得晃,我突然想起当年那个没有空调的夏夜,风扇嗡嗡转着,两张旧显卡在机箱里发热,像两个拼尽全力的人。
没人知道那套写得乱七八糟的脚本后来有没有用,就像没人知道那些被拆成碎块的参数,最终会拼成什么样的模型。
作者|大讲堂
排版|大讲堂
审核|知知
大讲堂