Tracks
如果您无需升级 GPU、无需更换机器、也不必改用更小的模型,就能让大语言模型跑得更快,会怎样?
本指南将用多标记预测(MTP)来进行测试。在我的基准测试中,同一台 RunPod RTX 3090 上运行同一个 Qwen3.6 27B 模型,在启用 MTP 后,速度从38 tokens/sec 提升到 65 tokens/sec。这相当于1.71 倍提速,吞吐提升约71%,且输出质量无明显下降。
在本指南中,我们将:
- 配置一台 RunPod RTX 3090 机器
- 克隆并切换到 MTP 分支
- 以 CUDA 支持构建 llama.cpp
- 下载 Qwen3.6 27B MTP GGUF 模型
- 先在未启用 MTP 的情况下运行模型以获取基线速度
- 启用 MTP 并再次测试模型
- 对比启用与未启用 MTP 时的标记生成速度
- 了解 TurboQuant,作为进一步优化的可能下一步
什么是多标记预测(MTP)?
大多数 LLM 按「逐标记」方式生成文本:模型预测下一个标记,将其加入上下文,然后重复同样的过程。此方式可靠,但可能较慢,因为通常每生成一个新标记都需要一次解码步骤。
多标记预测(MTP)改变了这一点:它允许模型向前「预看」,一次提出多个后续标记,而不是仅预测一个。随后主解码流程会校验这些候选标记。若预测无误,模型可以一次性接收多个标记;若其中某个出错,模型就从那一点回退到常规路径。
在实践中,MTP 更像是内置的「草稿」机制。模型先起草几个最可能的下一个标记,再逐一验证并保留通过校验的标记。被接受的草稿标记越多,所需的完整解码步骤就越少,从而在不改变最终输出质量的前提下,提高每秒标记数。
简单来说:
- 未启用 MTP:生成标记 1 → 生成标记 2 → 生成标记 3
- 启用 MTP:起草多个标记 → 验证它们 → 批量接受有效标记
这就是 MTP 能显著加快本地 LLM 推理体验的原因。与其让模型一次只往前迈出一小步,不如在草稿预测正确时,让模型安全地「跳步」前进。

在llama.cpp 等工具和 vLLM 风格的实现中,这与投机解码(speculative decoding)密切相关:草稿标记只有在与验证器输出一致时才会被接受。
1. 配置 RunPod RTX 3090 机器
在本指南中,我使用了带 RTX 3090 的 RunPod GPU 实例。您也可以使用其他支持 CUDA 的 GPU,但本教程的基准结果基于 RTX 3090 的配置。
首先,新建一个 RunPod pod,并选择RTX 3090 GPU。
在部署 pod 之前,编辑模板设置:
-
将卷磁盘大小增加到 100 GB
-
新增一个 HTTP 端口:8910
-
添加名为
HF_TOKEN的环境变量,并将其值设置为您的 Hugging Face 访问令牌。
这个额外的 HTTP 端口便于您通过浏览器访问 llama.cpp 的服务器和 Web UI。Hugging Face 令牌用于下载鉴权,可加快模型下载速度,尤其是较大的 GGUF 文件。

更新模板后,部署 pod。运行就绪后,等待 RunPod 提供JupyterLab 访问。打开 JupyterLab,然后启动一个新终端。
在终端中安装所需系统包:
apt update
apt install -y git cmake build-essential curl wget python3-pip

2. 克隆并切换到 MTP 分支
接下来,进入我们将安装并构建 llama.cpp 的工作区目录:
cd /workspace
克隆 llama.cpp 仓库:
git clone --depth 1 https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
MTP 的改动仍在通过专门的 llama.cpp 拉取请求进行测试,因此我们需要获取并切换到该分支,以便在其并入主分支前使用最新的 MTP 实现。
在本地获取 MTP 分支:
git fetch origin pull/22673/head:mtp-pr
git checkout mtp-pr
这样就将本地的 llama.cpp 构建切换为启用 MTP 的版本,我们将在后续步骤中使用它。

3. 以 CUDA 支持构建 llama.cpp
现在已位于启用 MTP 的分支,接下来以 CUDA 支持构建 llama.cpp。这样模型即可使用 RTX 3090 GPU,而不是在 CPU 上进行推理。
运行 CMake 构建配置:
cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release
然后编译本指南所需的两个目标:
cmake --build build --target llama-cli llama-server -j

