4.3 训练与推理的"踩坑实录":把真实故障变成可复用经验 第四章前两节给了训练任务沙箱化(4.1)和推理服务沙箱化(4.2)的范式。这一节把现场里最容易让人熬夜的八类故障,写成"踩坑实录"——每条都是"现象 → 我当时怎么想错 → 正确归因 → 药方"。我刻意保留"想错"的过程,因为踩坑的价值不在结论,而在避免重蹈同样的思维盲区。 实录一:多卡训练卡死,日志只有一行 bus error 现象:4 卡 启动后,进程互相等待,十几分钟不动,日志偶尔冒出 或 NCCL 超时。 我当时想错:以为是网络不通,去查 ,折腾了半天。 正确归因: 默认只有 64MB,多卡 NCCL 通信用共享内存做握手,空间不够直接崩。这是多卡训练的经典坑,和"外网"毫无关系。 药方:启动加 或 ,把共享内存放大。
第四章前两节给了训练任务沙箱化(4.1)和推理服务沙箱化(4.2)的范式。这一节把现场里最容易让人熬夜的八类故障,写成"踩坑实录"——每条都是"现象 → 我当时怎么想错 → 正确归因 → 药方"。我刻意保留"想错"的过程,因为踩坑的价值不在结论,而在避免重蹈同样的思维盲区。
现象:4 卡 torchrun 启动后,进程互相等待,十几分钟不动,日志偶尔冒出 bus error 或 NCCL 超时。
我当时想错:以为是网络不通,去查 --network,折腾了半天。
正确归因:/dev/shm 默认只有 64MB,多卡 NCCL 通信用共享内存做握手,空间不够直接崩。这是多卡训练的经典坑,和"外网"毫无关系。
药方:启动加 --shm-size=16g 或 --ipc=host,把共享内存放大。记住这条:凡多卡,先把 shm 调大,能省下无数排查时间。
现象:好不容易训到一半,宿主机重启,容器没了,checkpoint 也没了。
我当时想错:以为容器里的 /models 目录是"安全的"。
正确归因:权重写进了容器可写层,没挂 volume。容器一删,可写层随之消失。4.1 节强调过——checkpoint 必须落在挂载卷。
药方:用 -v /data/ckpt:/workspace/ckpt 把检查点目录挂到宿主机;训练脚本的 --output_dir 指向该挂载路径。最好再加一层定时上传到对象存储,防磁盘故障。
现象:4.2 起的推理容器,QPS 不高,但 resident 内存每天涨一点,三天后 OOM 被 kill。
我当时想错:怀疑是框架 bug,准备降版本。
正确归因:请求里带了大体积输入(长文档/大图),框架层没有并发上限和批处理上限,请求在队列里堆积、张量未及时释放。容器层面没限制,于是无节制增长。
药方:在框架层设最大并发/最大批处理上限,并对单请求输入大小做裁剪;容器层面用 --memory 兜底,避免拖垮宿主机。把"吞吐"和"隔离"同时考虑,正是沙箱的价值。
现象:共用八卡机,对方 --gpus all 起训练,我的推理容器虽然只挂了一张卡,却莫名被 OOM 杀死。
我当时想错:以为"各跑各的容器"天然隔离。
正确归因:对方没切分设备,占满了整张卡;你的容器若也可见该卡(或 MPS 共享),就会互相踩。隔离不是自动的,见 1.4 疑问三与 3.2 隔离边界。
药方:给每个任务显式指定 device,或用 MIG 做硬件级切分,或 cgroup 限制显存。一句话——设备视图必须被显式规划,不能靠运气。
现象:容器映射了 8888,但本地浏览器访问超时。
我当时想错:以为端口映射写错了。
正确归因:Jupyter 默认只监听 127.0.0.1,容器外连不进来;而且很多时候忘了带 --ip=0.0.0.0 和 token 参数。
药方:启动 Jupyter 加 --ip=0.0.0.0 --allow-root --no-browser,并把 token 或密码在 4.2 提到的安全基线里管好,别裸奔在公网。
现象:换机器后报 no kernel image is available for CUDA。
我当时想错:以为是 PyTorch 装错了。
正确归因:基础镜像编译的 CUDA 架构(计算能力)不包含目标卡的架构。A100 是 9.0、4090 是 8.9,某些轮子只编了部分架构。以 NVIDIA 官方 CUDA GPUs 列表为准核对计算能力,不要以"都是新卡"想当然。
药方:选支持目标计算能力的框架 wheel 或自行编译;容器化的好处正是可以"按卡的算力档准备不同标签镜像",宿主机只保留一套驱动。
现象:两台机器 torchrun --rdzv 互相找不到,卡在初始化。
我当时想错:以为是代码问题。
正确归因:多机需要网络互通且 rendezvous 端点可达,而默认 bridge 网络下跨机地址解析复杂。
药方:多机训练优先用 --network=host 让容器直接用宿主网络,确保节点间端口可达;rendezvous 端点用稳定可达的地址。具体参数名随框架版本略有差异,以官方分布式训练文档为准。
现象:训练、推理、系统日志散落在不同容器、不同路径,出事时拼不出时间线。
我当时想错:觉得"能跑就行",没规划日志。
正确归因:没有统一的日志挂载与轮转策略,容器一删日志没了。
药方:所有容器把日志目录挂到统一宿主路径,配合 logrotate;关键事件(OOM、重启、checkpoint)单独落盘。可观测性是沙箱工程化的一部分,详见 4.2 的可观测小节。
这八条看似零散,内核只有一句:沙箱不是"跑通一次"的终点,而是"每一次都能被解释、被恢复、被复盘"的基建。设备要显式、数据要外挂、资源要设上限、日志要可追。把这些当成肌肉记忆,第四章才算真正落地。下一章我们收束为团队层面的标准化工程。