# [功能] 适配 offload_group_size 和 offload_num_in_group 到 Ascend NPU

## vLLM Ascend 权重分组预取卸载参数适配与优化

**团队名称：** 乘风破浪的大学生

**目标版本：** vLLM Ascend v0.18.0

**项目分支：** `feature/offload-group-num-v018-optimized`

**优化提交：** `f0ab80524e2088763ab1e9859534f05912850194`

**结项日期：** 2026 年 7 月

---

## 摘要

本项目面向 vLLM Ascend v0.18.0，适配 vLLM 权重卸载配置中的 `offload_group_size` 与 `offload_num_in_group` 两个参数。实现按照 decoder layer 分组，在每组末尾选择固定数量的层，将权重保存在 CPU 侧，并通过 Ascend NPU 独立复制流、事件同步和静态缓冲槽位在执行前进行预取。该方案的目标不是无条件提升吞吐，而是在 NPU HBM 紧张时提供可配置、可复现的权重常驻空间与推理吞吐权衡。

项目完成了参数语义与边界校验、Ascend Prefetch Offloader、vLLM 官方 `auto/prefetch/uva` 后端契约兼容、CPU pinned storage 能力探测、shape/stride/dtype 保真、设备健康检查、性能矩阵、GSM8K 与 GPQA Diamond 全量精度验证，以及统一复现脚本。

在 `Qwen2.5-1.5B-Instruct` 的正式单卡测试中：

- `group_8_num_1` 节省约 0.2615 GB 权重存储空间，可用 KV cache 从 27.27 GiB 增至 27.53 GiB，吞吐为 678.85 tok/s，相对 baseline 下降 8.61%。
- `group_8_num_2` 节省约 0.5230 GB 权重存储空间，可用 KV cache 增至 27.79 GiB，吞吐为 383.49 tok/s，相对 baseline 下降 48.37%。
- GSM8K 三组均为 51/1319（3.8666%），GPQA Diamond 三组均为 0/198（0.0000%），相对 baseline 的精度差均为 0。

结果表明，两个参数在目标版本上能够正确工作并保持确定性推理结果，但更激进的卸载会增加 CPU-NPU 权重传输开销。实际使用时应根据模型是否能够装入 HBM、KV cache 需求和吞吐目标选择参数，而不能将 offload 简化为单一的性能开关。

**关键词：** vLLM Ascend；权重卸载；预取；NPU；HBM；GSM8K；GPQA

---

# 一、项目概述

## 1.1 项目背景

大模型推理的设备内存通常同时承载模型权重、KV cache、激活值和运行时工作区。随着模型规模、上下文长度和并发数增长，权重常驻空间会压缩 KV cache 容量，进而限制模型可加载规模或服务并发能力。

vLLM 提供 CPU weight offload 能力。`offload_group_size` 与 `offload_num_in_group` 用于控制以 decoder layer 为单位的分组卸载：

| 参数 | 含义 | 默认/禁用行为 |
| --- | --- | --- |
| `offload_group_size` | 每多少层组成一个 offload group | 0 表示不启用分组预取卸载 |
| `offload_num_in_group` | 每个 group 中选择多少个末尾层进行卸载 | 0 表示禁用，且不得大于 group size |

本项目认领这两个参数，并将其适配到 vLLM Ascend v0.18.0。目标基线扫描未发现 Ascend 专用实现，因此本项目在该基线上补齐参数解释、分层选择、权重驻留、NPU 预取和测试复现链路。

## 1.2 目标与范围

项目目标包括：

1. 在 vLLM Ascend v0.18.0 中正确读取和应用两个参数。
2. 保持参数为 0 时的原有行为，不破坏 vLLM 既有 UVA offloader。
3. 使用 Ascend NPU Stream/Event 实现可复用的权重预取路径。
4. 为两个参数分别提供边界、选择规则和 runner 集成测试。
5. 使用 GSM8K 和 GPQA Diamond 完成三组参数矩阵的全量精度验证。
6. 提供性能、精度和统一复现脚本，确保环境、命令和产物可追踪。

本项目不把以下内容作为已完成范围：

- 多卡和分布式推理下的物理设备映射闭环。
- server streaming 场景下的真实 TTFT 测量。
- 长上下文、高并发和 ACL graph 的系统性能结论。
- 对所有模型、提示词或数据集作无精度损失的普遍保证。