这将构建:
-
llama-cli:用于运行快速的命令行测试 -
llama-server:用于启动带浏览器访问的 OpenAI 兼容服务器
构建完成后,将 llama-server 二进制复制到 llama.cpp 根目录:
cp ./build/bin/llama-server ./llama-server
这样便于接下来在项目根目录直接运行服务器。
4. 下载 Qwen3.6-27B-MTP 模型
接下来,下载我们要用于测试的 Qwen3.6 27B MTP GGUF 模型。我们将先在未启用 MTP 时运行该模型,然后启用 MTP 再跑一次,以对比速度差异。
首先安装 Hugging Face 下载工具:
pip install -U "huggingface_hub[hf_xet]" hf-xet hf_transfer
然后启用更快的 Hugging Face 下载:
export HF_HUB_ENABLE_HF_TRANSFER=1
这有助于加快大型模型的下载,尤其在处理 GGUF 文件时。
现在为模型创建一个专用目录:
mkdir -p /workspace/models/qwen3.6-mtp
下载 Qwen3.6 27B MTP GGUF 模型:
hf download froggeric/Qwen3.6-27B-MTP-GGUF \
Qwen3.6-27B-Q4_K_M-mtp.gguf \
--local-dir /workspace/models/qwen3.6-mtp

如果您对微调 LLM 感兴趣,可查看我关于在医疗问答数据集上微调 Qwen3.6的教程。
5. 在未启用 MTP 的情况下运行 Qwen3.6-27B
现在进入本指南的核心:在启用 MTP 前后测试模型速度。
首先在未启用 MTP 的情况下运行模型。这将为我们提供干净的基线,便于稍后比较速度差异。我们使用同一个模型、同一块 GPU、相同的上下文长度和相同的服务器设置。下一步的主要变化仅是启用 MTP。
返回到 llama.cpp 目录:
cd /workspace/llama.cpp
以未启用 MTP 的方式启动服务器:
./llama-server \
-m "/workspace/models/qwen3.6-mtp/Qwen3.6-27B-Q4_K_M-mtp.gguf" \
--alias qwen3.6-27b-no-mtp \
--host 0.0.0.0 \
--port 8910 \
-ngl 99 \
-c 100000 \
--cache-type-k q8_0 \
--cache-type-v q8_0 \
-np 1 \
-b 2048 \
-ub 512 \
-t 8 \
-fa on \
--temp 0.7 \
--top-k 20 \
--top-p 0.95 \
--repeat-penalty 1.1 \
--metrics
这会在端口 8910 上启动一个 OpenAI 兼容的 llama.cpp 服务器。
模型可能需要一点时间加载,因为服务器需要将权重加载至 GPU 内存。准备就绪后,终端会显示服务器已在端口 8910 可用。

由于我们在设置 RunPod 模板时已暴露此端口,您无需再做其他配置。回到 RunPod 控制台,点击与端口 8910 关联的链接。这会在浏览器中打开llama.cpp Web UI,并已加载本地模型。

此处您可以像使用聊天界面那样,在浏览器中直接测试提示词。

在我的基线测试中,未启用 MTP 时,模型的响应速度约为38.86 tokens/sec。即便提示更复杂,速度仍大致在同一范围内。
对于在 RTX 3090 上运行的 27B 模型而言,这已经是可用的结果,尤其考虑到该 GPU 相比新的数据中心卡更慢且显存有限。
6. 在启用 MTP 的情况下运行 Qwen3.6-27B
现在我们用启用 MTP 的方式再次运行同一模型。
回到正在运行服务器的终端,按如下操作停止它:
CTRL + C
关键在于我们并未更换模型、GPU、量化方式或大多数运行时设置,只是新增了两个与 MTP 相关的参数:
--spec-type mtp
--spec-draft-n-max 3
第一个参数指示 llama.cpp 使用 MTP 风格的投机解码;第二个参数将草稿标记的最大数量设为 3,表示模型在验证前最多可尝试起草三个后续标记。
现在以启用 MTP 的方式重启服务器:
./llama-server \
-m "/workspace/models/qwen3.6-mtp/Qwen3.6-27B-Q4_K_M-mtp.gguf" \
--alias qwen3.6-27b-mtp \
--host 0.0.0.0 \
--port 8910 \
-ngl 99 \
-c 100000 \
--spec-type mtp \
--spec-draft-n-max 3 \
--cache-type-k q8_0 \
--cache-type-v q8_0 \
-np 1 \
-b 2048 \
-ub 512 \
-t 8 \
-fa on \
--temp 0.7 \
--top-k 20 \
--top-p 0.95 \
--repeat-penalty 1.1 \
--metrics
服务器就绪后刷新浏览器页面。如果页面未自动重连,请关闭并从 RunPod 控制台再次打开端口 8910 的链接。
现在使用相同类型的提示再次测试模型。

