☰
Prefix Cache 实验附录:环境、复现与详细统计
2026/10/17 5:05:45 网站建设 项目流程

Prefix Cache 实验附录:环境、复现与详细统计

本文是博客正文的配套材料。实验数据采集于 2026-10-11、2026-10-13,附录整理于 2026-10-14。完整脚本、操作记录和原始结果打包为实验附件;解压后保留experiments/目录结构。下文的证据路径均相对于附件根目录。

A. 环境与配置

平台为 HiDevLab A3。机制实验和两轮性能实验都只使用可见逻辑设备0,TP=1、PP=1;npu-smi原始型号为Ascend910,每芯片 HBM 总容量显示为65536 MB。这不是实验实际峰值占用,也不据此推断 910B/910C 等子型号。

10 月 13 日两轮性能实验的 14 份前后环境快照中,驱动和 Toolkit 版本文件内容一致:

driver/version.info: Version=26.1.1 package_version=26.1.1 Innerversion=V100R001C10SPC009B220 ascendhal_version=7.35.23 ascend_toolkit_install.info: version=9.1.0 innerversion=V100R001C11SPC001B243

10 月 11 日机制实验的npu-smi也报告版本26.1.1,但未单独保存 Toolkit 安装版本文件。实际固件版本未采集;驱动文件中的固件兼容范围不是已安装固件的版本。

环境原始记录:

  • 机制:experiments/prefix-cache-01/evidence/prefix_cache_20261011_02/environment.json
  • 原 1K 性能:experiments/prefix-cache-perf-01/evidence/prefix_cache_perf_20261013_01/environment_before.json,以及 02、03 的前后快照。
  • 长度扫描:experiments/prefix-cache-perf-length-01/evidence/prefix_cache_perf_length_20261013_01/environment_before.json,以及总实验和各run_01~run_03的前后快照。
项目记录
Python3.12.13
PyTorch / torch-npu2.10.0+cpu / 2.10.0.post4
vLLM / vLLM-Ascend0.26.0+empty / 0.26.0rc1
Transformers5.14.1
模型本地 Qwen3-0.6B;模型与 tokenizer 的不可变上游 revision 未知,原始环境记录保存了文件 SHA256
运行 vLLM568afb3a13806beb53bb2e6bd518269357b237c0
运行 vLLM-Ascendf2f74a16c3c50a76f4349d807918e83edec1e35c
公共执行条件BF16、Eager、同步调度、并发 1、贪心采样、忽略 EOS、块大小 128、Chunked Prefill 开启

三轮配置不能混为一组:

实验B 输入 / 输出 token长度上限 / token 预算缓存条件与重复
机制对照1038 / 32048 / 2048OFF、COLD、A→WARM、A→修改前缀
原 1K 性能1038 / 642048 / 2048Prefix Cache 均开启;3 次启动,各 3 对预热 + 8 对正式冷/热
长度性能1038、4110、8206、16398 / 6418432 / 184323 次启动,每长度各 3 对预热 + 8 对正式冷/热

长度扫描里的 1K 是重新测量的结果,没有与原 2048 配置的 1K 混算。

B. 复现实验与证据

完整执行过程保存在三组实验各自的execution-walkthrough.md,包括输入构造、实际命令、启动问题及修复、结果字段和源码对应。下面提炼能复现实验设计的步骤;实验由助手执行,原记录保留了执行者与学习验收的区分。

B.1 机制:先确认命中与输出

在具有上述软件环境的独立实验目录中,使用附件的run_prefix_cache.py。加载现有 Toolkit/ATB 环境,指定可见设备 0;原实验模型位置为/workspace/models/Qwen3-0.6B,复现时按自己的模型位置替换:

source/usr/local/Ascend/ascend-toolkit/set_env.shsource/usr/local/Ascend/nnal/atb/set_env.shexportPATH=/usr/local/python3.12.13/bin:$PATHexportLD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/common:/usr/local/Ascend/driver/lib64/driver:$LD_LIBRARY_PATHexportASCEND_RT_VISIBLE_DEVICES=0exportHF_HUB_OFFLINE=1exportTRANSFORMERS_OFFLINE=1python3.12-urun_prefix_cache.py\--model/workspace/models/Qwen3-0.6B--modeoff --output-dir off python3.12-urun_prefix_cache.py\--model/workspace/models/Qwen3-0.6B--modeon --output-dir on

实际包装脚本为experiments/prefix-cache-01/run_a3.sh。ON 脚本内部按“reset→B”“reset→A→B”“reset→A→B′”顺序执行;B′ 修改下标 17 的 token。运行结果与输入保存在experiments/prefix-cache-01/evidence/prefix_cache_20261011_02/:

  • on/inputs.json:固定的输入 IDs、共同前缀与修改位置。
  • on/05_WARM_B.json:B 输入 1038、命中 1024、输出[73670, 65770, 16872]。
  • on/08_PREFIX_CHANGED_Bprime.json:修改前缀后命中 0。
  • off/:B 与 B′ 各自关闭缓存的输出参照。
  • off.log、on.log、summary.json:运行日志与核对结果。

B.2 性能:固定输入与输出,再改变缓存状态

原 1K 性能脚本读取上一步保存的on/inputs.json,复制到新实验目录并命名为inputs.json。同目录还需run_prefix_cache_perf.py;完整环境采集与日志包装见该组run_a3.sh。

python3.12-urun_prefix_cache_perf.py\--model/workspace/models/Qwen3-0.6B--inputsinputs.json\--output-dir results --output-tokens64--pairs8--warmup-pairs3

