单卡 RTX 5090:Qwen3.8-27B NVFP4 在 vLLM 中实现真实 262K 上下文长度 — 短上下文速度达 77 tok/s,128K 上下文时为 64.7 tok/s

Reddit r/LocalLLaMA 新闻

摘要

本文展示了在NVIDIA RTX 5090显卡上使用vLLM框架运行Qwen3.8-27B模型的实际部署流程与性能基准测试,涵盖262K令牌上下文窗口的配置细节与各项关键指标。

这是我实际每天使用的 Qwen3.8-27B 配置,运行在单块 RTX 5090 上。我将其详细记录下来,以便其他 5090 用户能够复现,而无需猜测我使用了哪些内存参数。简而言之:完整的 262,144 个 token 窗口可与视觉功能、FP8 KV 缓存、前缀缓存、工具调用以及常规 KDE 桌面环境共同运行。在 1K 提示后,解码速度为 77.2 tok/s;当已有 128K 上下文时,解码速度为 64.7 tok/s。一次成功的 262,000 个 token 预填充耗时 166 秒。这并非声称 262K 速度很快;而是证明其确实能完整容纳并完成处理。模型:joshebbs/qwen3.8-27b-uncensored-nvfp4-modelopt,固定版本为 e5ff4986938dcd0dd05ab4cce89da1b052be6ce3。这是 JonathanColetti/Qwen3.8-27B-Uncensored 的 NVFP4 ModelOpt 导出版本。检查点为 19.18 GiB 的 safetensors 文件,保留了视觉塔和 MTP 头。模型采用 64 层混合架构:48 个门控 DeltaNet 层和 16 个全注意力层。 **结果** 所有运行均通过 `/v1/completions` 接口访问已预热的日常 vLLM 服务器,并发数为 1,使用随机 token 提示、`--ignore-eos` 参数以及温度 0。PP 指接受的输入 token 数除以 TTFT。TG 指 1000 / mean_TPOT_ms,因此不包括预填充时间。根据服务器计数器,非前缀运行的前缀缓存命中数为零。 | 工作负载 | 运行次数 | PP tok/s | TTFT | 稳态 TG tok/s | 端到端输出 tok/s | | :--- | :--- | :--- | :--- | :--- | :--- | | 8,192 输入 -> 1 输出 | 5 | 7,005 | 均值 1.169 s / 中位数 1.167 s | 不适用 | 不适用 | | 32,768 输入 -> 1 输出 | 3 | 6,148 | 均值 5.330 s / 中位数 5.332 s | 不适用 | 不适用 | | 131,072 输入 -> 256 输出 | 1 | 2,781 | 47.128 s | 64.7 | 5.01(因 47 秒预填充占主导) | | 262,000 输入 -> 1 输出 | 1 | 1,578 | 166.004 s | 不适用 | 不适用 | | 1,024 输入 -> 512 输出 | 5 | 不作为 PP 测试 | 均值 119.3 ms / 中位数 116.9 ms | 77.2 | 75.95 | 短上下文解码运行的平均 TPOT 为 12.959 ms,实测峰值输出速度为 78 tok/s。当上下文为 128K 常驻时,TPOT 上升至 15.463 ms,因此生成速度下降约 16.2%,至 64.7 tok/s。128K 和 262K 行仅为单次运行。将其视为实测操作点和适配检查,而非分布。8K、32K 和短上下文解码行为多次运行结果。随着上下文增长,PP 的下降幅度显著:这是一个混合模型,而非完全线性注意力模型。仍有十六层使用全注意力。 **前缀缓存** 使用一个共享的 36,864 个 token 前缀、一个 16 个 token 的唯一后缀、一个输出 token 和五个顺序请求进行的新测试: - 冷启动 TTFT:6.437 s - 四个缓存命中 TTFT:0.288、0.282、0.296、0.288 s - 缓存命中中位数:0.288 s - 冷启动到缓存加速比:22.3 倍 我启动器中的一条旧记录显示为 6.61 -> 0.20 s,即 33 倍。在此次新测试中,我无法重现 0.20 s 的数字,因此 22.3 倍是我今天会使用的数字。前缀缓存仍然是区分可用长代理对话与每轮重新预填充整个对话记录的关键。重要注意事项:启用前缀缓存时,vLLM 会将混合 Mamba/DeltaNet 缓存置于实验性对齐模式。如果看到输出损坏,禁用前缀缓存是我建议首先尝试的控制选项。 **硬件和软件** | 部分 | 精确实测设置 | | :--- | :--- | | GPU | NVIDIA GeForce RTX 5090,报告显存 32,607 MiB,功耗限制 600 W | | CPU | Intel Core i7-14700K,20 核 / 28 线程 | | RAM | 已安装 32 GiB,可见 31 GiB | | 操作系统 | Arch Linux,内核 7.1.8-arch1-3 | | 桌面 | KDE/Wayland,VRAM 快照期间开启了 Firefox 和终端 | | NVIDIA 驱动 | 610.57.04 (nvidia-open / nvidia-utils 610.57.04) | | CUDA 工具包 | Arch cuda 13.3.1-1,nvcc 13.3.73 | | Python | 3.13.13 | | vLLM | 0.27.1,发行版 wheel | | PyTorch | 2.13.0+cu130 | | Transformers | 5.15.0 | | FlashInfer | 0.6.16.post3 | | Triton | 3.7.1 | | compressed-tensors | 0.17.0 | 运行时从启动日志中自动选择了以下路径: - modelopt_fp4 量化 - FlashInfer CUTLASS NVFP4 GEMMs - FlashInfer attention for the text model, flashinfer-native decode on SM120 - Triton/FLA GDN 预填充内核 - Flash Attention for the vision encoder - 完整和分段 CUDA 图;推测执行已关闭 **实际显存预算** 重要区别在于模型权重大小、vLLM 的进程分配以及来自 nvidia-smi 的全卡数字之间。 | 项目 | 测量值 | | :--- | :--- | | 磁盘上的检查点 safetensors | 19.18 GiB | | vLLM 报告的模型加载 | 18.51 GiB | | 手动固定的 KV 池 | 9,150,000,000 字节 = 8.52 GiB | | vLLM 报告的 GPU KV 容量 | 268,170 个 token | | vLLM 报告的最大 262,144 个 token 并发数 | 1.02 倍 | | 运行中的 VLLM::EngineCore 进程 | 29,322 MiB | | 最终全卡快照 | 已使用 30,532 MiB / 空闲 1,610 MiB | 在加载服务器的空闲快照期间,随着桌面活动,空闲显存从 1,610 到 1,818 MiB 不等。这是真实的工作余量,但并不宽裕。我不会称其为仅无头环境的适配方案:KDE、Firefox 和终端都在运行,但第二个大型 CUDA 工作负载显然会使其崩溃。在此配置中,`--gpu-memory-utilization 0.92` 仅作为启动准入门槛。因为 `--kv-cache-memory-bytes 9150000000` 固定了 KV 池,vLLM 明确表示该分配不遵循 `gpu_memory_utilization`。降低 0.92 并不会缩小此 KV 池或上下文窗口;它只是让进程在正常桌面占用显存的情况下启动。`--max-num-seqs 3` 并不意味着三个同时进行的 262K 请求。KV 池仅有 1.02 倍的完整窗口容量。三个槽位有助于处理共享同一池的较短实际请求。 **精确安装和模型版本** 我已有可用的 Arch NVIDIA 驱动和 /opt/cuda。这会创建上述 Python 环境并固定 CUDA 13.0 vLLM/PyTorch wheel 系列: ```bash uv venv --python 3.13 qwen38-env uv pip install --python qwen38-env/bin/python 'vllm==0.27.1' --torch-backend=cu130 ./qwen38-env/bin/hf download \ joshebbs/qwen3.8-27b-uncensored-nvfp4-modelopt \ --revision e5ff4986938dcd0dd05ab4cce89da1b052be6ce3 \ --local-dir Qwen3.8-27B-Uncensored-NVFP4-modelopt ``` 权重哈希值: ``` 5db0ff93ebdf68034770a6acec123971e618928684bd2d5f3f51346990254911 model.safetensors 90fa0e3eed5a647c035c6df9ecabc416c0f8d573ff84ac12485b085f00a7cdf2 model-mtp-grafted.safetensors ``` 不要因为推测执行已关闭就从此版本删除 model-mtp-grafted.safetensors;检查点索引包含映射到它的 15 个张量。当推测执行关闭时,vLLM 在运行时不使用 MTP 头,但保持下载版本完整可避免检查点不完整。 **我日常设置中使用的聊天模板** 速度测试使用原始 completions 端点,因此聊天模板不影响这些数字。它影响我的日常聊天/工具行为。我精确使用的模板是 froggeric/Qwen-Fixed-Chat-Templates v22.2,版本 f64494d7b8a768222ab799d8c81f6e89dd272ac3,加上一个小型系统提示简洁性块。上游仓库此后已更新,因此需固定版本: ```bash mkdir -p chat-templates/froggeric-fixed chat-templates/sharp-v22.2 ./qwen38-env/bin/hf download froggeric/Qwen-Fixed-Chat-Templates \ chat_template.jinja \ --revision f64494d7b8a768222ab799d8c81f6e89dd272ac3 \ --local-dir chat-templates/froggeric-fixed cp chat-templates/froggeric-fixed/chat_template.jinja \ chat-templates/sharp-v22.2/chat_template.jinja ``` 我将第一行版本字符串更改为 `qwen3.8-froggeric-v22.2-sharp`,然后在 `{%- set _msgs = messages[head.count:] %}` 之后立即插入以下内容: ``` {%- set _terse %} Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable. Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made. Always: keep essential steps, caveats, uncertainties, and specifics — never drop correctness or a needed warning for brevity. Keep the final answer lean. Use the least structure that conveys it (plain prose when short; lists or code only when they earn their place). If genuinely uncertain, say so and explain why — never omit uncertainty for the sake of brevity. If a user request is genuinely ambiguous, ask a sharp question, don't guess. {%- endset %} {%- if not _sc %} {%- set _sc = _terse | trim %} {%- else %} {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %} {%- endif %} ``` 校验和: ``` 55d027bfded4407d214e5718e2f2804de73e843... (此处省略) ```
查看原文

相似文章

在32GB显存上以Q8量化使用Qwen3.6-27,接近100K上下文

Reddit r/LocalLLaMA

用户分享了他们在拥有32GB显存的RTX 5090上,使用Q8量化的Qwen3.6-27B模型尝试达到115K上下文长度的配置与实验过程,并给出了基准测试结果,以及上下文长度与kv-cache量化之间的权衡。