Linux深度学习环境搭建:16年工程师的排错实战路径
|
跟老板拍桌子。不是为预算,是为他让我在周五下午三点、GPU 卡还没到货前,把训练 pipeline 推进 CI 流水线。我说“你让流水线跑一个不存在的 CUDA 版本”,他点头说“先 mock 掉 driver 检查”。我原以为他真懂 mock——结果他让前端同事写了段 JSON Schema 验证逻辑,用正则去 match nvidia-smi 的 stderr。那会儿桌面那个没关的录屏还在录,红点闪着,我也没关,就看着它闪。 优胜劣汰不是修辞。是血洗。昨天凌晨两点改完 PyTorch 编译参数,发现 /usr/local/cuda 是个 symlink 到 cuda-12.4.0,而 nvcc -V 输出的是 12.3.1——但 ldconfig -p | grep cudnn 居然能搜出三十七个变体,其中两个路径拼写里有波浪号(~),一个是 ~jenkins/.local/cuda/…,另一个是 /home/jenkins/~/cudnn/lib。我敢打包票:那个波浪号是某次 scp -r 时 shell 展开失败留下的残骸,不是符号链接,是字面量字符串。没人动过它,三年了,就挂在 ld.so.cache 里,像块结石。
文章配图,仅供参考 Lighthouse 跑分截图发到群里没人回。PM 在问“数据增强的 batch 内一致性是不是该加个开关”,后端在贴 Grafana 查询语句,而我刚把 conda-forge 的 pytorch-nightly 换成 source build,因为 pip install torch==2.4.0+cu124 —no-deps 装完跑 model.cuda() 就 segfault,但 strace 显示它其实成功 mmap 了显存,只是 _cuda_init 后立刻 abort。abort 前调用了两次 clock_gettime(CLOCK_MONOTONIC),这个我敢打包票——gdb tui 里断在 libc 的 __pthread_clockjoin_ex 上,栈顶指针偏移是 0x7f8a1c3b2e90,和上个月我在另一台机器上看到的一模一样。你说巧不巧?我删过七次 /etc/ld.so.conf.d/nvidia.conf。不是因为不会写,是因为每次写完都得等三分钟——systemd-binfmt 自动 reload,但 journald 正好卡在 buffer flush,log 里只显示 “binfmt: register ‘py’” 然后断掉。你去查 journalctl -u systemd-binfmt --since “2026-07-08 15:02:13”,能看到一行 timestamp 对不上,差整整十八毫秒。这个我说不准是不是 TZ 设置问题,但我知道上周四下午三点,运维同事换了一根 USB-C 充电线,Type-C 头带 E-Marker 芯片那种,之后 binfmt 重载延迟就开始固定在十八毫秒。他换线时我在倒水,纸杯捏扁了,水洒在键盘右下角,Alt 键粘了两天。 CUDA_VISIBLE_DEVICES=0,1,2,3,但 nvidia-smi 显示只有 GPU 0、1、3 在 use;GPU 2 一直 stuck 在 “Compute M.”,风扇转速恒定 2100 RPM,不升不降。我试过 nvidia-smi --gpu-reset -i 2,返回 Success,但状态不变;试过 modprobe -r nvidia_uvm && modprobe nvidia_uvm,它直接拒绝卸载——说 “module nvidia_uvm is in use by: nvidia_drm”。可 nvidia-drm.ko 根本没加载,lsmod | grep drm 是空的。最后发现是 BIOS 里 “Above 4G Decoding” 和 “Resizable BAR” 两个开关冲突,开了 Resizable BAR,Above 4G 必须关,否则 PCIe 地址映射乱掉,GPU 2 的 BAR 0 被映射到了 0x1ffff00000,超出了内核允许范围。这个事没文档,英伟达官网 FAQ 第八页底下一个脚注写着 “某些 OEM 平台可能存在地址对齐异常”,没提哪几个 OEM,没提哪几款主板。我查了三个月主板型号手册,全是英文,“alignment” 这个词出现了十七次,一次都没带单位。 CDN 账单的事也顺嘴说一句:上季度我们静态资源走的 Cloudflare Workers,按请求计费,结果某天突然峰值跳高三十倍,排查发现是 PyPI index 页面嵌了个 ,而这个 js 文件的 Cache-Control 是 max-age=300,但 CF 缓存 TTL 给设成了 86400 秒,导致 workers 每次都绕过缓存重取——不是 bug,是我们自己写的规则里写了 “if (url.path.startsWith(‘/static/’)) cacheTtl = 86400”。这个锅算谁的?算我的,因为我 review 了 PR,没看到这行。但我现在看见任何以 /static/ 开头的 URL 都手抖。 PyTorch 的 TORCH_CUDA_ARCH_LIST 我现在只敢设成 “8.0;8.6”,连 9.0 都不敢加,哪怕卡是 H100。因为试过一次,build 完 import torch 就 core dump,gdb 里看 backtrace 最后一帧是 at::native::cudnn_convolution_backward_input,再往上是 libtorch_cpu.so 里的函数,名字我都记不住。但这事儿不能怪 PyTorch,它编译日志里清清楚楚写着 “skipping SM90 due to missing CUTLASS backend”,我漏看了。漏看就漏看,可第二天晨会 PM 说“客户要求支持 FP8 inference”,我就知道这事得重来一遍。反正我已经把 conda env export > environment.yml 的输出删了三回,每次删完都发现 requirements.txt 里还藏着一行 pip install git+https://github.com/pytorch/audio@main#subdirectory=torchaudio —no-deps,这个 subdirectory 字段会破坏 wheel 缓存一致性,你知道吧?不知道就算了。 我现在装环境,第一步不是装驱动,是先 ls -la /dev/nvidia,然后 cat /proc/driver/nvidia/parameters | grep -E "(EnableMIG|NVSwitch)"; 如果出来东西,立马停手。上次一个同事在 A100 上开了 MIG,分区后没清 /run/nvidia-persistenced/socket,结果 persistenced 启动时绑定失败,整个 cudaMalloc 都卡在 mutex 上,strace 里全是 futex(WAIT_PRIVATE),但 top 里看不到任何进程占用 CPU。这事儿查了十六小时,最后是他去倒水时无意间碰了机箱重启按钮——机箱按钮坏了,短接了两秒,系统硬重启,MIG 分区全崩,反而好了。我那天没喝到水,就记得他纸杯里茶叶沉底,颜色像陈年机油。 不折腾了。今天下班前我把 /usr/local/cuda 下所有 cuda- 目录 ln -sf 的 target 全打了个 sha256sum,存了个 backup.csv,连修改时间都存了。下次再有人问我“环境怎么搭最稳”,我就发他 CSV。不是懒得教,是教不完——稳的从来不是步骤,是某次你手抖 rm -rf /tmp/.torch_extensions 之前,刚好看了眼 df -h,发现 /tmp 所在的 LVM VG 用了 93%,而 /var/log/journal 占了其中四百七十二 KB。这点空间,够你多活一轮。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


深度学习服务器选型避坑与全栈调优实战
云端部署深度学习模型:网络延迟直降67%实战
嵌入式Linux开发者Unix环境搭建避坑指南
Linux安全环境搭建:从零到生产就绪
Windows站点环境搭建的3个致命安全断点
Linux运维老手也常踩的5个Unix环境搭建坑
Windows数据科学环境搭建:7年用户访谈总结的避坑与高效配置