vLLM 启动 GGUF 模型踩坑记:从报错到 100% GPU 占用的原因解析

摘要: 本文记录了使用 vLLM 部署本地 GGUF 格式大模型的踩坑过程。从最初的路径格式错误,到参数解析问题,再到 NumPy 版本兼容性引发的 AttributeError,最终解决了启动问题。然而,启动后 GPU SM 占用率长时间 100%,这并非卡死,而是 vLLM 进行关键优化步骤(内存分析与 CUDA 图捕捉)的正常现象。最终成功启动服务并明确了 API Base URL。

背景: 想要使用强大的 vLLM 框架来部署一个本地的 GGUF 格式量化大模型(例如 all-hands_openhands-lm-32b-v0.1-Q4_K_M.gguf),并提供 OpenAI 风格的 API 服务。

环境: Conda 环境,vLLM 0.7.2,多 GPU(使用 tensor-parallel-size=2

踩坑一:GGUF 路径格式与 Repo ID 混淆

最初尝试使用模型所在的 目录 作为 vllm serve 的参数:

bash 复制代码
vllm serve /home/kent/_Project/hf_model/bartowski/all-hands_openhands-lm-32b-v0.1-GGUF \
    --host 0.0.0.0 --port 8000 \
    # ... 其他参数

报错:

复制代码
huggingface_hub.errors.HFValidationError: Repo id must be in the form 'repo_name' or 'namespace/repo_name': '/home/kent/_Project/hf_model/bartowski/all-hands_openhands-lm-32b-v0.1-GGUF'. Use `repo_type` argument if needed.

原因: vLLM 默认将 serve 后的第一个参数视为 Hugging Face Hub 的仓库 ID 或本地包含 config.json 等文件的模型目录。直接提供 GGUF 文件所在的目录路径不符合预期。

解决: 需要提供指向 .gguf 文件本身的完整路径

踩坑二:vllm serve 的参数解析 - model_tag 的要求

修正路径后,尝试使用 --model 参数指定 GGUF 文件:

bash 复制代码
vllm serve \
    --model /path/to/your_model.gguf \
    --host 0.0.0.0 --port 8000 \
    # ... 其他参数

报错:

复制代码
usage: vllm serve <model_tag> [options]
vllm serve: error: the following arguments are required: model_tag

原因: vLLM 的 serve 子命令强制要求一个位置参数 model_tag(即 serve 后面的第一个无 -- 前缀的参数)来指定模型。即使使用了 --model,这个位置参数也不能省略。

解决: 将 GGUF 文件的完整路径作为 serve 后面的第一个位置参数 ,并移除 --model 选项。

bash 复制代码
vllm serve \
    /home/kent/_Project/hf_model/bartowski/all-hands_openhands-lm-32b-v0.1-GGUF/all-hands_openhands-lm-32b-v0.1-Q4_K_M.gguf \
    --host 0.0.0.0 --port 8000 \
    # ... 其他参数

踩坑三:NumPy 版本兼容性问题

修正命令后再次运行,遇到新的报错:

复制代码
AttributeError: `newbyteorder` was removed from the ndarray class in NumPy 2.0. Use `arr.view(arr.dtype.newbyteorder(order))` instead.

原因: 环境中安装了 NumPy 2.0 或更高版本。而 vLLM 依赖的某个库(如 transformers 或其依赖 gguf-py)内部代码使用了 NumPy 1.x 版本中存在的 .newbyteorder() 方法,该方法在 NumPy 2.0 中已被移除。

解决: 降级 NumPy 版本到 2.0 之前。推荐使用一个稳定的 1.x 版本,如 1.26.4。

bash 复制代码
# 在激活的 Conda 环境中执行
pip install "numpy<2.0"
# 或者指定版本
# pip install numpy==1.26.4

踩坑四(解惑):启动后 GPU SM 长时间 100%

在解决了上述所有报错后,vllm serve 命令终于开始正常执行。模型权重成功加载,但观察 nvidia-sminvtop 发现 GPU 的 SM 占用率长时间维持在 100%,似乎服务卡住了。

原因: 这并非卡死,而是 vLLM 在进行必要的、但非常耗时的启动优化步骤。主要包括:

  1. 内存分析 (Memory Profiling):

    • 目的: 精确计算在当前 GPU 和配置下,除了模型权重外,有多少显存可以安全地分配给 KV Cache,以最大化吞吐量和并发数。
    • 表现: 在日志中可以看到类似 Memory profiling takes XXX.XX seconds 的信息。这个过程需要模拟计算,会长时间占用 GPU。在我们的案例中,这步耗时近 4 分钟。
    log 复制代码
    INFO 04-01 22:18:59 worker.py:267] Memory profiling takes 231.99 seconds
    INFO 04-01 22:18:59 worker.py:267] ... the rest of the memory reserved for KV Cache is 7.46GiB.
  2. CUDA 图捕捉 (Capturing Cudagraphs):

    • 目的: 将模型推理过程中的一系列 GPU 操作预先录制成一个"图"(Graph)。后续处理请求时,可以直接重放这个图,大幅减少 CPU 到 GPU 的调度开销,提升性能。
    • 表现: 日志中会出现 Capturing cudagraphs for decoding... 和一个进度条。这个过程同样需要实际运行推理,会长时间占用 GPU。在我们的案例中,这步耗时约 1 分 12 秒。
    log 复制代码
    INFO 04-01 22:19:02 model_runner.py:1434] Capturing cudagraphs for decoding...
    Capturing CUDA graph shapes: 100%|████████████| 35/35 [01:12<00:00,  2.07s/it]
    INFO 04-01 22:20:14 model_runner.py:1562] Graph capturing finished in 72 secs...