## 1.3 版本背景与主仓实现情况

本项目的竞赛目标版本固定为 vLLM Ascend v0.18.0，源码基线提交为：

```text
72dc68973bd7e6ceef9a122de316a7ee9c9a84aa
```

基线扫描未发现 `offload_group_size` 与 `offload_num_in_group` 的 Ascend 专用执行路径，因此竞赛规则中“若主仓已有实现，须在性能或精度至少一个维度取得可量化提升”的附加要求不适用于本目标基线。

前期版本调研显示，后续 vLLM Ascend 版本已逐步出现官方 NPU Prefetch Offloader，其中首个包含相关实现的发布序列为 v0.21.0rc1。由于本项目必须继续基于 v0.18.0，工作重点是将参数语义、后端兼容和复现体系稳定适配回目标版本，而不是直接依赖后续主仓实现。

## 1.4 决赛阶段工作定位

当前核心 offloader 文件与初赛最终提交包文本等价，因此本结项书不把核心算法表述为“决赛重新实现”或“相对初赛新增提速”。决赛阶段的实质工作集中在：

- 固定并验证 vLLM Ascend v0.18.0 与 CANN 8.5.1 运行环境。
- 对齐官方 `offload_backend=auto/prefetch/uva` 契约，避免非标准环境变量切换。
- 完善 pinned storage、布局保真、设备采样和健康门禁等工程细节。
- 建立三组参数 case 的正式性能和精度矩阵。
- 形成从安装、测试、性能、精度到结果校验的一体化复现入口。
- 明确数据收益、吞吐代价和证据限制，避免只报告“运行成功”。

---

# 二、参数理解与技术难点

## 2.1 参数选择语义

对 layer index 为 `i` 的 decoder layer，选择规则为：

```text
i % offload_group_size >= offload_group_size - offload_num_in_group
```

也就是说，每个 group 选择末尾连续的 `offload_num_in_group` 层。以 24 层模型为例：

| Case | group size | num in group | 选中层 |
| --- | ---: | ---: | --- |
| `baseline_0_1` | 0 | 1 | 无 |
| `group_8_num_1` | 8 | 1 | 7、15、23 |
| `group_8_num_2` | 8 | 2 | 6、7、14、15、22、23 |

这种规则是确定性的固定选择，不是根据运行时负载自动搜索最优层。

## 2.2 参数边界

实现需要保证：

- 两个参数必须为非负整数。
- `offload_group_size=0` 或 `offload_num_in_group=0` 时禁用分组预取卸载。
- `offload_num_in_group` 不得大于 `offload_group_size`。
- 参数禁用时，不应覆盖 vLLM 父类已经构造的 offloader。
- 非法后端名称应尽早抛出明确错误。

需要特别说明：配置层只接受 `auto`、`prefetch` 和 `uva`。仓库中保留了同步 offloader 作为内部参考和直接测试对象，但用户不能通过 `offload_backend=sync` 选择它。

## 2.3 模型层命名与选择

参数语义面向 decoder layers，但运行时模块由完整模块名标识。实现需要稳定提取 layer index，并确保：

- 非 decoder 模块不会被误选。
- 同一层内多个子模块的 wrap 行为一致。
- 分组选择能在模型加载完成前确定。
- 测试可直接验证给定层数下的精确选择集合。

## 2.4 CPU-NPU 权重生命周期

选中层的权重不能在每次前向时临时创建，否则会引入额外分配、碎片和同步开销。实现需要管理三个阶段：

1. 模型加载后，将选中参数捕获到 CPU storage。
2. 初始化固定数量的 NPU static buffer slot。
3. 前向执行前将当前层权重预取到 slot，执行后滚动复用 slot。

CPU storage 与 NPU static buffer 必须保持原始 `shape`、`stride()` 和 `dtype`。如果只按元素数量分配连续 buffer，非连续布局或不同 dtype 可能出现错误复用。

## 2.5 异步复制与正确性

预取并不等于“完全无等待”。NPU copy stream 可以与部分计算重叠，但在目标层执行前仍需等待对应 event。正确性要求：

- copy 在独立 NPU stream 上提交。
- copy 完成后记录 event。
- 当前计算 stream 在使用权重前等待 event。
- 前向结束后启动未来层预取。
- 推理结束或 teardown 时等待 copy stream，避免缓冲被提前释放。