在三个新目录中分别启动引擎,共三次。每对冷、热都先运行 A;冷组在 A 完成后再次清缓存,热组保留缓存。B 的计时从add_request前开始,到step()返回后取时间。A、reset、模型加载和分词均不计入 B。

长输入实验同样使用这份基础输入,另需run_length_sweep.py与perf_common.py:

python3.12-urun_length_sweep.py\--model/workspace/models/Qwen3-0.6B--inputsinputs.json\--output-dir run_01/results --run-index1\--max-model-len18432--output-tokens64--pairs8--warmup-pairs3

再分别使用run_02/results --run-index 2和run_03/results --run-index 3独立启动。脚本按 run-index 改变四种长度的顺序,每个长度内部交替冷、热顺序。每次都执行全部预定样本,没有只留下热缓存更快的请求。

原 1K 的三组结果在experiments/prefix-cache-perf-01/evidence/prefix_cache_perf_20261013_01/~03/;每组results/保存 A、B、reset、原始输出事件与 summary。长度扫描结果在experiments/prefix-cache-perf-length-01/evidence/prefix_cache_perf_length_20261013_01/;其下run_01~run_03/results/length_1024等目录按启动与长度分组。

B.3 不连接 NPU,也能复算保存的数据

解压实验附件,在附件根目录使用 Python 3.9 或以上运行以下标准库分析程序。输出目录需尚未存在,避免覆盖原统计:

python experiments/prefix-cache-01/validate_results.py\experiments/prefix-cache-01/evidence/prefix_cache_20261011_02 python experiments/prefix-cache-perf-01/analyze_results.py\--output-dir recomputed-1k python experiments/prefix-cache-perf-length-01/analyze_length_results.py\--output-dir recomputed-length

两份measurements.csv都保留预热与正式请求;分析以phase区分,只用正式样本计算正文统计。analysis.json保存按启动、长度和配对的完整结果。原始事件可用于重算 TTFT、首到末输出耗时、TPOT 与请求总耗时;这些事件不是 Scheduler 逐轮任务。

C. 第 7 章的详细统计

以下是原 2048 配置、每次 8 对正式请求的分组中位数,单位为 ms:

独立运行冷 TTFT热 TTFT冷首到末输出热首到末输出冷总耗时热总耗时
0138.2938.522157.082179.162195.372217.57
0238.5537.422109.982116.822150.132154.59
0338.5138.212136.762141.442175.072179.84

再对每一对计算“冷耗时 − 热耗时”;正数表示这一对热组更快:

独立运行TTFT 配对差中位数配对差最小~最大热 TTFT 更快对数总耗时配对差中位数热总耗时更快对数
01+0.16 ms−3.78~+2.57 ms4 / 8−6.02 ms3 / 8
02+0.74 ms−0.73~+3.32 ms7 / 8+15.55 ms6 / 8
03+0.14 ms−0.75~+0.84 ms4 / 8−4.86 ms2 / 8

“逐对相减后取中位数”与“两个组的中位数相减”不是同一统计量。因此,第二次多数配对的总耗时偏向热组,与第一张表的组中位数方向不同,并不矛盾。三次合看,未出现跨启动一致的整请求改善。

完整精度、范围和各对差值保存在附件的experiments/prefix-cache-perf-01/analysis.json;长度扫描的同类统计保存在experiments/prefix-cache-perf-length-01/analysis.json。原审计分别通过 1711 项与 87215 项检查;检查数表示数据校验,不是性能提升或统计显著性的证据。

长度实验正文中的“6.74 倍”是 16K 冷/热 TTFT组中位数之比;配对比值中位数约为 6.73,两个口径不能混用。各长度的 24 对来自 3 次引擎启动,不代表 24 个独立部署。

D. 固定版本的源码入口

正文第 5 章按本地阅读提交解释,以下链接固定到公开仓库的同一提交,不随主分支漂移。它们是静态阅读依据,不能替代未采集的 Scheduler 或设备 trace。

要找的问题本地阅读版本的固定源码
请求保存块哈希Request.update_block_hashes,request.py:278
完整块生成链式哈希get_request_block_hasher,kv_cache_utils.py:796;哈希组合式,第 648 行
将完整块登记到索引cache_full_blocks,block_pool.py:225;插入索引,第 638 行
允许查找与查找入口prefix_cache_lookup_enabled,第 230 行;get_computed_blocks,第 245 行
从第一个块连续查找find_longest_cache_hit,single_type_kv_cache_manager.py:771;实际查索引,block_pool.py:217
Scheduler 接收新请求命中scheduler.py:914
计算待算量与预算裁剪scheduler.py:1036;第 1076 行
申请块、写入任务单scheduler.py:1155;第 1257 行

计时与 Ascend 执行分支同时提供阅读版、运行版的对应入口:

位置本地阅读版本远程运行版本
提交请求llm_engine.py:223llm_engine.py:218
获取并整理结果llm_engine.py:312llm_engine.py:304
缓存命中路径取 KV、块表和上下文长度attention_v1.py:817attention_v1.py:1238
截取已准备的有效 queryattention_v1.py:855attention_v1.py:1294

有效 query 截取发生在调度决定待算输入之后;它自身不负责决定哪些 token 需要重新计算。静态代码能说明热请求仍使用历史上下文,但本实验没有 profiler,不能将热 TTFT 的增长全部归因于读取 KV。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询