前言
上半年经常看老特的本地llm部署视频,虽然感觉满足了好奇心,但是因为手上没有硬件+没有依靠本地AI来赚钱的需求,一直也只是看看。最近出了strata这个框架,又听说gsq量化的qwen 27b模型不错,依靠手头已经有的硬件很可能可以实现本地token自由,于是画了两个周末调研+折腾了一下。下面就是折腾的成果,希望给同样使用RDNA4消费级显卡的朋友一点信心。如果大家看了这个下面的设置能指点指点就更好了。
硬件
RX 9070 16 GB / Ryzen 7 5700X / B450m主板 / 64 GB DDR4-3133 / Intel Optane 905P 1.5t
相比各位大神这个配置应该是比较寒酸的,因为这个是我的游戏电脑,没有往里面投钱的动力,是这样的。
为了跑strata,唯一做的改动是内存。原本我用的是一对16g的ddr4 3600内存。看了chiphell的帖子说只要有16g vram+64g ram就可以跑效果几乎无损的iq3_s量化模型,于是从一台当前比较空闲的小主机上抠下了两根32g 3200mhz的内存,然后去pdd花30买了两条笔记本内存转接卡。也因为用了转接卡可能信号有损失,要降频到3133mhz才能亮机。也试过混插原本的32g,结果会进一步拉低内存频率,最多2133mhz。考虑到strata可能对内存带宽比较高,于是就只用64g了。
傲腾是去年存储低位的时候在亚马逊淘的。在我当前的配置下其实它的随机读写性能优势相对一般nvme ssd不能产生什么增益,详见后文。
系统
Ubuntu Server 24.04.5,内核 6.17.0-42,ROCm 7.2.4(gfx1201)。
这里先声明一下,我的agent跑在我日常使用的mac上。推理机就只做推理,完全不跑任何别的东西。所以同等配置我能用的系统资源会比较多
系统层次的优化主要就是把ubuntu的后台更新服务关掉了,别的也没干什么。
下面的内容主要都是deepseek帮我总结的了,有想复现的喂一下agent让它复现就好。
我选用了strata 0.1.45和kvmem分别作为flash next和27b的引擎。我原本以为我的配置只能跑大概96-128k的上下文,但是通过实验,我发现只要牺牲一点点速度,就可以换来更长的上下文,减少触发压缩的频次,提高体验。以下的配置都是基于长对话优先来配的,尽可能利用系统资源。
0. 软件栈版本与构建
0.1 基础环境
| 项 | 版本 |
|---|---|
| 系统 | Ubuntu 24.04.5 LTS,内核 6.17.0-42-generic |
| GPU | AMD Radeon RX 9070 16 GB(gfx1201) |
| ROCm | 7.2.4(rocm-core 7.2.4 / hip-runtime-amd 7.2.53211.70204) |
| LLVM/编译器 | ROCm 自带 clang(/opt/rocm-7.2.4/llvm/bin/clang++) |
| 磁盘 | Intel Optane 905P(/data,ext4 noatime);WD Elements USB SSD(/,系统盘 + 备份) |
0.2 KVMem(llama.cpp fork,27B 服务)
| 项 | 值 |
|---|---|
| KVMem 版本 | 0.18.0(repo commit faf3c22) |
| vendored llama.cpp | 620d2225c(上游 v0.7.0) |
| 构建目录 | /data/src/kvmem/build-hip-linux |
| CMake | -DCMAKE_BUILD_TYPE=Release -DGGML_HIP=ON -DGGML_VULKAN=OFF -DGPU_TARGETS=gfx1201,ROCM_PATH=/opt/rocm-7.2.4,CMAKE_HIP_ARCHITECTURES=gfx1201 |
| 入口 | python3 scripts/build-rocm.py --linux --rocm /opt/rocm --gpu-targets gfx1201 --jobs 8 |
本地修复(ROCm 7.2.4 下官方源码不能直接编过,共 4 处):
CMakeLists.txt:kvmem-stagein-hip目标补kvmem/include(官方漏了该 include 目录)backends/patches/llamacpp-kvmem.patch:把补丁里新增的cudaPeekAtLastError()改为hipPeekAtLastError()(ROCm 无 CUDA 运行时名),并同步更新backends/versions.json的patch_sha256- 清理补丁残留:失败重试会留下未跟踪文件(
src/llama-kvmem-factory.h),导致git apply报"已存在" compat/cuda_runtime.h垫片:两个 adapter TU(llama-memory-kvmem.cpp/-mtp.cpp)以普通 C++ 编译却#include <cuda_runtime.h>;提供最小垫片(includehip/hip_runtime.h+cuda*→hip*宏),并在 CMake 给这两个文件加-I compat -I /opt/rocm/include -D__HIP_PLATFORM_AMD__=1
0.3 Strata(125B 服务)
| 项 | 值 |
|---|---|
| 版本 | 0.1.45(源码 commit 477ac13) |
| 构建 | engine/BUILD.json:source: local-hip、backend: hip、archs: [gfx1201]、src b95137167bd9b751 |
| 构建目录 | /data/src/Strata/build-hip,CMAKE_BUILD_TYPE=Release |
| CMake 开关 | STRATA_ENABLE_HIP=ON、STRATA_ENABLE_CUDA=OFF、STRATA_ENABLE_SYCL=OFF、STRATA_NATIVE_EXPERTS=ON、STRATA_MMQ_KQUANTS=ON、STRATA_MMQ_TAB=OFF、STRATA_BUILD_TESTS=OFF;CMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++、CMAKE_HIP_ARCHITECTURES=gfx1201 |
| 运行时环境 | STRATA_HIPBLASLT_TUNING=/data/src/Strata/tools/hip/gfx1201-hipblaslt-100202.txt、lib_dirs=/opt/rocm/lib、backend=hip |
| 数据 | pack iq3_s(49 GB,experts.bin + dense)、原生长张量 + PLE 分片(GGUF,79 GB)、MTP 草稿层(6.5 GB) |
1. Qwen3.8-27B(KVMem 虚拟化 KV,kvmem.service)
1.1 启动命令(systemd ExecStart)
ExecStart=/data/src/kvmem/build-hip-linux/bin/llama-kvmem-server \
-m /data/models/gsq/Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp.gguf \
--mmproj /data/models/mmproj/mmproj-Qwen3.8-27B-Q5_K-MIX.gguf --no-mmproj-offload \
--device ROCm0 --split-mode layer -ngl 99 -fa on --load-mode auto \
--host 0.0.0.0 --port 8080 \
-c 262144 -b 512 -n 16384 \
--kvmem --kvmem-lrfu --kvmem-budget 32768 --kvmem-gen-reserve 16384 \
--kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \
--kvmem-host-mib 49152 --kvmem-sessions 8 \
--spec-type draft-mtp --spec-draft-n-max 3 --spec-kv-dtype f16 \
--kvmem-mtp-state replay --image-max-tokens 512 \
--enable-thinking --reasoning-budget 4096 \
--chat-template-file /data/models/templates/chat_template.jinja \
--temp 1.0 --top-k 20 --top-p 0.95 --min-p 0 --presence-penalty 0.0 --repeat-penalty 1.0
1.2 参数逐条解释
| 参数 | 值 | 作用 |
|---|---|---|
-m |
Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp.gguf(12.12 GB) |
27B 3.5 bpw 权重,自带 MTP 头 |
--mmproj / --no-mmproj-offload |
Q5_K_MIX(331 MiB) | 视觉投影器;跑在 CPU,不占显存 |
--device ROCm0 / --split-mode layer |
单卡 | 全部层上 GPU |
-ngl 99 |
99 | 权重全量 offload |
-fa on |
开 | flash attention(显式) |
--load-mode auto |
Linux 默认 | 自动选加载方式 |
-c 262144 |
262,144 | 逻辑上下文(模型原生窗口) |
-b 512 |
512 | 逻辑 batch |
-n 16384 |
16,384 | 单轮输出上限 = 生成预留 |
--kvmem |
开 | 启用 KV 虚拟化 |
--kvmem-lrfu |
开 | 检索历史按相关度加权(LRFU) |
--kvmem-budget 32768 |
32,768 token | GPU 工作集(sink 12K + recent 1K + 检索块) |
--kvmem-gen-reserve 16384 |
16,384 token | 生成追加空间(单轮输出被它限制) |
--kvmem-block-tokens 128 |
128 | 检索块粒度 |
--kvmem-query-policy user |
user | 用最后一条用户消息作为检索查询 |
--kv-dtype q8_0 |
q8_0 | 主 KV 格式(≈34 KiB/token) |
--kvmem-host-mib 49152 |
48 GiB | 主机侧会话 KV 配额 |
--kvmem-sessions 8 |
8 | 最多保留 8 个会话 |
--spec-type draft-mtp |
draft-mtp | 投机解码:用模型自带 MTP 头 |
--spec-draft-n-max 3 |
3 | 每步最多 3 个草稿 token |
--spec-kv-dtype f16 |
f16 | MTP 草稿 KV 精度 |
--kvmem-mtp-state replay |
replay | MTP 状态随会话分页/replay |
--enable-thinking / --reasoning-budget 4096 |
4,096 | 开思考,思考预算 4K |
--chat-template-file |
froggeric v22.5 | 修复版模板(默认 medium 思考) |
| 采样 | 官方思考套 | temp 1.0 / top_p 0.95 / top_k 20 / min_p 0 / presence 0 / repeat 1.0 |
1.3 采用的优化与实测效果
| 优化 | 做了什么 | 效果(实测,2026-10-18/19) |
|---|---|---|
| KV 虚拟化 | GPU 只放 32,768 token 工作集,其余历史分页到主机 RAM(48 GiB 配额) | 逻辑上下文 262,144;150K needle 命中(prefill 694 t/s、decode 42.0 t/s、冷读 219s);253K needle 命中(prefill 637 t/s、decode 39.1 t/s、冷读 401s) |
| 多轮复用 | 会话按 token 前缀识别,历史 KV 常驻主机 | 150K 历史下追问只处理 34 个新 token、3 秒返回 |
| 多会话保留 | --kvmem-sessions 8 |
A(150K)→ B(54.5K)→ 回 A:A 历史保留,34 token / 4 秒 |
| MTP 投机 | draft-mtp + n-max 3 + replay |
代码类 400-token 生成 62.0 → 66.5 t/s(+7%);长文 decode 39–42;自由行文略降(44.5 vs 48.0) |
| LRFU 检索 | 历史块按查询相关度加权 | 长文召回更稳;150K/253K needle 均命中 |
| 更大工作集 | budget 28,672 → 32,768 | 同时可见历史 +14%;显存 14.0 GB(仍有余量) |
| 修复版模板 | froggeric v22.5 | https://huggingface.co/froggeric/Qwen-Fixed-Chat-Templates, 默认 medium 思考(官方默认 xhigh);enable_thinking=false → reasoning 0;内联 <\|think_off\|> → reasoning 0;reasoning_effort:low 254 字符 vs xhigh 633 字符 |
| 官方采样 | temp 1.0 / top_p 0.95 / top_k 20 / min_p 0 / presence 0 | 与 Qwen 3.8 模型卡一致(思考模式) |
| 视觉加速 | --no-mmproj-offload |
视觉编码走 CPU,不占显存 |
资源占用:显存 14.0–14.7 GiB(空闲 ~88 MiB 基线),主机内存 15–18 GiB(会话装满后),48 GiB 会话配额。
1.4 已知上限
- 单 lane(
lanes=1),同一时刻只服务一个请求;会话在内存 park。 - decode 39–45 t/s:dense 27B 的带宽上限(645 GB/s ÷ 12.1 GB ≈ 53 t/s 理论值),参数调不动。
- 若要 70+ t/s,必须换 MoE(见 Strata)或更小模型(Bonsai 6.7 GB 实测 51.5 t/s)。
1.5 投机解码调参(--spec-draft-n-max 扫描,2026-10-19)
固定 400 token 生成、temp 0、短 prompt,端到端实测(KVMem 不吐接受率):
| 任务 | n-max 2 | n-max 3(当前) | n-max 4 | n=3 + p-min 0.6 |
|---|---|---|---|---|
| 代码生成(结构可预测) | 62.0 | 66.5(+7.3%) | 66.3(无增益) | 65.6 |
| 自由解释(中文说明) | 48.0 | 44.5(−7%) | — | 45.5 |
结论:
- n=3 是甜点;n=4 无收益(带宽受限);
--spec-draft-p-min反而拖慢(0.75 时掉到 63),不加 gate - 内容强相关:结构化/代码输出 n=3 更快;自由写作类 n=2 更快
- 任务映射:代码/agent/工具调用 → n=3;纯自由行文 → 可临时回 n=2;调研类(混合)→ 维持 n=3(工具调用段收益 + 长文 prefill 主导,n-max 影响小)
- 社区佐证:llama.cpp issue #30568(Strix Halo Vulkan n=4 腰斩)、sudoingX/qwen38-mtp(53 配置,建议 2~4 扫,带宽差加 p-min、快卡不加)
2. Qwen3.8-Flash-Next 125B(Strata,strata-256k.service)
2.1 启动命令
systemd ExecStart:
ExecStart=/data/src/Strata/.venv/bin/python /data/src/Strata/serve/server.py \
--engine strata --config /data/src/Strata/strata-iq3_s-256k.json \
--port 8080 --host 0.0.0.0 --slot-save-path /data/strata-slots
引擎配置 strata-iq3_s-256k.json 的 args:
["--pack", "/data/src/Strata-data/packs/iq3_s",
"--native", "/data/models/strata/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_S-00001-of-00002.gguf",
"--ple-gguf", "/data/models/strata/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_S-00002-of-00002.gguf",
"--expert-profile", "/data/src/Strata/data/expert-profile.bin",
"--expert-cache", "auto",
"--prefill", "auto",
"--spec", "4",
"--spec-min-p", "0.5",
"--mtp", "/data/src/Strata-data/mtp/rt",
"--max-context", "262144",
"--kv", "k8v4",
"--resident-experts",
"--vram-reserve-mib", "1024"]
2.2 参数逐条解释
| 参数 | 值 | 作用 |
|---|---|---|
--pack |
packs/iq3_s(49 GB) |
专家权重包(experts.bin 47 GB + dense 1.5 GB) |
--native |
IQ3_S 分片 1(52 GB) | 原生长张量(302 个)从 GGUF 直接读 |
--ple-gguf |
IQ3_S 分片 2(27 GB) | PLE 表(51.2 GB FP8 常量表) |
--expert-profile |
expert-profile.bin |
预热专家槽位(启动时 3 秒完成) |
--expert-cache auto |
自动 → 3,512 槽 / 6.72 GiB | GPU 专家缓存;KV 让位后自动缩 |
--prefill auto |
自动 | 预填充调度 |
--spec 4 / --spec-min-p 0.5 |
4 / 0.5 | MTP 投机解码(每步 4 草稿,最小概率 0.5) |
--mtp |
Strata-data/mtp/rt |
MTP 草稿层(6.5 GB) |
--max-context 262144 |
262,144 | 上下文上限(模型原生窗口) |
--kv k8v4 |
K q8_0 / V q4_0 | 混合 KV:13.06 KiB/token(f16 是 64 KiB) |
--resident-experts |
开 | GPU 装不下的专家复制进 RAM(pageable,~44 GiB) |
--vram-reserve-mib 1024 |
1,024 | 预留显存 |
serve --slot-save-path |
/data/strata-slots |
会话存盘/恢复 API |
2.3 采用的优化与实测效果
| 优化 | 做了什么 | 效果(实测,2026-10-18/19) |
|---|---|---|
| 缩专家缓存换 256K | 4,906 → 3,512 槽(9.34 → 6.72 GiB),KV 全放显存 | 上下文 96K → 262,144;显存 15.5–15.7 GiB(余 602–884 MiB) |
| 混合 KV(k8v4) | K q8_0 + V q4_0 = 13.06 KiB/token | 256K 的 KV 仅 3.27 GiB(f16 要 16 GiB) |
| MTP 投机 | --spec 4 --spec-min-p 0.5 |
接收率 39/46(85%);253K 下 decode 56.4 t/s(dense 27B 的 1.5 倍) |
| 专家分页 | --resident-experts(大页 + 8 GiB 守卫) |
44 GiB 专家常驻 RAM;RAM 55 GiB / available ~7–9 GiB |
| 会话槽保存 | --slot-save-path + /slots/0?action=save\|restore |
66K 会话:save 0.86s / 1.06 GB,restore 1.19s;恢复后追问 2s(34 新 token) |
| 前缀检查点 | 引擎每 16K token 打检查点 | 同会话追加几乎 0 重读 |
实测(253,650 token 长文):
- needle 命中(RED-COMET-77,文本 ~46% 深度)
- prefill 1,150 t/s(253K 冷读约 220 秒)
- decode 56.4 t/s
- 275K 请求 → 干净 HTTP 400("requests are never truncated")
2.4 已知上限 / 代价
- RAM 贴顶:55 GiB 常驻专家,available 仅 7–9 GiB;长会话有触发 8 GiB 守卫的风险(要宽裕换 IQ3_XXS,专家省 7 GB)。
- decode 比 96K 略降:256K 下 39–56 t/s(取决任务/命中);96K + KV streaming 时 45–57。
- 单会话:多会话需手动 save/restore(没有 KVMem 的自动多会话)。
3. 两套模型对比
| 指标 | Qwen3.8-27B(KVMem) | Qwen3.8-Flash-Next 125B(Strata) |
|---|---|---|
| 参数量(激活) | 27B dense | 125B MoE(~8B 激活) |
| 上下文 | 262,144(虚拟化) | 262,144(全注意力) |
| 253K 冷读 prefill | 637 t/s | 1,150 t/s |
| 253K decode | 39.1 t/s | 56.4 t/s |
| 短上下文 decode | 40–45 t/s | 45–57 t/s |
| 显存 | 14.0–14.7 GiB | 15.5–15.7 GiB |
| 主机内存 | 15–18 GiB(48 GiB 配额) | 55 GiB(专家常驻) |
| 多会话 | 8 个自动保留(4 秒切换) | 1 个(手动 save/restore 1–2 秒) |
| 视觉 | 有(mmproj,CPU) | 无 |
| 质量 | 27B 级别 | 125B 级(更强) |
选型:
- 多任务/多对话并行、内存敏感 → 27B KVMem
- 单会话长文、要最强模型 → Strata 125B
- 两者共用端口 8080,systemd
Conflicts=互斥,切换一条命令。
4. 多轮性能与磁盘实测(2026-10-19)
4.1 多轮对话:KVMem(27B)
测试:66,600 token 文档(4,000 条记录 + 10 个唯一访问代码),同一会话 10 轮问答。
| 轮次 | prompt 处理 | 耗时 | decode |
|---|---|---|---|
| 第 1 轮(冷读) | 66,622 token | 102.5 秒 | 56.7 t/s |
| 第 2–10 轮 | 28–56 token(只算新增) | 4–6 秒/轮 | 52–57 t/s |
准确率:
- 唯一访问代码:逐个追问 9/9 全对;"列出全部" 10/10
- 细粒度记录值不可靠:问 record 3400(实际 5800)→ 答 9500(那是 record 3500 的值);新会话单轮同样错
- 原因:① KVMem 只可见 32K/66K(中段靠检索,可能漏块);② 4,000 行近似文本导致注意力抓错相邻行(sink 区/结尾区都正确,只有中段错)
实操提醒:多轮场景 max_tokens 要给足(≥1,000),否则会被思考截断误判为"答不出"。
4.2 多轮对话:Strata(125B)+ DSH 极简模式模拟
请求结构:system(DSH 极简提示 + 工具列表)→ user → assistant 工具调用 JSON → user 工具结果(66,800 token)→ 10 轮问答。
| 轮次 | prompt 处理 | 缓存命中 | 耗时 | decode |
|---|---|---|---|---|
| 1(冷读) | 66,802 | 0 | 60.2 秒 | 56.6 t/s |
| 2–10 | 37–111 | 66.8–67.1K | 1.4–2.9 秒/轮 | 55–69 t/s |
准确率:10/10 全对,包括 record 3400 → 5800
(KVMem 失败的那题)。
4.3 两套栈多轮对比
| 指标 | KVMem(27B) | Strata(125B) |
|---|---|---|
| 首轮冷读(66.6–66.8K) | ~102 秒 | 60.2 秒 |
| 多轮延迟 | 4–6 秒/轮 | 1.4–2.9 秒/轮 |
| 唯一信息召回 | 9/9 + 10/10 | 10/10 |
| 中段精确查找(record 3400) | 9500 |
5800 |
结论:单会话 agent 工作(长工具结果 + 多轮追问)Strata 明显更优(更快、无检索漏块);KVMem 的价值在多会话自动保留(8 个)+ 内存省 3 倍。
4.4 磁盘敏感性:傲腾 vs USB 移动 SSD(Strata)
| 指标 | 傲腾 905P | USB 移动 SSD |
|---|---|---|
| 启动(44 GiB 专家拷贝) | ~60–90 秒 | 187 秒 |
| 专家 profile 预热 | 3.0 秒(2,399 MB/s) | 15.2 秒(474 MB/s) |
| 253K prefill | 1,150 t/s | 1,155 t/s(持平) |
| 253K decode | 56.4 t/s | 51.7(MTP 接受率 73% vs 85%,非磁盘因素) |
| 运行时磁盘读 | PLE 流(顺序) | 51.5 GB / 219 秒 ≈ 235 MB/s |
结论:在"专家常驻 RAM(--resident-experts)"的配置下,只有冷启动(1–3 分钟)明显受磁盘影响;稳态 prefill/decode 不吃盘(PLE 是顺序流,与计算重叠)。傲腾的随机读优势要到低内存模式或 SSD 分层才体现。
9500