因此，方案的实际收益依赖可重叠计算量、PCIe/互联带宽、层大小和预取距离。

## 2.6 HBM 指标解释

权重卸载释放的空间可能被 vLLM 重新分配给 KV cache。生成结束后直接比较 `npu-smi` 已用 HBM，可能看不到与权重节省相同的下降。项目采用两个独立口径：

- 模型加载日志：记录权重 storage 节省。
- vLLM KV cache 规划日志：记录可用 KV cache 容量。

这比单纯报告进程结束时的设备显存差值更符合 vLLM 的内存分配行为。

---

# 三、技术方案

## 3.1 总体架构

```text
OffloadConfig
    |
    | offload_group_size / offload_num_in_group / offload_backend
    v
model_runner_v1.py
    |
    +-- uva 或禁用：保留父类 offloader
    |
    +-- auto/prefetch + 有效参数
            |
            v
AscendPrefetchOffloader
    |
    +-- layer selection
    +-- CPU weight storage
    +-- static NPU buffer pool
    +-- NPU copy stream + events
    +-- forward hooks / rolling prefetch
```

## 3.2 模块划分

| 模块 | 职责 |
| --- | --- |
| `vllm_ascend/model_executor/offloader/selection.py` | 校验参数、解析 layer index、生成选中层集合 |
| `vllm_ascend/model_executor/offloader/prefetch.py` | CPU storage、静态 NPU buffer、Stream/Event、预取 hook |
| `vllm_ascend/model_executor/offloader/sync.py` | 同步参考路径和直接测试对象 |
| `vllm_ascend/model_executor/offloader/__init__.py` | 公共接口导出 |
| `vllm_ascend/worker/model_runner_v1.py` | offloader 工厂、runner 注册、加载后初始化 |

## 3.3 后端选择兼容

工厂行为如下：

| `offload_backend` | 参数状态 | 行为 |
| --- | --- | --- |
| `uva` | 任意 | 保留父类 vLLM UVA offloader |
| `auto` | group 或 num 为 0 | 保留父类行为 |
| `auto` | group 与 num 均有效 | 创建 Ascend Prefetch Offloader |
| `prefetch` | 参数有效 | 创建 Ascend Prefetch Offloader |
| 其他值 | 任意 | 抛出不支持错误 |

该兼容方式避免了两个风险：

- 在不启用参数时错误替换父类 offloader。
- 引入未文档化环境变量，造成配置入口与 vLLM 官方契约分离。

## 3.4 CPU storage 与静态缓冲

Prefetch 路径通过以下逻辑创建 CPU storage：

```python
torch.empty_strided(
    tensor.shape,
    tensor.stride(),
    dtype=tensor.dtype,
    device="cpu",
    pin_memory=is_pin_memory_available(),
)
```

随后复制模型加载后已经处理完成的权重。NPU buffer key 包含参数名、shape、stride 和 dtype，防止不同权重错误共享同一 slot。

此处只能准确表述为“平台报告支持时使用 pinned CPU storage”。不能承诺所有平台始终启用 pin memory，也不能仅凭该分配方式推导出完全非阻塞 DMA。

## 3.5 Stream/Event 预取流程

对当前目标模块，执行流程为：

1. 在 copy stream 上将 CPU 权重复制到对应 static buffer。
2. copy 完成后记录 NPU event。
3. 当前计算 stream 在模块前向前等待该 event。
4. 将 buffer 中的权重临时绑定到目标参数。
5. 前向完成后，根据预取窗口启动后续模块的 copy。
6. slot 在生命周期结束后回收，用于后续层。

该流程减少了运行期动态 buffer 分配，并为计算与传输重叠提供基础。由于存在显式 event wait，性能结果必须由实际 benchmark 给出，不能仅根据结构推断“零开销”。

## 3.6 设备映射和健康门禁

性能与精度脚本默认设置：

```bash
export ASCEND_RT_VISIBLE_DEVICES=0
```

脚本通过 `npu-smi info -m` 获取物理 NPU index，并将同一 index 用于健康检查和 HBM 采样。正式运行前执行：

```bash
bash scripts/check_npu_health.sh
```

检查未返回 `Health Status : OK` 时以状态码 42 终止。

