已合并
fix qwen3_8b chapter 5&6 issues #632
fix qwen3_8b chapter 5&6 issues #632
已合并
liuyufan创建于 8月10日
3 个文件变更+38-6
@@ -144,7 +144,8 @@
144 "source": [144 "source": [
145 "from inference_scripts.recipe_workflow import resolve_model_path\n",145 "from inference_scripts.recipe_workflow import resolve_model_path\n",
146 "#下载非量化模型权重\n",146 "#下载非量化模型权重\n",
147- "resolved_model_path, model_source = resolve_model_path('Qwen/Qwen3-8B', quiet_model_io=False)"147+ "MODEL_ID = os.environ.get('QWEN3_8B_MODEL_PATH') or 'Qwen/Qwen3-8B'\n",
148+ "resolved_model_path, model_source = resolve_model_path(str(MODEL_ID), quiet_model_io=False)"
148 ]149 ]
149 },150 },
150 {151 {
@@ -524,7 +525,7 @@
524 "\n",525 "\n",
525 "- **Shape 随推理阶段和模型层级变化**:Prefill 阶段 M 维度较大(如 50),Decode 阶段 M=1;K 和 N 取值取决于具体层的隐藏维度与投影维度。\n",526 "- **Shape 随推理阶段和模型层级变化**:Prefill 阶段 M 维度较大(如 50),Decode 阶段 M=1;K 和 N 取值取决于具体层的隐藏维度与投影维度。\n",
526 "\n",527 "\n",
527- "现在让我们模拟一个实际的需求分析场景:假设我们正在部署一个 W8A8 量化的大语言模型,推理过程中需要调用 INT8 量化矩阵乘法算子。通过 Profiling 分析,我们发现该模型对底层算子的调用规格恰好如上表所示——即需要一种能同时支持\" INT8 输出\"和\"perTokenScale 反量化输出\"两种模式的量化 Matmul 算子。\n",528+ "现在让我们模拟一个实际的需求分析场景:假设我们正在部署一个 W8A8 量化的大语言模型,推理过程中需要调用 INT8 量化矩阵乘法算子。通过 Profiling 分析,我们发现该模型对底层算子的调用规格恰好如上表所示——即需要一种能同时支持\"INT32 输出\"和\"perTokenScale 反量化输出\"两种模式的量化 Matmul 算子。\n",
528 "\n",529 "\n",
529 "然而,现有框架中可能没有完全匹配该规格的算子实现,或者我们需要针对特定硬件平台进行深度优化。此时,就需要开发一个自定义算子 `QmmCustom` 来满足这一需求。从 Profiling 数据中归纳出的输入输出规格,自然就成为 `QmmCustom` 的原型定义:\n",530 "然而,现有框架中可能没有完全匹配该规格的算子实现,或者我们需要针对特定硬件平台进行深度优化。此时,就需要开发一个自定义算子 `QmmCustom` 来满足这一需求。从 Profiling 数据中归纳出的输入输出规格,自然就成为 `QmmCustom` 的原型定义:\n",
530 "\n",531 "\n",
@@ -11,11 +11,11 @@
11 "\n",11 "\n",
12 "实践的环境准备、提交方式可参考[启航营课程实践说明](https://gitcode.com/cann/cann-launch-camp/blob/master/2026/University/HIT/First-session/README.md)。\n",12 "实践的环境准备、提交方式可参考[启航营课程实践说明](https://gitcode.com/cann/cann-launch-camp/blob/master/2026/University/HIT/First-session/README.md)。\n",
13 "\n",13 "\n",
14- "### 本章定位\n",14+ "## 本章定位\n",
15 "\n",15 "\n",
16 "本章将开发一个自定义的量化 matmul 算子 `QmmCustom`,通过 A8W8 量化(Activation INT8 + Weight INT8)减少计算量和内存占用,从而提升推理性能。这是本次启航营中综合性最强的一章——涵盖了从算子概念理解、Tiling 设计、Kernel 实现到算子编译、接入网络与功能性能测试的全链路。\n",16 "本章将开发一个自定义的量化 matmul 算子 `QmmCustom`,通过 A8W8 量化(Activation INT8 + Weight INT8)减少计算量和内存占用,从而提升推理性能。这是本次启航营中综合性最强的一章——涵盖了从算子概念理解、Tiling 设计、Kernel 实现到算子编译、接入网络与功能性能测试的全链路。\n",
17 "\n",17 "\n",
18- "### 通过实践达成的学习目标\n",18+ "## 通过实践达成的学习目标\n",
19 "\n",19 "\n",
20 "- **理解量化推理原理**:掌握 A8W8 量化方案(INT8 激活 + INT8 权重)的数学原理与 Scale 反量化机制,理解 perChannelScale 与 perTokenScale 的作用。\n",20 "- **理解量化推理原理**:掌握 A8W8 量化方案(INT8 激活 + INT8 权重)的数学原理与 Scale 反量化机制,理解 perChannelScale 与 perTokenScale 的作用。\n",
21 "- **设计 Tiling 数据结构与函数**:根据算子原型定义自行设计 TilingData 结构体,实现多核分块的 Tiling 函数,理解 Cube 计算单元的分块策略。\n",21 "- **设计 Tiling 数据结构与函数**:根据算子原型定义自行设计 TilingData 结构体,实现多核分块的 Tiling 函数,理解 Cube 计算单元的分块策略。\n",
@@ -23,7 +23,7 @@
23 "- **完成算子编译与 Torch 接入**:编译自定义算子并通过 Torch 接口接入,打通“算子开发 → 框架调用”的链路。\n",23 "- **完成算子编译与 Torch 接入**:编译自定义算子并通过 Torch 接口接入,打通“算子开发 → 框架调用”的链路。\n",
24 "- **测试算子功能与性能,尝试优化迭代**:验证自定义算子的精度正确性,测试单算子与网络性能,并根据测试结果对 Tiling 或 Kernel 进行优化迭代。\n",24 "- **测试算子功能与性能,尝试优化迭代**:验证自定义算子的精度正确性,测试单算子与网络性能,并根据测试结果对 Tiling 或 Kernel 进行优化迭代。\n",
25 "\n",25 "\n",
26- "### 本章大纲\n",26+ "## 本章大纲\n",
27 "\n",27 "\n",
28 "- 环境准备\n",28 "- 环境准备\n",
29 "- A8W8 量化 matmul 算子概念\n",29 "- A8W8 量化 matmul 算子概念\n",
@@ -154,6 +154,8 @@
154 "- **W(Weight)**:将权重从 BF16/FP16 量化为 **INT8**\n",154 "- **W(Weight)**:将权重从 BF16/FP16 量化为 **INT8**\n",
155 "- **反量化**:计算结果 `INT8 × INT8 → INT32` 后,通过 Scale 反量化回浮点精度\n",155 "- **反量化**:计算结果 `INT8 × INT8 → INT32` 后,通过 Scale 反量化回浮点精度\n",
156 "\n",156 "\n",
157+ "> **术语说明**:A8W8 与第 5 章使用的 W8A8 是同一种 INT8 激活 + INT8 权重量化方案的不同写法,本章沿用 A8W8 命名。仓库中 YAML 配置文件名(如 `qwen3_8b_a8w8_1tp.yaml`)和类名(`CompressedTensorsW8A8Int8LinearMethod`)也分别使用了这两种写法。\n",
158+ "\n",
157 "### 2.2 算子规格\n",159 "### 2.2 算子规格\n",
158 "\n",160 "\n",
159 "在上一章中,通过分析量化模型的profiling,归纳出了自定义算子的输入输出规格:\n",161 "在上一章中,通过分析量化模型的profiling,归纳出了自定义算子的输入输出规格:\n",
@@ -994,6 +996,10 @@
994 "W8A8_FILE = RECIPE_ROOT / 'module/quantization/compressed_tensors/compressed_tensors_w8a8_int8.py'\n",996 "W8A8_FILE = RECIPE_ROOT / 'module/quantization/compressed_tensors/compressed_tensors_w8a8_int8.py'\n",
995 "print('[替换] 目标文件:', W8A8_FILE)\n",997 "print('[替换] 目标文件:', W8A8_FILE)\n",
996 "\n",998 "\n",
999+ "# 备份原始内容,仅在首次执行时保存,避免重复执行时覆盖为已修改的代码\n",
1000+ "if 'W8A8_ORIGINAL_CODE' not in dir():\n",
1001+ " W8A8_ORIGINAL_CODE = W8A8_FILE.read_text(encoding='utf-8')\n",
1002+ "\n",
997 "ct_code = W8A8_FILE.read_text(encoding='utf-8')\n",1003 "ct_code = W8A8_FILE.read_text(encoding='utf-8')\n",
998 "_lib_path = str(QMM_CUSTOM_DIR / \"build/libascendc_ops.so\")\n",1004 "_lib_path = str(QMM_CUSTOM_DIR / \"build/libascendc_ops.so\")\n",
999 "_load_lib_stmt = 'torch.ops.load_library(r\"' + _lib_path + '\")'\n",1005 "_load_lib_stmt = 'torch.ops.load_library(r\"' + _lib_path + '\")'\n",
@@ -1198,6 +1204,28 @@
1198 "display(combined.style.set_caption('QmmCustom 各 Shape 平均耗时 (us)'))"1204 "display(combined.style.set_caption('QmmCustom 各 Shape 平均耗时 (us)'))"
1199 ]1205 ]
1200 },1206 },
1207+ {
1208+ "cell_type": "markdown",
1209+ "id": "restore_w8a8_md",
1210+ "metadata": {},
1211+ "source": [
1212+ "### 7.4 恢复原始 W8A8 源码\n",
1213+ "\n",
1214+ "自定义算子推理与 Profiling 已完成,下方单元格会从备份恢复 `compressed_tensors_w8a8_int8.py` 原始内容,避免修改后的源码污染 baseline 对比或产生 git 工作区变更。"
1215+ ]
1216+ },
1217+ {
1218+ "cell_type": "code",
1219+ "execution_count": null,
1220+ "id": "restore_w8a8_code",
1221+ "metadata": {},
1222+ "outputs": [],
1223+ "source": [
1224+ "W8A8_FILE = RECIPE_ROOT / 'module/quantization/compressed_tensors/compressed_tensors_w8a8_int8.py'\n",
1225+ "W8A8_FILE.write_text(W8A8_ORIGINAL_CODE, encoding='utf-8')\n",
1226+ "print('[恢复] 已恢复原始 W8A8 源码,baseline 对比不受污染')"
1227+ ]
1228+ },
1201 {1229 {
1202 "cell_type": "markdown",1230 "cell_type": "markdown",
1203 "id": "9eca2376",1231 "id": "9eca2376",
@@ -1,5 +1,5 @@
1# Qwen3-8B 推理优化实践1# Qwen3-8B 推理优化实践
2-本教程以 `Qwen3-8B` 为例,展示如何在昇腾 NPU 上使用 cann-recipes-infer 离线推理框架完成 Baseline 推理、Profiling 分析,验证 Dense RMSNorm NPU 融合路径的性能收益。课程主流程采用 recipes 的典型用法:查看并修改 `models/qwen/config/` 下的 YAML 配置,通过 `executor/scripts/infer.sh` 拉起离线推理,再从 `res/` 与 `prof/` 目录读取日志和性能产物。2+本教程以 `Qwen3-8B` 为例,展示如何在昇腾 NPU 上使用 cann-recipes-infer 离线推理框架完成 Baseline 推理、Profiling 分析,验证 Dense RMSNorm NPU 融合路径的性能收益,并通过 AMCT 工具完成 W8A8 量化导出与推理,以及自定义量化 matmul 算子的开发与接入。课程主流程采用 recipes 的典型用法:查看并修改 `models/qwen/config/` 下的 YAML 配置,通过 `executor/scripts/infer.sh` 拉起离线推理,再从 `res/` 与 `prof/` 目录读取日志和性能产物。
3 3 
4教程包含以下内容:4教程包含以下内容:
5- Notebooks:包含环境准备、YAML 修改、`infer.sh` 启动、Profiling 分析和 Dense RMSNorm NPU 融合路径 A/B 验证步骤,可在 GitCode 提供的轻量级 Notebook 上运行,也可在本地 Jupyter 环境中执行。5- Notebooks:包含环境准备、YAML 修改、`infer.sh` 启动、Profiling 分析和 Dense RMSNorm NPU 融合路径 A/B 验证步骤,可在 GitCode 提供的轻量级 Notebook 上运行,也可在本地 Jupyter 环境中执行。
@@ -35,6 +35,7 @@ Notebook 环境中按顺序打开并 Run All:
352. `02_baseline_inference.ipynb`352. `02_baseline_inference.ipynb`
363. `03_profiling_analysis.ipynb`363. `03_profiling_analysis.ipynb`
374. `04_npu_optimization.ipynb`374. `04_npu_optimization.ipynb`
38+5. `05_quantization_qwen3_8b.ipynb`
38 39 
39首次执行 `02_baseline_inference.ipynb` 的 Baseline 推理 cell 会开始下载并缓存 `Qwen/Qwen3-8B` 权重;如果已设置 `QWEN3_8B_MODEL_PATH`,则直接使用本地权重目录。40首次执行 `02_baseline_inference.ipynb` 的 Baseline 推理 cell 会开始下载并缓存 `Qwen/Qwen3-8B` 权重;如果已设置 `QWEN3_8B_MODEL_PATH`,则直接使用本地权重目录。
40 41 
@@ -49,6 +50,8 @@ recipes 日志保存在 `src/inference_scripts/recipe_qwen3_8b/models/qwen/res/<
49 50 
50第 3 章会在 YAML 中打开 `model_config.enable_profiler=true`。运行后进入 recipes 结果目录下的 `prof/`,查看 `kernel_details`、trace、`op_statistic``op_summary` 等性能产物,再基于真实算子耗时选择第 4 章的优化点。51第 3 章会在 YAML 中打开 `model_config.enable_profiler=true`。运行后进入 recipes 结果目录下的 `prof/`,查看 `kernel_details`、trace、`op_statistic``op_summary` 等性能产物,再基于真实算子耗时选择第 4 章的优化点。
51 52 
53+第 5 章使用 AMCT 工具将 BF16 权重导出为 W8A8 INT8 量化权重,并通过量化 YAML 配置(`qwen3_8b_a8w8_1tp.yaml`)执行量化模型推理与 Profiling 分析,定位耗时最高的量化 matmul 算子。第 6 章基于第 5 章 Profiling 归纳的算子规格,需要使用 Ascend C 开发自定义量化 matmul 算子 `QmmCustom`,编译后接入 Qwen3-8B 量化模型验证功能与性能。
54+ 
52本地终端运行前先准备 CANN 和可见 NPU。55本地终端运行前先准备 CANN 和可见 NPU。
53 56 
54```bash57```bash