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 高负载。耐心等待后,即可获得高效的推理服务。


相关推荐
光而不耀@lgy41 分钟前
C++初登门槛
linux·开发语言·网络·c++·后端
偶尔微微一笑1 小时前
AI网络渗透kali应用(gptshell)
linux·人工智能·python·自然语言处理·编辑器
Run1.1 小时前
深入解析 Linux 中动静态库的加载机制:从原理到实践
linux·运维·服务器
The Mr.Nobody1 小时前
STM32MPU开发之旅:从零开始构建嵌入式Linux镜像
linux·stm32·嵌入式硬件
老兵发新帖2 小时前
Ubuntu 上安装 Conda
linux·ubuntu·conda
秋秋秋秋秋雨2 小时前
linux安装单节点Elasticsearch(es),安装可视化工具kibana
linux·elasticsearch·jenkins
码农hbk2 小时前
linux ptrace 图文详解(七) gdb、strace跟踪系统调用
linux·服务器
hotlinhao3 小时前
ThinkPHP6模型中多组条件逻辑或Or查询的使用
linux·服务器·数据库
Jogging-Snail3 小时前
从零开始掌握Linux数据流:管道与重定向完全指南
linux·运维·管道·重定向·linux 数据流·管道原理
niuTaylor3 小时前
Linux驱动开发快速上手指南:从理论到实战
linux·运维·开发语言·驱动开发·c#