当前探测实现取映射输出中的第一张 Ascend 卡。在多卡、卡重排或 `ASCEND_RT_VISIBLE_DEVICES` 指向非首卡时，应显式设置：

```bash
export ASCEND_RT_VISIBLE_DEVICES=0
export NPU_INDEX=0
export NPU_CHIP_INDEX=0
```

并将三个值写入复现记录。

## 3.7 异常与降级策略

- 参数非法：抛出明确 `ValueError`。
- 后端非法：在 offloader 工厂阶段拒绝。
- NPU 健康异常：正式脚本 fail-fast。
- pin memory 不可用：使用普通 CPU storage，不中断推理。
- 参数禁用：保留 vLLM 父类 offloader，不改变默认推理路径。
- 可选 `msserviceprofiler` 缺失：记录非致命插件加载信息，不影响 Ascend 平台激活和推理。

---

# 四、实际交付

## 4.1 代码与测试

| 类型 | 路径 |
| --- | --- |
| 参数选择 | `vllm_ascend/model_executor/offloader/selection.py` |
| Prefetch Offloader | `vllm_ascend/model_executor/offloader/prefetch.py` |
| 同步参考实现 | `vllm_ascend/model_executor/offloader/sync.py` |
| runner 集成 | `vllm_ascend/worker/model_runner_v1.py` |
| 参数单测 | `tests/model_executor/offloader/test_offload_group_size_param.py` |
| 参数单测 | `tests/model_executor/offloader/test_offload_num_in_group_param.py` |
| 选择规则 | `tests/model_executor/offloader/test_selection.py` |
| Prefetch 行为 | `tests/model_executor/offloader/test_prefetch.py` |
| runner 集成 | `tests/model_executor/offloader/test_runner_integration.py` |
| 精度复现结构 | `tests/model_executor/offloader/test_accuracy_repro.py` |
| 脚本验收 | `tests/model_executor/offloader/test_acceptance_scripts.py` |

## 4.2 性能与精度脚本

| 脚本 | 作用 |
| --- | --- |
| `scripts/run_benchmark_all.sh` | 运行三组正式性能 case |
| `scripts/bench_one.py` | 执行单次推理并采集吞吐、延迟和 HBM 证据 |
| `scripts/run_accuracy_gsm8k_gpqa.sh` | 运行 GSM8K 与 GPQA 三组精度矩阵 |
| `scripts/accuracy_gsm8k_gpqa.py` | 数据加载、推理、评分和 example JSONL 输出 |
| `scripts/verify_accuracy_matrix.py` | 校验样本数、参数、数据集哈希和精度下降 |
| `scripts/run_reproduce_all.sh` | 性能后精度的一键复现入口 |
| `scripts/check_npu_health.sh` | 正式测试前 NPU 健康门禁 |
| `scripts/detect_npu_index.py` | 获取物理 NPU index |
| `scripts/install_v018_runtime_compat.sh` | 安装并重建 v0.18.0 兼容运行环境 |

## 4.3 文档交付

| 文档 | 内容 |
| --- | --- |
| `docs/v018-deployment-and-reproduction.md` | 环境部署、性能、精度和统一复现 |
| `docs/v018-test-evidence.md` | 正式测试结果及健康状态 |
| `docs/offload-group-size/` | 参数技术方案、单测计划和测试报告 |
| `docs/offload-num-in-group/` | 参数技术方案、单测计划和测试报告 |
| `docs/finals/` | 决赛结项书和答辩材料 |

---

# 五、测试结论

## 5.1 测试环境

| 组件 | 版本 |
| --- | --- |
| vLLM | `0.18.0+empty` |
| vLLM Ascend 包 | `0.1.dev1+g72dc68973.d20260720` |
| vLLM Ascend 源码基线 | `72dc68973bd7e6ceef9a122de316a7ee9c9a84aa` |
| CANN | `8.5.1` |
| Python | `3.11` |
| torch | `2.9.0+cpu` |
| torch-npu | `2.9.0` |
| triton-ascend | `3.2.0.dev20260322` |
| 模型 | `Qwen2.5-1.5B-Instruct` |

## 5.2 功能测试

脚本和复现相关 unittest：

```text
Ran 35 tests in 0.341s
OK
```

完整 offloader suite：

