ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CANN PyPTO Pro 算子性能调优实战指南:从 Profiling 基线到多核切分与流水优化

CANN PyPTO Pro 算子性能调优实战指南:从 Profiling 基线到多核切分与流水优化 CANN PyPTO Pro 算子性能调优实战指南从 Profiling 基线到多核切分与流水优化【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pyptoPyPTO ProParallel Tensor/Tile Operation算子的性能由多核任务划分、数据搬运效率、片上数据复用以及计算与搬运的流水并行度共同决定。本文以 CANN PyPTO 仓库的性能调优指南为骨架系统讲解如何用torch_npu.profiler与msOpProf建立性能基线、定位瓶颈并围绕多核切分、Tile Shape、多缓冲流水、Cube/Vector 协同与 TilingKey 特化等方向落地优化。读完本文你将掌握一套先采集、再定位、后调优、最后回归验证的完整调优闭环可直接用于 PyPTO Pro Kernel 的日常开发与性能交付。性能调优的总原则PyPTO Pro 算子的性能受多核任务划分、数据搬运效率、片上数据复用以及计算与搬运流水并行度等因素影响。因此性能调优必须以采集数据为依据先分析 Kernel 耗时、AI Core 流水、访存和任务时间线确定瓶颈所在再选择相应的优化手段。调优过程中有两条不可动摇的前提功能和精度正确优先性能优化必须以功能和精度正确为前提。每次调整 Tile Shape、同步关系或多核切分后均需先通过精度回归再验证性能收益。单轮单因素每轮只调整一类关键因素如仅改 Tile Shape、仅改同步关系或仅改多核切分完成精度回归后再按相同口径复测否则无法判断性能变化来自哪一处修改。性能工具与适用场景性能采集工具有两类适用场景与产物不同需按需选用工具适用场景主要产物或分析内容torch_npu.profiler在 Python 代码中控制采集范围适合采集 PyPTO Pro Kernel 的性能数据。Kernel 耗时、AI Core 流水指标和任务时间线。msOpProf单算子上板性能分析和核内流水采集。算子耗时、AI Core 流水、内存、Cache、资源冲突和核内流水图。msOpProf由 CANN 包中的msopprof可执行程序提供其命令接口与msprof op一致下文统一使用msprof op命令进行说明。二者的定位差异在于torch_npu.profiler面向 Python 测试脚本内的端到端采集控制粒度细、上手快msOpProf面向单算子深挖可下探到核内指令级流水适合定位资源冲突、Cache 复用不足等底层问题。建立可比较的性能基线可比较的性能数据必须来自相同的运行条件。采集前需要固定以下变量输入 Shape、数据类型、TilingKey、block_dimStream 和同步位置完成 JIT 预热首次启动 Kernel 时会解析函数体并触发编译见 Kernel核函数。测量纯 Kernel 耗时时不要将输入分配、随机数生成、Host 到 Device 拷贝和结果校验计入其中。优化前后应使用相同的采集配置并通过多次测量排除偶然波动。需要特别注意的是不同测量口径的耗时不能直接比较例如仅含 Kernel 执行时间与包含任务下发、同步等待的口径。记录结果时需注明测量口径算子交付前还需验证实际调用链如 aclnn 调用路径的端到端性能而不只是在 JIT 直接调用下测得的数字。使用 torch_npu.profiler 采集 Kernel 性能torch_npu.profiler可在 Python 代码中采集 PyPTO Pro Kernel 的耗时和 AI Core 流水指标。以下示例假设待测脚本已经定义kernel、block_dim和argsimport torch import torch_npu profiler_output ./profiling_output experimental_config torch_npu.profiler._ExperimentalConfig( export_type[torch_npu.profiler.ExportType.Text], profiler_leveltorch_npu.profiler.ProfilerLevel.Level1, aic_metricstorch_npu.profiler.AiCMetrics.PipeUtilization, ) # 在正式采集前完成JIT预热 kernelNone, block_dim torch.npu.synchronize() with torch_npu.profiler.profile( activities[torch_npu.profiler.ProfilerActivity.NPU], with_stackFalse, record_shapesFalse, profile_memoryFalse, experimental_configexperimental_config, on_trace_readytorch_npu.profiler.tensorboard_trace_handler( profiler_output, analyse_flagTrue ), ): kernelNone, block_dim torch.npu.synchronize()代码要点kernelNone, block_dim中方括号第一项为 StreamNone表示使用当前 Stream第二项为实际核数参见 Kernel核函数 中的调用形式说明预热调用与采集调用使用相同的启动配置确保采集到的是 JIT 编译完成后的稳定性能profiler_levelLevel1与aic_metricsPipeUtilization用于采集 AI Core 流水指标tensorboard_trace_handler(..., analyse_flagTrue)会同时输出 CSV 与 trace 文件。采集结束后重点检查以下输出文件文件检查内容kernel_details.csv在 Name 或 Type 列中定位目标 Kernel查看 Duration(us)、Block Dim 及 AI Core 流水指标。trace_view.json 或 trace_result.json查看应用层、CANN 层和 NPU 任务的时间关系。使用 msOpProf 采集单算子性能使用msprof op命令对 PyPTO Pro 测试脚本中的算子进行上板性能采集msprof op python3 test_example.py正式采集前先在测试脚本中完成 JIT 预热。通过--aic-metrics选择所需的 AI Core 指标采集多组指标时应保持输入和运行条件不变。常用指标及其可定位的问题如下指标主要检查内容可定位的问题PipeUtilizationCube、Vector、Scalar 及数据搬运流水的耗时或占比。主导流水、流水空闲和重叠不足。ArithmeticUtilizationCube 和 Vector 计算指令的执行情况。冗余计算或计算单元利用率不足。Memory、MemoryL0、MemoryUBGM、L1 Buffer、L0A Buffer、L0B Buffer、L0C Buffer 和 UB 等存储层级的读写带宽。搬运受限、有效带宽不足或片上复用不足。L2CacheL2 Cache 访问和命中情况。数据切分或访问顺序不合理造成的 Cache 复用不足。ResourceConflictRatioUB bank conflict、bank group 及其他资源冲突。片上数据排布或并发访问冲突。采集结果保存在OPPROF_*目录中。输出文件取决于--aic-metrics配置常用文件如下文件检查内容OpBasicInfo.csv算子名称、类型、Task Duration(us)、Block Dim、Device ID 和 AI Core 频率等基本信息。PipeUtilization.csv各 Core 上计算与搬运流水的耗时和占比。ArithmeticUtilization.csvCube 和 Vector 计算指令的耗时和占比。Memory.csv、MemoryL0.csv、MemoryUB.csvGM 及各级片上存储的读写带宽。L2Cache.csvL2 Cache 命中情况。ResourceConflictRatio.csvUB bank conflict、bank group 及其他资源冲突。trace.json各 Core 内部 Scalar、MTE、Cube、Vector 和 Fixpipe 等流水的指令级时间线。使用 Trace Viewer 或 MindStudio Insight 打开后可检查流水空洞、依赖关系和并行情况。visualize_data.binMindStudio Insight 使用的可视化数据文件。dump/采集生成的原始数据、Kernel 二进制等中间文件通常无需直接查看。性能数据与流水图分析定位瓶颈的五步法采集完成后按以下顺序定位瓶颈确认目标 Kernel从kernel_details.csv或OpBasicInfo.csv中确认目标 Kernel对比多个样本的 Kernel 耗时。性能结论以独立、稳定的多轮测量结果为准。识别主导流水比较 Cube、Vector 和数据搬运流水的耗时及占比识别主导流水。注意流水占比只能反映时间覆盖情况判断计算效率和带宽利用率时还需结合指令吞吐、带宽和阻塞指标。对照理论耗时根据计算量、数据搬运量和目标硬件规格估算理论耗时再与实测结果对比判断瓶颈来自工作量本身还是硬件利用率不足。检查流水连续性使用trace.json检查关键流水是否连续以及搬运、Vector 和 Cube 能否有效重叠。选择优化方向并复测根据分析结果选择优化方向例如多核切分、Tile Shape、片上复用或多缓冲。每轮只调整一类关键因素完成精度回归后再按相同口径复测。理解 bound 状态流水优化的终极目标流水优化的目标是让决定 Kernel 性能的主流水在稳态阶段连续执行并尽可能将其他流水的开销隐藏在主流水中。当总耗时主要受某条计算或搬运流水限制时Kernel 即达到该流水的 bound 状态矩阵计算类 Kernel 通常以Cube bound为目标矢量计算或搬运密集型 Kernel 则可能分别达到Vector bound或MTE bound。判断 bound不能只看累计占比还要确认主流水在主要执行区间内是否连续以及其他流水是否与其充分重叠。下图展示了未达到 bound 的状态Cube 和 Vector 流水均存在明显间隙计算任务未能连续执行。此时 Kernel 尚未达到稳定的计算 bound应重点检查 Tile 粒度、数据依赖、同步等待以及搬运与计算的重叠方式。图1 Cube 和 Vector 流水存在间隙Cube和Vector流水均存在明显间隙下图展示了达到 bound 的状态Cube 流水在稳态阶段保持连续MTE、Fixpipe 和 Vector 任务与 Cube 计算并行执行。此时 Kernel 达到 Cube bound即达到 Cube 流水的性能上限。图2 Cube 流水达到 bound 状态Cube流水连续执行并形成Cube bound多核切分优化PyPTO Pro 使用pypto_pro.language.get_block_idx()和pypto_pro.language.get_block_num()划分多核任务。从源码看python/pypto_pro/language/_api.pyget_block_idx()获取当前 AI Core 的 Block 索引get_block_num()返回的是应用 Stream 核数限制后的实际工作 Block 数——该值可能小于 Host 侧请求的kernel[stream, block_dim]因此应以该运行时值作为工作划分的步长避免因限核导致部分 Tile 未被处理。切分方案需要同时满足三个要求完整覆盖切分要完整覆盖计算范围无重叠写避免多个 Core 重复写入同一输出区域负载均衡保证各 Core 负载均衡。具体实践要点block_dim不能超过对应 Kernel 模式的平台上限也不宜超过可并行执行的任务数否则会产生空闲工作单元。模式相关上限参见 Kernel核函数Vector Kernel 按 AIV 实例数设置Cube Kernel 按 AIC 实例数设置混合 Kernel 则按 AIVAIC 组合数设置。各 Core 的工作量应尽量接近避免将尾块或高开销分支集中到少数 Core。规则二维 Tile 可先线性编号再按 Core 编号进行跨步分配以减小尾部负载差异。输出区域应由唯一 Core 写入需要跨 Core 归约时应使用明确且受支持的同步与归约方案。小 Shape 和大 Shape 应分别选择核数单一block_dim通常无法覆盖所有场景的最优配置。调试阶段使用block_dim1有助于验证逻辑但性能测试必须恢复目标核数。Tile 与片上内存优化Tile Shape 同时影响单次计算量、片上内存占用、循环次数、尾块比例和搬运效率。选择 Tile 时需综合考虑以下因素各类片上 Buffer 的容量限制UB、L0A、L0B、L0C、L1 等数据类型和 Tile Shape 共同决定的实际字节数数据搬运和计算指令的对齐要求尾块比例以及有效数据之外的补齐开销同一份输入数据在片上的复用次数多缓冲后总内存占用的倍增。较大的 Tile可以减少循环和指令下发次数但会占用更多片上内存可能无法启用双缓冲甚至降低并行度较小的 Tile资源占用较低但会增加循环次数、搬运次数和尾块处理开销。最终配置应根据目标 Shape 实测确定不存在放之四海皆准的固定值。GM 访问应保持连续和对齐并尽量合并为大粒度搬运。需要重复使用的数据在容量允许时应驻留片上避免反复从 GM 加载能够由后续计算直接消费的中间结果也不应写回 GM 后再重新加载——这条原则与流水分析中减少跨存储层搬运的目标一致。流水与多缓冲优化pypto_pro.language.make_tile_group为同一逻辑数据分配多块轮转 Tilecurrent()返回当前 Tilenext()切换到下一块。启用pypto_pro.language.jit(auto_mutexTrue)后编译器根据 Tile 的 mutex 信息插入核内同步从而构建双缓冲或 N 缓冲流水。从源码看python/pypto_pro/language/_api.pymake_tile_group的核心参数包括typepl.TileType描述符声明 Tile 的 shape、dtype 与所在存储空间addrs连续 Tile 的基地址或每个 Tile 一个地址mutex_ids每个 Tile 的互斥编号可为单个 int 或列表/元组每个 Tile 使用的 mutex 数量必须一致且同一 Tile 内不重复depthTile 数量未提供mutex_ids时必须显式指定fwd_ids/bwd_ids可选的跨 Core 事件编号0..15用于标记生产者→消费者通道供自动流水变换使用。优化时应重点检查加载下一块数据能否与当前块的 Vector 或 Cube 计算重叠当前结果写回能否与后续计算重叠每个轮转 Tile 是否使用独立且不冲突的 mutex 编号next()的调用次数和位置是否与数据的生产、消费顺序一致手动同步是否正确配对是否与自动 mutex 重复保护同一依赖流水末尾是否正确排空最后一个结果是否完成写回。增加缓冲数量会提高片上内存占用和调度开销。只有双缓冲仍无法隐藏关键延迟时才考虑增加缓冲级数并通过 Profiling 确认收益——盲目加深缓冲可能反而因资源占用上升而劣化性能。Cube 与 Vector 协同优化矩阵计算通过pypto_pro.language.section_cube()描述 Cube 任务矢量计算通过pypto_pro.language.section_vector()描述 Vector 任务。二者在源码中均为上下文管理器形式的执行域声明python/pypto_pro/language/_api.py执行域决定可使用的指令、片上 Buffer 以及block_dim的含义。对于同时包含 Cube 与 Vector 执行域的混合 Kernel应尽量重叠 Cube 计算、Vector 前后处理和 DMA 搬运并减少不必要的数据格式转换和跨存储层搬运。具体优化要点Cube 计算应检查 M、N、K 方向的 Tile Shape、左右矩阵布局、转置方式以及 L0A Buffer/L0B Buffer 装载格式归约长度较大时应在 L0C Buffer 中完成分块累加再按需要转换并写回避免中间结果反复出入 GMVector 前后处理应尽量与 Cube 流水重叠避免形成全局串行阶段连续执行多个细粒度 Vector 操作且额外开销明显时可在确认瓶颈后使用 Vector Function 表达寄存器级计算减少中间 Tile 读写调整 Cube 与 Vector 的并行关系后必须重新检查 mutex 和实际数据依赖不能以破坏正确性为代价消除同步。TilingKey 与编译期特化TilingKey 用于区分数量有限、执行路径差异明显的编译期配置。例如可为对齐与非对齐路径、不同算法模式或少量固定布局分别生成专用 Kernel消除热循环中的无效分支。TilingKey 通过启动方括号的第三项传入例如kernelNone, block_dim, {UseScale: 1, BlockM: 128}具体编码与启动规则参见 Kernel核函数。使用 TilingKey 必须注意成本边界不要将取值范围较大的运行时 Shape 逐一展开为 TilingKey。Key 数量过多会增加二进制规模、编译时间、缓存占用及测试成本只有特化收益明确且候选集合可控时才适合新增 TilingKey对于常用 Shape可设计规整、无分支的主路径将尾块和低频场景放入独立分支热循环中应减少依赖运行时数据的分支同时保留必要的边界检查不能为了消除分支而牺牲正确性。结果验证与交付检查完成调优后应执行以下检查清单确认优化成果可交付全部目标 Shape、数据类型、布局、TilingKey 和block_dim均通过精度测试覆盖最小 Shape、非对齐 Shape、尾块、空闲 Core 和最大资源占用等边界场景在相同测量条件下比较基线与优化版本并保存多轮结果Profiling 数据能够解释性能变化不以偶然波动作为优化结论已移除调试接口和仅用于定位问题的额外同步JIT 直接调用和实际 aclnn 调用路径均完成性能验证二进制大小、TilingKey 数量和首次编译时间仍处于可接受范围。最后一步尤为关键调优的收益必须能解释、可复现并在真实调用链而非仅 JIT 直调中成立同时不能以膨胀的二进制、过长的首次编译时间或过高的测试成本为代价。小结一套可复用的 PyPTO Pro 调优流程综合全文PyPTO Pro 算子的性能调优可以收敛为如下可复用的闭环流程固定条件固定 Shape、dtype、TilingKey、block_dim、Stream 与同步位置完成 JIT 预热确定测量口径采集数据用torch_npu.profiler或msprof op采集 Kernel 耗时、AI Core 流水与访存指标定位瓶颈按确认 Kernel → 识别主导流水 → 对比理论耗时 → 检查流水连续性的顺序确定是工作量问题还是利用率问题针对性优化依据瓶颈选择多核切分、Tile Shape、多缓冲流水、Cube/Vector 协同或 TilingKey 特化每轮只改一类因素回归验证先精度回归再按相同口径复测用 Profiling 数据解释性能变化最后完成交付检查。其中每一步的依据都可在仓库中溯源性能指标语义与输出文件对应本文所列表格get_block_idx/get_block_num/make_tile_group/section_cube/section_vector的实现见 python/pypto_pro/language/_api.pyblock_dim的含义与 Kernel 调用形式见 Kernel核函数。以数据为依据、以正确性为前提是 PyPTO Pro 性能调优始终不变的原则。【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表