X99 + 128G DDR3 + 单张 7900 XTX:Strata RDNA3 fork 对比原版,prefill 2.8 倍、decode 1.27 倍,附 69 道客观质量题
机器:ubox(X99-TF)| 日期:2026-11-02 | 引擎:原版 0.1.52-linux-x86_64-hip-rx7900(预编译) vs nicejunjie/Strata-rdna3 @ 81cbfdb(含 PR #1),engine 0.1.43
模型:Qwen3.8-Flash-Next IQ3_S(同一份 GGUF,两套引擎共用),256K 上下文,int8 KV,MTP 草稿头
GPU:单张 RX 7900 XTX 24 GiB(gfx1100,PCIe 3.0 x16)| CPU:Xeon E5-2678 v3,12 核 24 线程,Haswell,无 AVX-512
0. 摘要
同一台机器、同一个模型文件,只换引擎:
| 实测输入 | 原版 prefill | fork prefill | 倍数 | 原版 decode | fork decode | 倍数 | 墙钟 |
|---|---|---|---|---|---|---|---|
| 5,572 tok | 1,121 tok/s | 1,743 tok/s | 1.55× | 67.4 tok/s | 85.8 tok/s | 1.27× | 8.8 s → 6.4 s |
| 22,112 tok | 1,236 tok/s | 3,276 tok/s | 2.65× | 68.9 tok/s | 82.4 tok/s | 1.20× | 21.7 s → 9.9 s |
| 88,259 tok | 1,262 tok/s | 3,526 tok/s | 2.79× | 63.4 tok/s | 79.7 tok/s | 1.26× | 74 s → 28.3 s |
| 168,284 tok | 1,201 tok/s | 3,357 tok/s | 2.80× | 61.9 tok/s | 82.5 tok/s | 1.33× | 144 s → 53.5 s |
| 238,940 tok | 1,148 tok/s | 3,280 tok/s | 2.86× | 58.6 tok/s | 74.6 tok/s | 1.27× | 212 s → 76.5 s |
※ 全部为 3 次中位数,温度 0、seed 42、每次唯一 salt 保证 cache_n = 0(无前缀复用)。数据为引擎自带 timings 字段,非客户端计时。
一句话:读满 24 万 token 从 3 分半缩到 1 分 16 秒,出字快约 27%;Agent 多轮里冷启动轮从 18.8 秒降到 8.9 秒,有缓存的轮次从 3.3 秒降到 2.5 秒。质量侧 69 道客观判卷题两边打平(各 65/69,错的是同一批题)。
1. 测试环境
硬件
| 项 | 值 |
|---|---|
| CPU | Intel Xeon E5-2678 v3,12 核 24 线程,Haswell;指令集 AVX2 / FMA / F16C,无 AVX-512(这一条决定了必须用 PR #1,见 §2.2) |
| 内存 | 125 GiB DDR3 四通道(4×32 GB,DMI 报 1866 MT/s) |
| GPU | AMD Radeon RX 7900 XTX,24 GiB,gfx1100;主机链路 PCIe 3.0 x16(实测 H2D 13.43 GB/s) |
| 存储 | NVMe 468 GB(模型 53 GB + fork 包 1.5 GB + ROCm 11 GB) |
| 系统 | Ubuntu 24.04.5,内核 6.8.0-147-generic,内核自带 amdgpu |
软件
| 项 | 原版 | fork |
|---|---|---|
| 引擎 | 0.1.52-linux-x86_64-hip-rx7900(预编译,Strata Terminal 组件) |
0.1.43,源码编译(build-hip,-DCMAKE_HIP_ARCHITECTURES=gfx1100) |
| ROCm | 随组件捆绑 | TheRock 轮子 7.10.0a20251120,装进 .venv(不污染系统) |
| 安装方式 | Terminal 应用一键装 | 源码 ./setup.sh --build |
| 模型 | IQ3_S abliterated(2 shard,53 GB) | 同一份文件(硬链接,零额外占用) |
2. 安装(fork 特有的三个坑)
2.1 源码
git clone 从国内直连会断流(early EOF / invalid index-pack),改用 tarball 一次成功:
aria2c -x8 -s8 -o strata.tar.gz \
"https://codeload.github.com/nicejunjie/Strata-rdna3/tar.gz/refs/heads/rdna3"
tar xzf strata.tar.gz -C Strata-rdna3 --strip-components=1
2.2 必须用 PR #1(AVX-512 的坑)
分支头(2026-11-01 之前)编译出来能过,但一启动就 SIGILL:
$ ./engine/strata --version
Illegal instruction (core dumped)
定位:src/kernels/cpu/iq_avx512.cpp 用 -mavx512f -mavx512bw -mavx512vl -mavx512dq -mavx512vnni -mavx512vbmi 单独编译,且其查表初始化在静态初始化阶段执行,早于 ISA 派发。STRATA_FORCE_ISA=avx2、STRATA_FORCE_AVX2=1 都救不回来。
作者已于 2026-11-02 02:13 合并 PR #1(把查表初始化推迟到函数内、探测代码按非 AVX-512 编译)。用 81cbfdb 及之后的版本即可:
$ ./engine/strata --version
strata 0.1.43
注意:如果你在 11-02 之前下过源码,重新拉一次;只改编译参数没用。
2.3 ROCm 下载:单连接 50 KB/s,必须多线程
setup.sh 会用 pip 从 rocm.nightlies.amd.com 拉三个轮子,共 2.1 GB。实测单连接被限速到约 50 KB/s(2.1 GB 要十几小时),pip 直接 Read timed out。
解法:先用 aria2 16 线程下好,再本地装(实测总带宽 13.8 MB/s,3.5 分钟下完):
aria2c -q -x16 -s16 --file-allocation=none -o rocm_sdk_core-7.10.0a20251120-py3-none-linux_x86_64.whl \
https://rocm.nightlies.amd.com/v2/gfx110X-dgpu/rocm_sdk_core-7.10.0a20251120-py3-none-linux_x86_64.whl
# devel 与 libraries 两个轮子同理,共三个
2.4 元包缺失时要手动解压
rocm 元包(提供 rocm-sdk 命令)在部分时间点不可用,导致 setup.py 卡在校验。手动补齐:
S=.venv/lib/python3.12/site-packages
tar xf $S/rocm_sdk_devel/_devel.tar -C $S # 8.1 GB,解出 _rocm_sdk_devel/
printf '#!/bin/sh\necho "%s/_rocm_sdk_devel"\n' "$PWD/$S" > .venv/bin/rocm-sdk
chmod +x .venv/bin/rocm-sdk
setup.py 只调用 rocm-sdk path --root,这个 shim 足够。
其余步骤(pip 依赖、模型包生成)按
./setup.sh --build --backend hip --model IQ3_S --no-start走即可,pip 记得挂国内镜像。
3. 四组对照:提升到底来自哪里
只跑 A/B 两组会得出错误结论——那 2.8 倍里有参数、有环境开关、有引擎代码。所以做了四组:
| 组 | 引擎 | 参数 | 用途 |
|---|---|---|---|
| A | 原版 0.1.52 | 原版调优参数(--pcie-frac 0.35 --ple-io ram --spec 3 --adapt-every 1) |
基准线 |
| B | fork 0.1.43 | fork 全套(--pcie-frac 0 --ple-io direct --spec 4 + 42 个 STRATA_* 开关) |
实际换过去能得到什么 |
| C | fork 0.1.43 | 原版参数,不加任何 STRATA_* |
只换引擎会怎样 |
| D | 原版 0.1.52 | fork 的命令行参数,不加 STRATA_* |
只抄参数会怎样 |
结果(prefill / decode,tok/s):
| 输入 | A | B | C | D |
|---|---|---|---|---|
| 5,572 | 1,121 / 67.4 | 1,743 / 85.8 | 770 / 64.5 | — |
| 22,112 | 1,236 / 68.9 | 3,276 / 82.4 | 826 / 67.3 | 1,265 / 72.6 |
| 88,259 | 1,262 / 63.4 | 3,526 / 79.7 | 828 / 64.9 | 1,281 / 65.5 |
| 168,284 | 1,201 / 61.9 | 3,357 / 82.5 | 800 / 60.4 | — |
| 238,940 | 1,148 / 58.6 | 3,280 / 74.6 | 未完成 | 1,139 / 63.7 |
读表:
- C 比 A 慢 31–34%:fork 的代码本身不但没更快,配原版参数还更慢。
- D 和 A 基本持平(prefill ±2%,decode +3~9%):光抄命令行参数没用。
- B 才是唯一有效的组合。
一句话:这不是"换个引擎"或"抄个参数",是引擎 + 命令行参数 + 42 个环境开关三者绑定,缺一个就失效。想只抄参数省事,数据说不行。
4. 性能测试
4.1 方法
- 每次请求带唯一 salt,保证
cache_n = 0(不复用前缀);读timings.prompt_per_second/predicted_per_second - 温度 0、seed 42、输出 256 token、每档 3 次取中位数
- 每组开测前先发一个丢弃的预热请求(首轮明显偏低,8K 档第一次 1,492、第二次 1,726)
- 显存/内存每档记录,两套引擎都是单实例独占
4.2 结果(fork 实测)
| 输入 | prompt tokens | prefill | decode | 墙钟 |
|---|---|---|---|---|
| 5.6K | 5,572 | 1,743 tok/s | 85.8 tok/s | 6.4 s |
| 22K | 22,112 | 3,276 tok/s | 82.4 tok/s | 9.9 s |
| 88K | 88,259 | 3,526 tok/s | 79.7 tok/s | 28.3 s |
| 168K | 168,284 | 3,357 tok/s | 82.5 tok/s | 53.5 s |
| 239K | 238,940 | 3,280 tok/s | 74.6 tok/s | 76.5 s |
4.3 Agent 多轮(模拟 8 轮对话,首轮读 2 万 token)
| 轮次 | A 原版 | B fork |
|---|---|---|
| 第 1 轮(冷启动) | 18.8 s | 8.9 s |
| 第 2–7 轮(缓存命中) | 3.2–3.7 s | 1.8–3.0 s |
| 第 8 轮(压缩后重读) | 18.3 s | 7.9 s |
有缓存的轮次也快了约 25%——那些轮次主要耗时在出字,而出字也快了。
4.4 数据怎么读
- 2.6–2.9 倍只出现在 22K 以上。5.6K 档只有 1.55 倍,因为短 prompt 的 prefill 时间本来就小,固定开销占比高。
- 墙钟差距比 tok/s 差距更大:239K 档 212 s → 76.5 s,是 2.77 倍。
- 这台机器的 PCIe 只有 3.0 x16(H2D 13.43 GB/s),能跑到 3,280 tok/s 说明 fork 的 prefill 主要不是靠总线搬数据。
5. 质量测试(69 道客观判卷题)
不跟原版比"像不像",而是每题配独立判卷器:
| 题型 | 判卷方式 | 题数 |
|---|---|---|
| 改代码 | 把输出代码跑单元测试,跑通才算过 | 22 |
| 数学 / 逻辑 | 精确匹配唯一答案 | 26 |
| 结构化输出 | JSON 解析校验、SQL 真跑比结果、正则测样例、CSV/表格解析 | 10 |
| 指令遵循 | 程序校验格式约束(行数、字数、分隔符、递增) | 8 |
| 长文取码 | 3 万–15 万字文档中间埋码,问出来 | 3 |
结果:
| 题集 | 原版 | fork |
|---|---|---|
| 40 题集(关思考) | 36/39 | 36/39 |
| 30 题新集(关思考) | 29/30 | 29/30 |
| 合计 | 65/69 | 65/69 |
两边错的是同一批题:
| 题目 | 两边都答成 | 正确 |
|---|---|---|
| 实现 LRU 缓存 | import OrderedDict(语法就错) |
from collections import ... |
| 词频 Top-K | import Counter(同样错) |
同上 |
| 鸡兔同笼(头 35 脚 94) | 12 只兔 | 23 只 |
| 3:15 时针分针夹角 | 82.5 度 | 7.5 度(问小夹角) |
同一批题、同一个错法 → 这是模型短板,不是引擎差异。
注意:开思考时 fork 有一道题把 1200 token 输出预算全花在推理上、没写出代码(
finish_reason=length)。关掉思考后该题通过。用 fork 写代码时把max_tokens设大一点。
6. 思考开关:端到端差 3–4 倍
出字速度(tok/s)不能当体感——思考过程也算时间。同一批题、同一引擎,只切 chat_template_kwargs: {enable_thinking: false}:
| 题型 | 原版·开思考 | 原版·关思考 | fork·开思考 | fork·关思考 |
|---|---|---|---|---|
| 改代码 | 8.9 s | 2.4 s | 8.2 s | 2.1 s |
| 数学逻辑 | 2.7 s | 0.7 s | 2.1 s | 0.6 s |
| 指令遵循 | 2.8 s | 0.8 s | 2.3 s | 0.6 s |
| 结构化输出 | 3.1 s | 1.1 s | 2.4 s | 0.9 s |
| 长文取码 | 63.3 s | 63.7 s | 23.4 s | 24.4 s |
- 短题关思考快 2.8–4.0 倍
- 长文题没差别(时间全在读入,输出只有几个字)
- 同一批题,开/关思考的判定结果几乎完全一致(13/14、4/4、6/6 相同)
反常识:引擎的 decode tok/s 在开思考时反而更高(结构化推理文本的投机接受率高)。但用户等的是最终答案,所以体感上关思考快得多。想要体感快,关思考;想要 tok/s 好看,开思考。
7. spec 扫描:3 或 4 都行,2 偏慢
--spec(每步草稿数)不是越大越好。Agent 多轮 8 轮总计:
| spec | 8 轮总计 | 缓存轮均值 | 草稿接受率(写代码) | 接受率(写说明) |
|---|---|---|---|---|
| 2 | 35.8 s | 3.0 s | 88.3% | 81.5% |
| 3 | 33.2 s | 2.7 s | 84.4% | 72.0% |
| 4 | 32.8 s | 2.7 s | 76.7% | 71.7% |
| 6 | 32.4 s | 2.6 s | 70.0% | 55.7% |
接受率随草稿数单调下降,收益在 3–4 封顶:
每步平均产出 = (1 - α^(k+1)) / (1 - α)
每步代价 ≈ 1 + c·k
α 掉得比 k 涨得快,k 过了 4 就白跑验证。spec 2 在 fork 上慢 8%,spec 6 只是持平。
每个 spec 只跑 1 轮,误差 ±5%,所以 3/4/6 之间 0.4–0.8 秒的差别不能当真。结论只有一句:2 明显差,3 以上打平,选 3 或 4。
8. 已知限制与注意事项
- 必须整套换:引擎、命令行参数、42 个
STRATA_*环境开关三者绑定。只换引擎慢 31–34%(C 组),只抄参数等于没换(D 组)。 - AVX-512 修复很新:PR #1 于 2026-11-02 02:13 合并。此前版本在无 AVX-512 的 CPU 上必然 SIGILL,且
STRATA_FORCE_ISA无效。 - 分支单人维护:
nicejunjie/Strata-rdna3,上游更新要手动合并;作者验证机是 9950X3D2,本机(Haswell + DDR3)不是他的目标平台。 - 安装链路长:ROCm 2.1 GB 需手动多线程下载,元包缺失要自己解压 + 写 shim,全程约 40 分钟(不含编译)。
- 写代码要把
max_tokens放大:开思考时容易把预算全花在推理上,finish_reason=length导致代码截断。 - 本组数据都是单次运行:每档 3 次取中位,但每组只跑一轮,跨组比较误差约 ±5%。
- 质量测试是自建判卷器:69 题、客观判分,但不是权威 benchmark,只能说明"两边没差别",不能说明"绝对水平如何"。
- 内存占用高:fork 的专家 arena 约 46.8 GiB(
arena_mib=47962),加 KV 后整机占用 50 GB 上下。这台 125 GiB 机器跑单实例没问题,但同机不能再跑第二个。
9. 复现命令清单
# 1) 源码(必须 81cbfdb 或之后,含 PR #1)
aria2c -x8 -s8 -o strata.tar.gz "https://codeload.github.com/nicejunjie/Strata-rdna3/tar.gz/refs/heads/rdna3"
tar xzf strata.tar.gz -C Strata-rdna3 --strip-components=1
# 2) 系统依赖
sudo apt install -y build-essential cmake ninja-build python3-venv aria2
# 3) ROCm 轮子(多线程下,单连接会被限速到 50 KB/s)
aria2c -q -x16 -s16 -o rocm_sdk_core-7.10.0a20251120-py3-none-linux_x86_64.whl \
https://rocm.nightlies.amd.com/v2/gfx110X-dgpu/rocm_sdk_core-7.10.0a20251120-py3-none-linux_x86_64.whl
# devel / libraries 同理
# 4) 编译 + 生成模型包(约 20 分钟)
cd Strata-rdna3
export XDG_CONFIG_HOME=$PWD/.config PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
./setup.sh --setup --build --backend hip --family qwen --model IQ3_S \
--context 262144 --kv int8 --vision no --gpu 0 \
--data-dir /path/Strata-data-rdna3 --no-start --yes
# 5) 起服务(fork 自带 serve/server.py,不要用 0.2.x 的)
./.venv/bin/python serve/server.py --engine strata \
--config /path/strata-iq3_s.json --port 8080
# 6) 自检
curl -s http://127.0.0.1:8080/health
# 预期健康返回
{"status": "ok", "max_context": 262144, "model": "qwen3.8-flash-next-iq3_s", "loaded": true}
测速脚本读引擎自己的 timings 字段即可,不需要客户端计时:
# 关键:每次请求带唯一 salt,确保 cache_n == 0
r = post("/v1/chat/completions", {"model": m, "messages": [{"role": "user", "content": salt + doc}],
"max_tokens": 256, "temperature": 0, "seed": 42})
t = r["timings"] # prompt_per_second / predicted_per_second / draft_n_accepted