```text
69 passed, 1 warning, 21 subtests passed in 11.05s
```

两组数字属于不同测试范围，不相加。warning 为上游 `pkg_resources` 弃用提示，不影响测试通过。

## 5.3 性能测试

正式配置：

- 三个 case，每个 case 3 次独立模型加载。
- 每次 1 个 warmup round、3 个 measured rounds。
- 每轮 8 prompts。
- 输入 128 tokens，最大输出 64 tokens。
- 共 9 条原始运行记录，表中按 case 取中位数。

| Case | 选中层 | 权重存储节省 | 可用 KV cache | 输出吞吐 | 相对 baseline | P50 延迟 |
| --- | --- | ---: | ---: | ---: | ---: | ---: |
| `baseline_0_1` | 无 | 0.0000 GB | 27.27 GiB | 742.77 tok/s | 0.00% | 0.6927 s |
| `group_8_num_1` | 7、15、23 | 0.2615 GB | 27.53 GiB | 678.85 tok/s | -8.61% | 0.7501 s |
| `group_8_num_2` | 6、7、14、15、22、23 | 0.5230 GB | 27.79 GiB | 383.49 tok/s | -48.37% | 1.3351 s |

结论：

1. 两个参数能够按预期增加被卸载层数和权重 storage 节省。
2. 新释放的空间被 vLLM 用于增加 KV cache 可用容量。
3. `group_8_num_1` 是本次固定负载下较温和的容量/吞吐折中。
4. `group_8_num_2` 获得约两倍权重 storage 节省，但传输开销显著增加。
5. 参数适合 HBM 容量优先场景，不适合作为纯吞吐优化开关。

## 5.4 GSM8K 和 GPQA 精度测试

正式精度设置：

```text
ACCURACY_LIMIT=0
temperature=0
seed=0
MAX_ACCURACY_DROP=0
```

| 数据集 | 样本数 | baseline | `group_8_num_1` | `group_8_num_2` | 精度变化 |
| --- | ---: | ---: | ---: | ---: | ---: |
| GSM8K test | 1319 | 51/1319（3.8666%） | 51/1319（3.8666%） | 51/1319（3.8666%） | 0 |
| GPQA Diamond | 198 | 0/198（0.0000%） | 0/198（0.0000%） | 0/198（0.0000%） | 0 |

验证汇总返回：

```text
all_passed: true
```

材料记录的 example JSONL SHA-256：

```text
GSM8K:
e6c13ad281308e2dc103279f6820b9212a9895ecb80ec5e705be4697deb2eead

GPQA:
baa5a967b1f4c4d96f6be810f7176019b037617141436255959f2b7b046c2623
```

三组 case 在每个数据集上记录了相同哈希，说明保存的预测输出逐字节一致。当前 `verify_accuracy_matrix.py` 不自动复算 example JSONL 哈希，因此正式复现时仍应保留原始 JSONL，并通过 `sha256sum` 或等价工具再次核验。

GPQA 0/198 是 `Qwen2.5-1.5B-Instruct` 在本次零样本提示和评分方式下的 baseline 表现。该结果不表示模型任务精度高，只证明两个 offload case 没有引入额外精度下降。

## 5.5 精度验收标准

两个参数 case 通过精度验证必须同时满足：

1. 数据集名称、行数和 SHA-256 与 baseline 一致。
2. 记录的 `offload_group_size` 与 `offload_num_in_group` 与 case 定义一致。
3. 结果中的 `correct/total` 与 accuracy 计算一致。
4. 相对 baseline 的 accuracy drop 不大于 0。
5. 保存的 example JSONL 哈希与 baseline 一致。

## 5.6 证据限制

当前仓库未包含文档所述 `materials/results/v018-*-formal-20260721` 原始归档。因此，本地克隆可以审计脚本、测试结构和结果文档，但不能在无 NPU 环境下独立重算九次性能原始记录、六组精度 JSONL、哈希和设备健康日志。

正式评审复现应以一键脚本重新生成结果，或将以下远端归档制作成不可变提交附件：

```text
/data/v018-performance-formal-20260721
/data/v018-accuracy-formal-20260721
```

---

# 六、AI 工具使用经验

## 6.1 参与环节

AI 工具用于：

