# Qwen3 GGUF 安装与调优手册 本文档只覆盖 `qwen3_gguf` 后端,目标机器为当前项目实测环境: - GPU: `Tesla T4 16GB` - CUDA: `12.8` - 模型: `DevQuasar/Qwen.Qwen3-Reranker-4B-GGUF` - 量化: `Q8_0` --- ## 1. 结论先看 当前这套代码里,GGUF 后端的主要瓶颈不是“显存没吃满”,而是 **llama.cpp 按 doc 顺序逐条打分**。因此最有效的优化策略是: - 让模型层尽可能全部 offload 到 GPU - 打开 `flash_attn` / `offload_kqv` - 把 `n_ctx / n_batch / n_ubatch` 调到一个对短标题重排更合适的高效点 本轮在当前机器上的推荐配置是: ```yaml qwen3_gguf: n_ctx: 512 n_batch: 512 n_ubatch: 512 n_gpu_layers: 999 n_threads: 2 n_threads_batch: 4 flash_attn: true offload_kqv: true infer_batch_size: 8 sort_by_doc_length: true length_sort_mode: "char" ``` 说明: - `n_gpu_layers: 999` 在 llama.cpp 中等价于“尽可能全部层都 offload” - 这台 T4 上,**即使全量 offload,当前模型也只占到约 `4.5 GiB` GPU 显存** - 所以“允许 8G 显存”并不会自动带来更高速度;这个模型/后端在当前工作负载下已经接近“该用到的权重都上 GPU 了” --- ## 2. 独立环境 `qwen3_gguf` 必须使用自己的独立 venv: - `qwen3_vllm` -> `.venv-reranker` - `qwen3_gguf` -> `.venv-reranker-gguf` 安装命令: ```bash ./scripts/setup_reranker_venv.sh qwen3_gguf ``` 脚本现在会自动做两件事: 1. 安装 GGUF 后端所需 Python 依赖 2. 在检测到 `/usr/local/cuda/bin/nvcc` 时,把 `llama-cpp-python` **重编译成 CUDA 版** --- ## 3. GPU 版验证 必须验证不是 CPU-only 版: ```bash ./.venv-reranker-gguf/bin/python - <<'PY' import llama_cpp print("supports_gpu_offload =", llama_cpp.llama_supports_gpu_offload()) PY ``` 正确结果应为: ```text supports_gpu_offload = True ``` 还可以看动态库: ```bash ldd .venv-reranker-gguf/lib/python3.12/site-packages/llama_cpp/lib/libllama.so | rg 'cuda|cublas|ggml-cuda' ``` 应能看到: - `libggml-cuda.so` - `libcudart.so` - `libcublas.so` --- ## 4. 模型下载 当前使用本地文件优先策略,模型放在: ```text models/reranker/qwen3-reranker-4b-gguf/Qwen.Qwen3-Reranker-4B.Q8_0.gguf ``` 若本地文件存在,后端会直接加载本地 GGUF,不再依赖启动时在线下载。 为了避免当前机器上 Hugging Face Xet 下载的 `416 Range Not Satisfiable` 问题,`start_reranker.sh` 已对 `qwen3_gguf` 默认设置: ```bash HF_HUB_DISABLE_XET=1 ``` --- ## 5. 本地调优脚本 新增本地基准脚本: ```bash PYTHONPATH=/data/saas-search ./.venv-reranker-gguf/bin/python \ scripts/benchmark_reranker_gguf_local.py --docs 64 --repeat 1 ``` 它会直接实例化 GGUF backend,输出: - 模型加载耗时 - 当前进程 GPU 显存占用 - 单次 rerank 延迟 --- ## 6. 本轮实测结果 测试条件: - Query: `白色oversized T-shirt` - Docs: `64` 条商品标题 - 本地脚本:`scripts/benchmark_reranker_gguf_local.py` - 每组 1 次,重点比较相对趋势 结果: ### 6.1 保守配置 ```text n_ctx=384 n_batch=384 n_ubatch=128 n_gpu_layers=24 ``` - GPU 显存:`2984 MiB` - 64 docs 延迟:`74347.91 ms` ### 6.2 全量 offload ```text n_ctx=384 n_batch=384 n_ubatch=128 n_gpu_layers=999 ``` - GPU 显存:`4338 MiB` - 64 docs 延迟:`51401.77 ms` ### 6.3 最优配置 ```text n_ctx=512 n_batch=512 n_ubatch=512 n_gpu_layers=999 ``` - GPU 显存:`4564 MiB` - 64 docs 延迟:`49116.10 ms` ### 6.4 其它尝试 `n_threads=4 / n_threads_batch=8`: - GPU 显存:`4564 MiB` - 64 docs 延迟:`49895.88 ms` - 比推荐值略慢 `infer_batch_size=64`: - GPU 显存:`4564 MiB` - 64 docs 延迟:`50723.36 ms` - 也略慢 ### 6.5 API 级验证 在把推荐配置写入 `config/config.yaml` 并重启服务后,使用: ```bash RERANK_BASE=http://127.0.0.1:6007 \ ./.venv/bin/python scripts/benchmark_reranker_random_titles.py 64 --repeat 1 --query '白色oversized T-shirt' ``` 得到: - `64 docs`:`50177.22 ms` 再用: ```bash RERANK_BASE=http://127.0.0.1:6007 \ ./.venv/bin/python scripts/benchmark_reranker_random_titles.py 153 --repeat 1 --query '白色oversized T-shirt' ``` 得到: - `153 docs`:`115328.60 ms` 对比旧日志中的保守配置: - 旧配置 `153 docs`:`153435.37 ms` - 新配置 `153 docs`:`115328.60 ms` 改善幅度约: - `24.8%` --- ## 7. 为什么没有吃到 8G 结论很重要: - 当前最优配置已经是“尽可能全量层 offload” - 该 `Q8_0` 模型在这套 llama.cpp / T4 / 短文本重排场景下,**实测只需要约 `4.5 GiB` GPU 显存** - 继续为了“吃满 8G”去增大 `n_ctx`,不会明显提升吞吐,反而可能带来额外开销 所以本轮不是“显存太保守”,而是: - 可 offload 的权重已经基本 offload 完了 - 真正拖慢响应的是 **逐 doc 顺序推理** 这一后端实现路径 --- ## 8. 生产建议 ### 8.1 当前建议 保留以下参数: ```yaml n_ctx: 512 n_batch: 512 n_ubatch: 512 n_gpu_layers: 999 n_threads: 2 n_threads_batch: 4 flash_attn: true offload_kqv: true ``` ### 8.2 如果还嫌慢 优先级建议: 1. 缩小 `rerank_window` 2. 减少传入 doc 数 3. 若业务允许,切换到更适合高吞吐的后端 原因: - 当前 GGUF 后端是本地单进程、逐 doc 打分 - 对长列表重排,它天然不如 vLLM / 云端 rerank API 擅长吞吐 --- ## 9. 本轮落地文件 - `config/config.yaml` - `scripts/setup_reranker_venv.sh` - `scripts/start_reranker.sh` - `scripts/benchmark_reranker_gguf_local.py` - `reranker/GGUF_INSTALL_AND_TUNING.md`