启用 MTP 后,速度明显提升。对于简单的问候提示,模型约能达到65–67 tokens/sec。与基线约38.86 tokens/sec 相比,仅通过增加两个命令行参数就带来了显著提升。

对于更复杂的提示,例如让模型用 Python 构建一个简单游戏,速度会略低,但仍远快于未启用 MTP 的基线。在该测试中,模型约能达到56–61 tokens/sec,对于在 RTX 3090 上运行的 27B 模型而言,仍是很强的表现。
总体上,在 RunPod RTX 3090 的配置下,启用 MTP 将 Qwen3.6 27B 的速度从约38 tokens/sec 提升至 65 tokens/sec。这相当于1.71 倍提速,吞吐提升约71%,无需更换硬件或改用更小的模型。
7. 建议:借助 TurboQuant 进一步提速
本指南的基准测试使用的是原生的 llama.cpp MTP 设置,未加入 TurboQuant、自定义补丁或其他运行时优化。这使测试更简单、可复现,并专注于仅启用 MTP 带来的速度提升。
若要进一步提升性能,下一步应探索将 MTP 与 TurboQuant 结合使用。MTP 通过允许模型接受多个预测标记来提高吞吐,而 TurboQuant 则有助于在推理期间降低 KV cache 的内存压力。
这对更大的模型、长上下文提示,以及类似 RTX 3090 这种可能受内存带宽和显存限制的 GPU 尤其有用。
因此,r/LocalLLaMA 社区的一些结果报告的 tokens/sec 高于本指南。那些设置通常将 MTP 与 TurboQuant、打过补丁的构建、不同的 KV cache 设置或更快的 GPU 结合使用。由于本教程专注于干净的仅 MTP 基准,TurboQuant 应被视为推荐的后续实验,而非当前设置的一部分。
结语
最近我一直关注 LocalLLaMA 的 Reddit 社区帖子,本地 LLM 推理的发展令人惊叹。大家已经能在显存有限的老款 GPU 上,将Qwen3.6 27B 用作本地编程助理。有些人还在 Mac 上运行了类似的方案,效果确实令人印象深刻。
在我亲自测试 MTP 之后,就理解了大家为何如此兴奋:在同一模型与同一 RTX 3090 配置下,启用多标记预测能将生成速度从约38 tokens/sec 提升至 65 tokens/sec。这几乎达到了2 倍提速,而无需升级 GPU 或改用更小的模型。
本指南聚焦于使用 llama.cpp 的简单、可复现的 MTP 设置,但这只是个开始。下一步可以尝试更优的 GGUF 量化、MTP、TurboQuant,以及更精细的运行时设置,看看本地推理速度还能被提升到何种程度。
对我而言,最令人期待的是这对本地编程代理的意义:您可以在自有硬件上运行强大的模型,降低每次请求的成本,保护代码隐私,并在不完全依赖互联网 API 的情况下使用 AI 编程助手。本地 LLM 的速度更快、可用性更高、实用性也远胜以往。
多标记预测常见问题
启用 MTP 是否需要单独的草稿模型?
不需要。对于 Qwen3.6-27B,MTP 已内置在模型本身,无需第二个草稿模型。
MTP 能让模型快多少?
在我们的 RunPod RTX 3090 配置中,启用 MTP 将生成速度从约 38 tokens/sec 提升至约 65 tokens/sec,即 1.71 倍提速,吞吐约提升 71%。
MTP 与投机解码有什么区别?
llama.cpp 中的 MTP 属于一种投机解码。模型自身的 MTP 头产生的草稿标记,只有通过验证才会被接受。与传统投机解码的关键区别在于:无需外部草稿模型。
是否还能在 MTP 基础上进一步加速?
可以。将 MTP 与 TurboQuant 结合使用(在推理时降低 KV cache 的内存压力)是进一步提速的推荐步骤,尤其适用于 RTX 3090 这类内存受限的 GPU。