- 阅读 vLLM、vLLM Ascend 的参数和 offloader 调用链。
- 梳理 v0.18.0 与后续版本的实现差异。
- 辅助设计参数边界、后端选择和 buffer 生命周期测试。
- 分析远端依赖冲突、CANN 自定义算子和设备映射问题。
- 生成性能、精度和统一复现脚本初稿。
- 对测试结果、文档数字和演示材料进行交叉审计。

## 6.2 有效方法

1. **先固定基线再改动。** 明确源码提交、运行时包和 CANN 版本，避免把环境漂移误判为代码问题。
2. **先跑最小验证再扩展。** 先通过参数选择和 mock 单测，再进行真实 NPU 冒烟，最后进行正式性能与精度矩阵。
3. **让 AI 输出可证伪假设。** 对性能、内存和精度结论要求给出对应日志字段、脚本和判定条件。
4. **独立审计数字。** 将代码实现和测试证据交给不同审计流程，重点检查夸大表述、旧数据混用和无法复算的结果。
5. **保留人工判断。** 参数是否值得启用取决于容量目标和吞吐预算，不能由 AI 根据单一指标自动下结论。

## 6.3 典型问题与改进

- AI 容易把“异步 copy”写成“零等待”，实际代码仍有 event wait。
- AI 容易把 HBM 用量差等同于权重节省，忽略 vLLM 会扩大 KV cache。
- AI 容易把 GPQA 的零下降写成“精度优秀”，忽略 baseline 本身为 0。
- AI 容易混用 7 月 5 日旧 benchmark 与 7 月 21 日正式中位数。

解决方式是将结论绑定到具体环境、case、数据源和限制条件，并对每个量化数字进行双重核对。

---

# 七、限制与后续工作

## 7.1 当前限制

1. 性能验证集中于单卡 eager/Python LLM API。
2. 输入长度、输出长度和 prompt 数固定，未覆盖长上下文和高并发。
3. 设备 index 自动探测只取首个 Ascend 映射，多卡需要显式配置。
4. 健康检查可通过 `SKIP_NPU_HEALTH_CHECK=1` 跳过，正式复现必须记录该变量未设置。
5. example JSONL 哈希尚未被 `verify_accuracy_matrix.py` 自动强制校验。
6. 正式原始结果尚未进入当前 Git 仓库。
7. 同步 offloader 不是 `offload_backend` 可选择的正式用户后端。

## 7.2 后续优化方向

### 方向一：完善证据链

- 将正式原始结果归档为版本化附件。
- 在 `verify_accuracy_matrix.py` 中复算并校验 example JSONL SHA-256。
- 在 `reproduction-manifest.json` 中写入设备映射、健康输出、数据集哈希和 Git dirty 状态。

### 方向二：多卡设备映射

- 解析 `ASCEND_RT_VISIBLE_DEVICES` 与 `npu-smi info -m` 的对应关系。
- 对每个逻辑 rank 记录物理 NPU/chip index。
- 增加多卡和卡重排测试。

### 方向三：性能覆盖

- 增加长上下文、多并发和不同 batch size。
- 使用 OpenAI-compatible server streaming 测量真实 TTFT、TPOT 和端到端延迟。
- 验证 ACL graph、tensor parallel 和 pipeline parallel。
- 扩展至更大模型，验证在“baseline 无法装入、offload 可以装入”场景中的容量价值。

### 方向四：参数自动推荐

根据模型层大小、可用 HBM、目标 KV cache 和链路带宽，建立离线估算器，输出候选 `group_size/num_in_group` 组合。推荐器应以“满足容量约束后最大化吞吐”为目标，而不是简单选择卸载层数最多的组合。

## 7.3 最终结论

本项目在 vLLM Ascend v0.18.0 上完成了 `offload_group_size` 与 `offload_num_in_group` 的参数适配、Ascend 分组预取卸载和完整测试复现链。

两个参数均通过 GSM8K 和 GPQA Diamond 全量矩阵的零精度下降验证；正式性能结果量化了权重 storage、KV cache 和吞吐之间的权衡。最温和的 `group_8_num_1` 组合节省约 0.2615 GB 权重 storage，吞吐下降 8.61%；更激进的 `group_8_num_2` 节省约 0.5230 GB，但吞吐下降 48.37%。

