1
DCU技术达人
新人贴
两百个感叹号:我在 DCU 上部署 DeepSeek 的一晚
2026-09-06 22:14:13
140
晚上十一点,服务起来了。加载成功、接口 200、token 计数正常,监控面板干干净净——然后我打开返回结果,看见 `content` 字段里整整齐齐排着 **200 个 `!`**。 那一晚的故事就是从这个画面开始的。目标是把 DeepSeek-R1-Distill-Qwen-32B 部署到海光 DCU 上,我原以为最难的部分是显存,最后发现最难的是「一切看起来都正常」。 ## 开局:省卡的美好愿望 最初选的是社区 GPTQ int4 量化版:权重从 65GB 压到 19GB,单张 K100_AI(64GB HBM)就装得下,这个算盘本身没毛病,后来证明错在我低估了量化 kernel 在新平台上的适配深度。 ## 第一折:主机环境,链接器的两个名字 主机 conda 环境(vLLM 0.11.0 + DTK 26.04)启动即崩: ``` RuntimeError: PassManager::run failed (栈顶在 _initialize_kv_caches → determine_available_memory) ``` 顺着栈读进 triton 源码,崩在 HCU 后端给 kernel 做 JIT 链接的阶段,再往下挖出一出三幕剧: 第一幕,triton 里硬编码找 `/opt/rocm/llvm/bin/ld.lld`——ROCm 的安装约定,而 DTK 装在 `/opt/dtk-26.04/`,`/opt/rocm` 根本不存在。好办,环境变量 `TRITON_HIP_LLD_PATH` 能覆盖。 第二幕,我指到 `/opt/dtk-26.04/llvm/bin/lld`,路径反复核对无误——还是崩。盯着文件名看久了才发现门道:`lld` 是 LLVM 的通用驱动,它按「自己被以什么名字调用」决定行为;叫 `ld.lld` 才以 GNU 链接器语义工作。DTK 目录里两个名字指向同一个文件,选错名字等于选错了它的人格。 第三幕: ```bash export TRITON_HIP_LLD_PATH=/opt/dtk-26.04/llvm/bin/ld.lld ``` 一个字符的差别,绕了我一整个傍晚。附带还搞明白一件事:TP=1 不崩、TP≥2 崩,是因为只有多卡分布式路径才触发这条 JIT 链接——**国产卡上「单卡能跑多卡崩」未必是显存问题**。 修好之后主机环境又冒出新的幺蛾子(`/etc/profile.d/dtk.sh` 不存在、真实入口在 `/opt/dtk-26.04/env.sh`……)。为了切割变量,我切到官方 Docker 镜像(vLLM 0.6.2 + DTK 24.04.3)做保底方案。然后就有了开头那两百个感叹号。 ## 第二折:全绿的服务,垃圾的输出 这是整个晚上最别扭的一段:**没有任何报错可供顺藤摸瓜,只有「输出错了」这一个事实**。能怀疑的方向就三个:chat template 没套对、权重损坏、量化 kernel 有问题。我给每个嫌疑配了一个能一锤定音的实验: | 嫌疑 | 实验 | 结果 | |---|---|---| | R1 特殊 chat template 没生效 | 服务端收到的 prompt 与 `tokenizer.apply_chat_template` 渲染结果逐字节比对 | 一致 → 排除 | | 权重损坏 | 同一权重 × vLLM 0.11(主机)/0.6.2(Docker)× TP=1/TP=2 四组合全跑 | 全部输出 `!` → 排除 | | Marlin 量化 kernel 替换 | `--quantization gptq_marlin` | 0.6.2 强制 config 与 CLI 一致直接报错 → 此路不通 | 四组交叉全灭加上 template 无罪,结论自己收敛了:vLLM 的 GPTQ reference kernel 在 DCU/HIP 上反量化数值错误——权重、形状、调度全部正常,唯独数值层坏掉,logits 坍缩到某个固定 token 上无限重复。接口兼容做得再漂亮,数值正确性要一个 kernel 一个 kernel 对,这就是平台适配的深水区。 继续调 kernel 不现实,那是框架加厂商的工程量。换 BF16。 ## 第三折:BF16,四张卡,走了 BF16 原模型 65.4GB,ModelScope 下载 ~3MB/s 跑了 **1.7 小时**,中间还埋了个小雷:下载工具第二遍报「8/8 完成」正常退出,实际有一个分片缺了 15MB。此后我对断点续传的完成计数不再信任,验收一律 `stat` 每个文件的实际字节数和 `index.json` 的 `total_size` 对账。 ```bash vllm serve /models/DeepSeek-R1-Distill-Qwen-32B \ --tensor-parallel-size 4 --dtype bfloat16 \ --max-model-len 4096 --enforce-eager ``` 8 个分片 18.6 秒加载完,TP=4 每卡权重 15.41GB。中文对话正常,`finish_reason=stop`;再拿「1+1 等于几?只用数字回答」验证推理链——先输出一段思考再给出 \boxed{2},蒸馏进去的 reasoning 行为完整保留。凌晨的事到此收工。 顺手补几条当晚攒下的小坑:分片文件名是 `model-00008-of-000008.safetensors`(六个零),手拼 URL 数错零会 404;`docker exec 容器 ls /path/*.safetensors` 通配符不展开,要套一层 `sh -c`;容器里的旧进程用 `pkill -9` 才杀干净;另外 BF16 这条 vLLM 0.6.2 路径自带 ld.lld 且 V0 引擎不触发 JIT 链接,第一折那个坑在这条路上天然不存在——保底方案确实是真保底。 ## 这次留下来的三件事 1. **面对「全绿但输出错」,打排除法矩阵**:把嫌疑列全,每个配一个能一锤定音的实验(逐字节比对、多版本多并行度交叉),让结论自己收敛,不靠猜。 2. **量化是平台适配深水区**:接口兼容 ≠ 数值正确。选量化模型前先找「本平台验证过」的证据;找不到,默认 BF16 多卡。GPTQ int4 省下的三张卡,价值是零。 3. **单卡服务就算正确,也比不过「输出会说话」**——什么都能骗人,日志能骗人、监控能骗人,只有把模型的输出真正读一遍才踏实。 *当晚环境:海光 K100_AI × 8 / 主机 conda(vLLM 0.11.0 + DTK 26.04)与 Docker 官方镜像(pytorch:2.3.0-ubuntu22.04-dtk24.04.3-py3.10,vLLM 0.6.2)/ 最终配置:DeepSeek-R1-Distill-Qwen-32B BF16 TP=4。*
全部评论(0)
只看楼主
暂无数据
--
楼主
Level.1
0 帖子
楼主热帖
暂无数据