结论: 启动 vLLM 服务(尤其是对于大型模型、启用 Tensor Parallel 或 Prefix Caching 时)需要耐心等待。内存分析和 CUDA 图捕捉是正常的优化过程,期间 GPU 高负载是预期行为。

最终成功与 Base URL

当所有优化步骤完成后,日志会显示:

log 复制代码
INFO 04-01 22:20:14 llm_engine.py:431] init engine (...) took 307.74 seconds
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

这表明服务已成功启动,并监听在 8000 端口。

API Base URL:

  • 如果从服务器本机访问:http://127.0.0.1:8000
  • 如果从局域网其他机器访问:http://<服务器的IP地址>:8000

常用的 OpenAI 兼容端点(例如文本补全)的完整 URL 为:http://<服务器的IP地址>:8000/v1/completions

总结: 部署 vLLM GGUF 模型需要注意命令行参数的正确格式、检查依赖库(尤其是 NumPy)的版本兼容性,并理解启动过程中的优化步骤会导致暂时的 GPU 高负载。耐心等待后,即可获得高效的推理服务。


相关推荐
cg50175 小时前
Spring Boot 的配置文件
java·linux·spring boot
暮云星影6 小时前
三、FFmpeg学习笔记
linux·ffmpeg
rainFFrain6 小时前
单例模式与线程安全
linux·运维·服务器·vscode·单例模式
GalaxyPokemon6 小时前
Muduo网络库实现 [九] - EventLoopThread模块
linux·服务器·c++
mingqian_chu7 小时前
ubuntu中使用安卓模拟器
android·linux·ubuntu
GalaxyPokemon8 小时前
Muduo网络库实现 [十] - EventLoopThreadPool模块
linux·服务器·网络·c++
自由鬼8 小时前
开源虚拟化管理平台Proxmox VE部署超融合
linux·运维·服务器·开源·虚拟化·pve
瞌睡不来8 小时前
(学习总结32)Linux 基础 IO
linux·学习·io
inquisiter8 小时前
UEFI镜像结构布局
linux·spring