因此，本项目的主要价值是把“是否卸载、每组卸载多少层”从不可控行为转化为可配置、可测试、可复现的工程能力，并明确给出适用边界：在 HBM 容量成为主要约束时使用，在吞吐优先且模型可直接装入时保持 baseline。

---

# 附录 A：完整复现

## A.1 环境安装

首先安装 CANN 8.5.1 toolkit、910B operator package 和 NNAL，然后执行：

```bash
cd /data/vllm-ascend-v0.18.0
bash scripts/install_v018_runtime_compat.sh
```

## A.2 设备配置和健康检查

```bash
export ASCEND_RT_VISIBLE_DEVICES=0
export NPU_INDEX=0
export NPU_CHIP_INDEX=0
unset SKIP_NPU_HEALTH_CHECK
bash scripts/check_npu_health.sh
```

预期包含：

```text
Health Status : OK
Error Code : NA
Error Information : NA
```

## A.3 功能测试

```bash
cd /data/vllm-ascend-v0.18.0
python -m pytest tests/model_executor/offloader -q
```

正式记录：

```text
69 passed, 1 warning, 21 subtests passed in 11.05s
```

## A.4 性能复现

```bash
cd /data/vllm-ascend-v0.18.0
MODEL_PATH=/data/models/Qwen2.5-1.5B-Instruct \
RESULTS_DIR=/data/v018-performance-results \
REPEATS=3 \
WARMUP_ROUNDS=1 \
MEASURED_ROUNDS=3 \
PROMPT_COUNT=8 \
INPUT_TOKENS=128 \
MAX_TOKENS=64 \
MAX_MODEL_LEN=512 \
bash scripts/run_benchmark_all.sh
```

产物：

```text
performance-runs.jsonl
performance-summary.json
performance-summary.csv
performance-summary.md
performance-run.log
```

## A.5 精度复现

```bash
cd /data/vllm-ascend-v0.18.0
MODEL_PATH=/data/models/Qwen2.5-1.5B-Instruct \
DATA_DIR=/data/accuracy-gsm8k-gpqa \
RESULTS_DIR=/data/v018-accuracy-results \
ACCURACY_LIMIT=0 \
MAX_ACCURACY_DROP=0 \
bash scripts/run_accuracy_gsm8k_gpqa.sh
```

`ACCURACY_LIMIT=2` 仅用于管线冒烟，不得作为提交精度证据。

## A.6 一键复现

```bash
cd /data/vllm-ascend-v0.18.0
MODEL_PATH=/data/models/Qwen2.5-1.5B-Instruct \
DATA_DIR=/data/accuracy-gsm8k-gpqa \
REPRO_RESULTS_DIR=/data/v018-reproduction-results \
bash scripts/run_reproduce_all.sh
```

统一结果目录：

```text
/data/v018-reproduction-results/
  reproduction-manifest.json
  performance/
    performance-runs.jsonl
    performance-summary.json
    performance-summary.csv
    performance-summary.md
    performance-run.log
  accuracy/
    baseline_0_1/
    group_8_num_1/
    group_8_num_2/
    accuracy-summary.json
    accuracy-summary.csv
    accuracy-summary.md
```

## A.7 输出哈希复核

```bash
sha256sum \
  /data/v018-accuracy-results/baseline_0_1/gsm8k-examples.jsonl \
  /data/v018-accuracy-results/group_8_num_1/gsm8k-examples.jsonl \
  /data/v018-accuracy-results/group_8_num_2/gsm8k-examples.jsonl

sha256sum \
  /data/v018-accuracy-results/baseline_0_1/gpqa-examples.jsonl \
  /data/v018-accuracy-results/group_8_num_1/gpqa-examples.jsonl \
  /data/v018-accuracy-results/group_8_num_2/gpqa-examples.jsonl
```

每组数据集的三个哈希应完全相同。

---

# 附录 B：答辩参数建议

| 场景 | 建议 |
| --- | --- |
| 模型和 KV cache 均可直接装入，吞吐优先 | 保持 `baseline_0_1` |
| 需要温和释放权重空间，允许约 10% 吞吐代价 | 优先评估 `group_8_num_1` |
| 容量优先，baseline 无法满足 HBM 约束 | 评估 `group_8_num_2` 或其他组合，并重新压测 |
| 多卡、长上下文或高并发 | 不直接套用本报告数字，必须在目标负载复现 |
