ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

【CANN训练营】Qwen3-8B 推理优化实践笔记(2~3)

【CANN训练营】Qwen3-8B 推理优化实践笔记(2~3) 1 简介见【CANN训练营】Qwen3-8B 推理优化实践食用指南-CSDN博客2 Baseline跑通notebook地址gitcode.com/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/02_baseline_inference.ipynb2.1 环境与工作区准备import json import os import subprocess import sys from pathlib import Path print([环境准备] 开始, flushTrue) os.environ.setdefault(QWEN3_8B_DOWNLOAD_BACKEND, modelscope) os.environ[TOKENIZERS_PARALLELISM] false os.environ.setdefault(ASCEND_RT_VISIBLE_DEVICES, 0) def locate_repo_root(): repo_roots [] for env_name in (GITCODE_REPO_ROOT, CANN_LEARNING_HUB_ROOT, REPO_ROOT): if os.environ.get(env_name): repo_roots.append(Path(os.environ[env_name])) try: cwd Path.cwd() lineage [cwd, *cwd.parents] repo_roots.extend(lineage) repo_roots.extend(base / cann-learning-hub for base in lineage) for base in lineage: try: repo_roots.extend(base.glob(*/cann-learning-hub)) except OSError: pass except FileNotFoundError: pass repo_roots.append(Path(/opt/atomgit/cann-learning-hub)) seen set() for repo_root in repo_roots: key str(repo_root) if key in seen: continue seen.add(key) if (repo_root / tutorials/llm_inference/qwen3_8b/src).exists(): return repo_root raise FileNotFoundError(Cannot locate cann-learning-hub repository root. Open this notebook inside cann-learning-hub or set CANN_LEARNING_HUB_ROOT to the repository root.) REPO_ROOT locate_repo_root() os.chdir(REPO_ROOT) TUTORIAL_DIR REPO_ROOT / tutorials / llm_inference / qwen3_8b SRC_DIR TUTORIAL_DIR / src SOURCE_DIR REPO_ROOT / Sources / model_inference_optimization / qwen3_8b SOURCE_DIR.mkdir(parentsTrue, exist_okTrue) if str(SRC_DIR) not in sys.path: sys.path.insert(0, str(SRC_DIR)) from inference_scripts.environment_check import find_unmet_requirements, read_pinned_requirements if not os.environ.get(ASCEND_TOOLKIT_HOME): raise EnvironmentError(ASCEND_TOOLKIT_HOME is not set. Please activate the CANN environment before running this notebook.) cann_script Path(os.environ[ASCEND_TOOLKIT_HOME]) / set_env.sh env_cmd fsource {cann_script} env env subprocess.check_output(fbash -lc {env_cmd}, shellTrue, textTrue, cwdREPO_ROOT) for line in env.splitlines(): if in line: os.environ.__setitem__(*line.split(, 1)) REQUIREMENTS_FILE TUTORIAL_DIR / requirements.txt pinned_requirements read_pinned_requirements(REQUIREMENTS_FILE) unmet_requirements find_unmet_requirements(pinned_requirements) if unmet_requirements: print([依赖检查] 以下依赖缺失或版本不匹配) for name, actual, expected in unmet_requirements: print(f - {name}: 当前{actual or 未安装}, 要求{expected}) requirements_to_install [f{name}{expected} for name, _, expected in unmet_requirements] subprocess.run( [ sys.executable, -m, pip, install, -i, https://pypi.tuna.tsinghua.edu.cn/simple, --extra-index-url, https://download.pytorch.org/whl/cpu, --trusted-host, pypi.tuna.tsinghua.edu.cn, *requirements_to_install, ], checkTrue, ) remaining find_unmet_requirements(pinned_requirements) if remaining: details , .join(f{name}: {actual or 未安装} ! {expected} for name, actual, expected in remaining) raise RuntimeError(f依赖安装后仍不满足统一版本{details}) print([依赖检查] 安装完成统一环境已满足) else: print([依赖检查] 所有依赖版本均满足跳过安装) RECIPE_ROOT SRC_DIR / inference_scripts / recipe_qwen3_8b RECIPE_CONFIG_DIR RECIPE_ROOT / models / qwen / config BASELINE_YAML_TEMPLATE RECIPE_CONFIG_DIR / qwen3_8b_1tp.yaml PROFILE_YAML_TEMPLATE RECIPE_CONFIG_DIR / qwen3_8b_1tp_profile.yaml OPTIMIZED_YAML_TEMPLATE RECIPE_CONFIG_DIR / qwen3_8b_1tp_add_rmsnorm.yaml INFER_SH RECIPE_ROOT / executor / scripts / infer.sh MODEL_ID os.environ.get(QWEN3_8B_MODEL_PATH) or Qwen/Qwen3-8B MODEL_SOURCE_HINT local_path if os.environ.get(QWEN3_8B_MODEL_PATH) else os.environ[QWEN3_8B_DOWNLOAD_BACKEND] print(仓库目录 , REPO_ROOT) print(教程目录 , TUTORIAL_DIR) print(运行目录 , SOURCE_DIR) print(recipes 目录 , RECIPE_ROOT) print(YAML 目录 , RECIPE_CONFIG_DIR) print(推理入口 , INFER_SH) print(可见 NPU , os.environ.get(ASCEND_RT_VISIBLE_DEVICES)) print([环境准备] 完成, flushTrue)这段代码是整个教程的环境准备阶段核心目标是把当前 Notebook 进程配置成“可以在昇腾 NPU 上跑 Qwen3-8B 推理”的完整环境。执行对应单元格即可。这部分代码完成了环境准备工作先通过多策略定位并切换到教程仓库根目录然后设置模型下载后端、tokenizer并行开关和可见NPU卡号等基础环境变量接着通过执行CANN的set_env.sh脚本把昇腾工具链所需的全部环境变量导入当前Notebook进程随后读取requirements.txt并检查当前Python环境的依赖版本若有缺失或不匹配则自动用清华镜像源安装补齐最后定义recipes推理框架、YAML配置文件、推理入口脚本和模型ID等路径常量并打印环境摘要供确认为后续在昇腾NPU上运行Qwen3-8B推理和Profiling采集做好了完整的运行环境准备。2.2 查看YAML并执行Baseline推理2.2.1准备Baseline YAML把 Baseline YAML 模板复制一份到运行目录填入真实模型路径并打印关键配置供确认。import os import time from inference_scripts.recipe_workflow import ( collect_recipe_metrics, find_recipe_case_dir, prepare_runtime_yaml, print_yaml_focus, resolve_model_path, ) from inference_scripts.inference_qwen3_8b import ensure_recipe_log_ok BASELINE_WORK_DIR SOURCE_DIR / run_outputs / baseline_demo BASELINE_YAML SOURCE_DIR / recipe_yaml / baseline_demo.yaml BASELINE_WORK_DIR.mkdir(parentsTrue, exist_okTrue) print([Baseline 推理] 开始, flushTrue) resolved_model_path, model_source resolve_model_path(str(MODEL_ID), quiet_model_ioFalse) prepare_runtime_yaml(BASELINE_YAML_TEMPLATE, BASELINE_YAML, model_pathresolved_model_path) print([YAML 准备] Baseline 配置, flushTrue) print(参考 YAML , BASELINE_YAML_TEMPLATE) print(运行 YAML , BASELINE_YAML) print_yaml_focus(BASELINE_YAML) baseline_log_dir BASELINE_WORK_DIR / recipe_logs baseline_log_dir.mkdir(parentsTrue, exist_okTrue) os.environ[QWEN3_RECIPE_ROOT] str(RECIPE_ROOT) os.environ[QWEN3_RUN_YAML] str(BASELINE_YAML) os.environ[QWEN3_RUN_LOG] str(baseline_log_dir / baseline_demo_infer_stdout.log) os.environ[QWEN3_RUN_START_TIME] str(time.perf_counter())什么是YAMLYAMLYAML Aint Markup Language是一种人类可读的配置文件格式用缩进和键值对来表示数据就像“简化版的 JSON但不用写括号和逗号”。为什么需要 YAML这套教程里YAML 的作用是用文本描述“怎么跑模型推理”而不需要改 Python 代码。比如需要改模型路径、是否开 Profiler、是否开 RMSNorm 融合、生成长度这些内容只需要改 YAML 文件不用动任何 Python 代码。YAML 长什么样运行YAML目录文件地址在cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/recipe_yaml/baseline_demo.yaml上一部分打印的内容作为Baseline配置这份YAML的核心特征是关闭了各类性能优化如 Profiler、RMSNorm 融合、缓存编译等用于作为后续优化对比的“原始基准”。YAML文件的主要字段及解释1 model_config模型与推理核心配置字段当前值含义model_nameqwen3_8b模型名称标识model_path/home/developer/.cache/...模型权重实际路径由代码自动填入dtypebfloat16计算精度BF16兼顾性能与精度exe_modeeager执行模式即时执行非图模式enable_profilerfalse​关键关闭性能剖析Baseline 不采集数据with_ckpttrue启用检查点enable_cache_compilefalse​关闭缓存编译enable_static_kernelfalse​关闭静态内核custom_params子字段自定义优化开关见下custom_params自定义优化Baseline 全部关闭enable_npu_rmsnorm:false关闭 NPU 原生 RMSNormenable_add_rmsnorm:false关闭 AddRMSNorm 融合这是第4章要优化的核心enable_prefetch:false关闭预取prefetch_size:18874368预取大小虽关闭但保留默认值2data_config数据配置dataset:default使用默认数据集input_truncated_len:256输入截断长度最多 256 token3parallel_config并行配置全部为1表示单卡运行无张量并行/专家并行world_size: 1attn_tp_size: 1注意力张量并行moe_tp_size: 1MoE 张量并行embed_tp_size: 1嵌入层并行lmhead_tp_size: 1输出头并行4scheduler_config调度与生成配置max_new_tokens:64最多生成 64 个新 tokenbatch_size:1单批次推理enable_thinking:false关闭思考模式Qwen3 特有2.2.2 使用 recipes 命令启动推理%%bash set -euo pipefail # 激活虚拟环境如果有 source /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/venv/bin/activate # recipes 原生启动命令 echo recipes 启动命令: echo cd ${QWEN3_RECIPE_ROOT} echo bash executor/scripts/infer.sh --model qwen --mode offline --yaml ${QWEN3_RUN_YAML} cd ${QWEN3_RECIPE_ROOT} bash executor/scripts/infer.sh --model qwen --mode offline --yaml ${QWEN3_RUN_YAML} 21 | tee ${QWEN3_RUN_LOG}这部分是 Baseline 推理的实际启动命令核心作用是通过 recipes 框架在昇腾 NPU 上真正跑一次 Qwen3-8B 推理。注意这部分需要在原代码开头加一行激活虚拟环境的代码如果有recipes 是什么recipes是昇腾 CANN 生态里的一套“大模型推理样例框架”它不是模型本身也不是 PyTorch而是怎么在 NPU 上把某个大模型跑起来的工程封装。infer.sh 是什么qwen3_8b/src/inference_scripts/recipe_qwen3_8b/executor/scripts/infer.sh 是 recipes 的统一推理入口脚本。主要任务解析参数 → 加载环境 → 定位 YAML → 校验配置 → 调用launch函数真正在 NPU 上跑推理。2.2.3 读取recipes运行结果case_dir find_recipe_case_dir(RECIPE_ROOT, BASELINE_YAML) if case_dir is None: raise RuntimeError(f未找到 recipes 结果目录{BASELINE_YAML.stem}) recipe_log_path case_dir / log_0.log ensure_recipe_log_ok(recipe_log_path) run_info { stdout_path: os.environ[QWEN3_RUN_LOG], stderr_path: os.environ[QWEN3_RUN_LOG], wall_time_s: time.perf_counter() - float(os.environ[QWEN3_RUN_START_TIME]), recipe_case_dir: str(case_dir), recipe_log_path: str(recipe_log_path), } baseline_metrics collect_recipe_metrics( RECIPE_ROOT, BASELINE_WORK_DIR, baseline_demo, BASELINE_YAML, run_info, model_idstr(MODEL_ID), resolved_model_pathresolved_model_path, model_sourcemodel_source, optimization_modenone, max_new_tokens64, max_input_tokens256, enable_thinkingFalse, ) print([Baseline 推理] 完成, flushTrue)这部分代码是Baseline推理的收尾阶段核心作用是定位推理结果目录检查日志是否正常 收集并保存推理指标为后续分析和对比做准备。参数含义参数值含义optimization_modenone本次是 Baseline无优化max_new_tokens64生成长度限制max_input_tokens256输入长度限制enable_thinkingFalse关闭思考模式2.3 查看结果print([结果查看] 开始, flushTrue) def status_cn(status): return {ok: 通过, warning: 告警, failed: 失败}.get(status, status) def yes_no(value): if value is None: return 未记录 return 是 if value else 否 def load_metrics(work_dir, tag): metrics_path Path(work_dir) / metrics / f{tag}_summary.json metrics json.loads(metrics_path.read_text(encodingutf-8)) print(指标文件 , metrics_path) print(recipes YAML , metrics.get(recipe_yaml_path)) print(recipes 结果目录 , metrics.get(recipe_case_dir)) print(生成文件 , metrics.get(outputs_path)) print(生成 token 数 , metrics.get(generated_tokens)) print(总耗时(s) , metrics.get(total_time_s)) print(吞吐(tokens/s) , metrics.get(tokens_per_second)) rmsnorm_status metrics.get(rmsnorm_status) or {} print(RMSNorm 融合 , yes_no(rmsnorm_status.get(rmsnorm_fused))) print(AddRMSNorm 融合 , yes_no(rmsnorm_status.get(add_rmsnorm_fused))) sanity metrics.get(generation_text_sanity) if sanity: print(吐字检查 , status_cn(sanity.get(status)), f警告{sanity.get(num_with_warnings)}, f失败{sanity.get(num_failed)}) return metrics baseline_metrics load_metrics(BASELINE_WORK_DIR, baseline_demo) print() print(生成文本:) for line in Path(baseline_metrics[outputs_path]).read_text(encodingutf-8).splitlines(): if line.strip(): print(json.loads(line).get(generated_text, )) print([结果查看] 完成, flushTrue)这段代码读取并展示刚才那次推理的完整指标和生成文本便于直观确认 Baseline 状态。运行结果[结果查看] 开始 指标文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/run_outputs/baseline_demo/metrics/baseline_demo_summary.json recipes YAML /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/recipe_yaml/baseline_demo.yaml recipes 结果目录 /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/src/inference_scripts/recipe_qwen3_8b/models/qwen/res/20261013/qwen3_8b_baseline_demo 生成文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/run_outputs/baseline_demo/outputs/baseline_demo_generations.jsonl 生成 token 数 38 总耗时(s) 5.3463899999999995 吞吐(tokens/s) 7.10759970746616 RMSNorm 融合 否 AddRMSNorm 融合 否 吐字检查 通过 警告0 失败0 生成文本: The output of an **attention function** is a **weighted sum of the value vectors**, where the weights are determined by the **similarity between the query vector and each key vector**. [结果查看] 完成打印内容实际值含义指标文件路径指标 JSON 的位置recipes YAML运行 YAML 路径用的是哪个配置recipes 结果目录推理产物目录日志、输出等存放位置生成文件outputs 路径生成文本的 JSONL 文件生成 token 数38实际生成了 38 个 token总耗时(s)5.35推理总耗时 5.35 秒吞吐(tokens/s)7.11每秒生成 7.11 个 tokenRMSNorm 融合否确认关闭AddRMSNorm 融合否确认关闭吐字检查通过无告警、无失败3 Profiling分析这部分在Baseline的基础上打开torch_npu.profiler。torch_npu.profiler 是 PyTorch 在昇腾 NPU 上的性能剖析器它底层会调用 CANN / Ascend Profiling​ 能力把三层数据对起来1Host 侧Python 调用、PyTorch 算子下发、CPU 活动2CANN 侧算子编译、任务调度、内存拷贝、流同步3NPU 侧AI Core / AI CPU / Vector 核上的 kernel 执行时间、耗时、等待时间它的目的不是“让模型更快”而是先看清楚 Baseline 推理里时间到底耗在哪些算子上了。准备工作与运行环境工作区准备的流程和baseline一致。准备YAML的时候准备的是Profiling YAML在baseline的基础上打开Profiling。其余运行流程与baseline一致。Profiling YAML中model_config.enable_profiler 设为true其余推理参数保持和 Baseline 一致。YAML 文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/recipe_yaml/baseline_profile.yaml model_path /home/developer/.cache/modelscope/models/Qwen--Qwen3-8B/snapshots/master enable_profiler True # 注意这里的enable_profiler即yaml里打开了profiler enable_npu_rmsnorm False enable_add_rmsnorm False enable_prefetch False prefetch_size None dataset default input_truncated_len 256 max_new_tokens 64 batch_size 1结果分析[Profiler 产物] 开始 指标文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/run_outputs/baseline_profile/metrics/baseline_profile_summary.json 生成 token 数 38 Profiler 开启 是 Profile 目录 /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/src/inference_scripts/recipe_qwen3_8b/models/qwen/res/20261013/qwen3_8b_baseline_profile/prof prof/prefill /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/src/inference_scripts/recipe_qwen3_8b/models/qwen/res/20261013/qwen3_8b_baseline_profile/prof/prefill 一级目录 7f27e7db10fd4ffda8f0b031bf276588_11042_20261013190353199_ascend_pt kernel_details.csv 已生成 trace_view.json 已生成 prof/decode /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/src/inference_scripts/recipe_qwen3_8b/models/qwen/res/20261013/qwen3_8b_baseline_profile/prof/decode 一级目录 7f27e7db10fd4ffda8f0b031bf276588_11042_20261013190359433_ascend_pt kernel_details.csv 已生成 trace_view.json 已生成 吐字检查 通过 警告0 失败0 Profiler 摘要文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/run_outputs/baseline_profile/profiler_summary/baseline_profile_summary.txt Profiler summary from kernel_details source: /mnt/workspace/gitCode/cann/cann-learning-hub/tutorials/llm_inference/qwen3_8b/src/inference_scripts/recipe_qwen3_8b/models/qwen/res/20261013/qwen3_8b_baseline_profile/prof/decode/7f27e7db10fd4ffda8f0b031bf276588_11042_20261013190359433_ascend_pt/ASCEND_PROFILER_OUTPUT/kernel_details.csv OP Type Count Total(us) Ratio(%) ---------------------------------------------------------------------------------------- aclnnMatmulWeightNz_MatMulCommon_MatMulV2 435 36531.740 68.653 aclnnMul_MulAiCore_Mul 978 3579.760 6.727 aclnnPowTensorScalar_PowsAiCore_Pows 435 2855.780 5.367 FusedInferAttentionScore 108 2413.320 4.535 aclnnMean_ReduceMeanAiCore_ReduceMean 435 2318.040 4.356 ... aclnnInplaceOne_OnesLikeAiCore_OnesLike 3 35.100 0.066 aclnnEmbedding_GatherV2AiCore_GatherV2 3 31.100 0.058 ... 仅显示前 24 行共 35 行 [Profiler 产物] 完成[分析结论] 开始 摘要类型 kernel_details 生成 token 数 38 Baseline RMSNorm 融合 否 Baseline AddRMSNorm 融合 否 Top 算子: - aclnnMatmulWeightNz_MatMulCommon_MatMulV2: 次数435总耗时(us)36531.740占比68.653% - aclnnMul_MulAiCore_Mul: 次数978总耗时(us)3579.760占比6.727% - aclnnPowTensorScalar_PowsAiCore_Pows: 次数435总耗时(us)2855.780占比5.367% - FusedInferAttentionScore: 次数108总耗时(us)2413.320占比4.535% - aclnnMean_ReduceMeanAiCore_ReduceMean: 次数435总耗时(us)2318.040占比4.356% - aclnnInplaceCopy_CastAiCore_Cast: 次数873总耗时(us)1377.980占比2.590% - aclnnScatterNdUpdate_ScatterNdUpdateAiCore_ScatterNdUpdate: 次数216总耗时(us)1090.060占比2.049% - aclnnAdds_AddAiCore_Add: 次数441总耗时(us)625.340占比1.175% - aclnnRsqrt_RsqrtAiCore_Rsqrt: 次数435总耗时(us)533.560占比1.003% - aclnnAdd_AddAiCore_Add: 次数219总耗时(us)473.720占比0.890% 结论: - Baseline YAML 中 Dense RMSNorm 两个融合开关均为关闭因此本章看到的是融合前的执行链路。 - 摘要中没有直接出现融合后的 RMSNorm 算子名说明 Baseline 仍按小算子链路执行。 - 结合 QwenRMSNorm 的计算式摘要中的归一化相关小算子包括aclnnAdd_CastAiCore_Cast、aclnnArgMax_CastAiCore_Cast、aclnnGather_CastAiCore_Cast、aclnnInplaceCopy_CastAiCore_Cast、aclnnMax_ReduceMaxAiCore_ReduceMax、aclnnMean_ReduceMeanAiCore_ReduceMean、aclnnPowTensorScalar_PowsAiCore_Pows、aclnnRemainderTensorScalar_BroadcastToAiCore_BroadcastTo。 - 摘要中也可以看到残差 Add 相关算子aclnnAdd_AddAiCore_Add、aclnnAdd_CastAiCore_Cast、aclnnAdds_AddAiCore_Add。 - 下一章保持 recipes 的 YAML infer.sh 工作流只切换 Dense RMSNorm NPU 融合开关对比精度、吐字健康和吞吐变化。 分析文件 /mnt/workspace/gitCode/cann/cann-learning-hub/Sources/model_inference_optimization/qwen3_8b/run_outputs/profiling_analysis_summary.json [分析结论] 完成算子耗时排名排名算子次数耗时(us)占比属于什么1MatMul​43536531.7468.65%​线性层QKV/O/FFN2Mul​9783579.766.73%RMSNorm 小算子​3Pow​4352855.785.37%RMSNorm 小算子​4FusedInferAttentionScore​1082413.324.54%注意力融合算子5ReduceMean​4352318.044.36%RMSNorm 小算子​6Cast8731377.982.59%类型转换7ScatterNdUpdate2161090.062.05%KV Cache 更新8Adds441625.341.18%残差 Add​9Rsqrt​435533.561.00%RMSNorm 小算子​10Add219473.720.89%残差 Add​可以看出MatMul矩阵乘法耗时最长其余部分RMSNorm 被拆成了 8 个小算子残差 Add 也是小算子没有融合。Profiling 分析证实了 RMSNorm 未融合时被拆成 8 个小算子Pow/ReduceMean/Rsqrt/Mul 等导致launch 次数多、访存多、耗时高是明确的性能瓶颈。下一章将打开enable_add_rmsnorm融合开关用 A/B 对比验证优化效果。trace_view.json 时间线图谱trace_view.json时间线图谱呈现了 Qwen3-8B 在昇腾 NPU 上Prefill​与Decode​两个阶段的执行特征。Prefill对应prof/prefill即处理输入提示词的阶段。时间跨度与标记整体约 150ms50ms-200ms标记为ProfilerStep#0末尾带有Dec​ 标记暗示向 Decode 阶段的过渡。算子形态NPUStream 46/49上的色块相对“大块”虽然密集但多为一次性大粒度计算如首轮的 QKV 大矩阵乘。重叠与频率CPUPython/CANN与 NPU 有明显的调度交互。底部Overlap Analysis中 Computing 与 Free 交替由于仅执行一次整体耗时较短未暴露出小算子的反复累加效应。Decode时间跨度与标记整体约 350ms100ms-450ms包含#3、#4、#5连续多步每步对应一个或几个Token 的生成。极度密集的细碎条纹这是最核心的视觉特征。NPU 时间线上布满高频、细碎的彩色条纹直观对应了前文数据中435次 MatMul​ 以及伴随的Pow/ReduceMean/Rsqrt/MulRMSNorm 未融合等小算子。多流并行Stream 46 与 Stream 49 交错CANN 线程持续调度AI Core 频率满载浅蓝色长条说明计算单元持续忙碌。对比维度PrefillDecode性能含义执行次数​单次Step#0多次迭代Step#3/4/5Decode 重复放大了局部开销算子粒度​相对大块计算密集极度细碎访存/调度密集​Decode 中小算子 Launch 开销显著时间线密度​密集但无高频锯齿满屏细碎条纹印证 RMSNorm 拆分成 4~8 个小算子耗时占比​较短~150ms较长~350ms端到端吞吐受 Decode 阶段主导图谱直观揭示了Decode阶段因 RMSNorm 未融合产生大量小算子调度细碎条纹是端到端性能的可优化瓶颈Prefill 则相对健康。后续
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表