- 人工智能
- 编译器
- 模型编译
- 高性能计算
- 深度学习
- CANN
【免费下载链接】pypto
PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。
导读
本文介绍 CANN PyPTO 提供的实验性运行时配置接口pypto.experimental.set_runtime_options,它把tile_fwk_config.json中运行时部分尚未稳定的参数(当前为stitch_function_num_per_pool)转化为可编程接口。通过该接口,开发者可以在算子编译前分别控制 Workspace 中三个子内存池(root_inner、assemble_outcast、exclusive_outcast)的容量,在“保证性能的前提下降低内存”与“优先内存的前提下提升并行度”两种典型场景下进行精细化调优。读完本文,你将掌握该接口的调用方式、参数校验规则、日志分析方法,以及一套可直接落地的两步调参流程。
产品支持情况
set_runtime_options及精细化 Workspace 模式在以下产品上受支持:
- Ascend 950PR / Ascend 950DT:支持
- Atlas A3 训练系列产品 / Atlas A3 推理系列产品:支持
- Atlas A2 训练系列产品 / Atlas A2 推理系列产品:支持
功能说明:实验性运行时参数的编程化入口
PyPTO 的运行时参数集中维护在配置文件 tile_fwk_config.json 的"runtime"小节中,其中包含stitch_function_max_num(默认 128)、max_workspace_kb(默认 0)、stitch_function_num_per_pool(默认[0, 0, 0])等参数。这些参数中尚未稳定的一部分(例如精细化 Workspace 内存池控制)不会进入pypto.frontend.jit(runtime_options=...)的稳定参数表,而是通过实验性接口暴露给用户,后续新增的运行时实验特性也沿此通道扩展。
该接口的 Python 侧实现位于 python/pypto/experimental/runtime.py,并在 python/pypto/experimental/init.py 中导出:
from .runtime import get_runtime_options, set_runtime_options # noqa: F401调用链上,set_runtime_options最终通过set_options(runtime_options=...)写入当前配置作用域(python/pypto/config.py 中set_options),其参数以runtime.前缀进入 C++ 侧配置。
函数原型
set_runtime_options( *, stitch_function_num_per_pool: Optional[list[int]] = None, )该接口采用关键字参数(keyword-only),当前仅暴露一个参数。若不传入任何参数(或传入None),本次调用不产生任何配置变更;传入的合法参数会被打包进runtime_options字典后写入当前 scope。
参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| stitch_function_num_per_pool | 输入 | 用于分别控制 Workspace 中三个子内存池的容量大小,格式为[root_inner, assemble_outcast, exclusive_outcast]。配置的大小决定每个内存池可容纳的最大 stitch 构建 loop 迭代的数量。 |
各子内存池的含义如下:
| 池序号 | 池名称 | 典型承载对象 |
|---|---|---|
| 第 1 个元素 | root_inner | 算子执行过程中产生的 RootInner 中间结果(如循环内部的 matmul 结果) |
| 第 2 个元素 | assemble_outcast | Assemble outcast 型中间 Tensor |
| 第 3 个元素 | exclusive_outcast | Exclusive outcast 型中间 Tensor |
参数的详细规则:
- 配置方法:
[0, 0, 0]表示关闭精细模式;任一元素非 0 即开启。开启后,某一维为 0 表示不为该子内存池预留容量。若算子存在该内存池对应类型的中间 Tensor,编译会因容量不足失败,此时该维至少需配为 1;仅当算子没有该类型 Tensor 时才可配 0。 - 类型:list of int,固定 3 个元素。
- 取值范围:每个元素 0~1024。
- 默认值:
[0, 0, 0](关闭)。 - 影响 Pass 范围:NA。
参数校验的源码实现
参数合法性在 python/pypto/experimental/runtime.py 的_validate_stitch_function_num_per_pool中强制校验:
def _validate_stitch_function_num_per_pool(value) -> List[int]: if not isinstance(value, (list, tuple)) or len(value) != 3: raise ValueError(...) if any(isinstance(x, bool) or not isinstance(x, int) or not 0 <= x <= 1024 for x in value): raise ValueError(...) return list(value)即:必须是长度为 3 的 list 或 tuple;每个元素必须是[0, 1024]内的整数;bool被显式拒绝(因为bool是int的子类)。校验失败抛出ValueError,异常信息包含Invalid stitch_function_num_per_pool字样。对应单元测试见 python/tests/ut/interface/test_config_options.py 中的test_runtime_option_stitch_function_num_per_pool与test_runtime_option_stitch_function_num_per_pool_invalid,后者覆盖了长度不足、长度超限、非列表、负数、越界、浮点、混入 bool 等非法输入。
C++ 侧同样在workspace_budget_calculator.cpp中对三个元素逐项校验(framework/src/machine/utils/dynamic/workspace_budget_calculator.cpp 中ValidateDepth调用),并提示“若当前程序确实需要该内存池,该值不能为 0”。
返回值说明
void:Set 方法无返回值。设置成功即生效(写入当前配置作用域,随本次编译生效)。
约束说明
- 类型安全:须为长度为 3 的 list 或 tuple,元素为
[0, 1024]内的整数,不能使用 bool。 - 作用范围:不要在
pypto.loop内或 kernel 内设置,应在算子编译(pypto.frontend.jit或函数定义)之前设置。 - 配置项相对关系:
stitch_function_max_num:在不考虑内存占用、只考虑调优性能时使用;max_workspace_kb:在有内存限制时按内存总量压缩内存使用,可能降低并行度;- 精细化配置(
stitch_function_num_per_pool)在上述两项之后使用,按三个子内存池分别设置;开启后stitch_function_max_num与max_workspace_kb均失效。
调用示例
最简单的启用方式:
pypto.experimental.set_runtime_options(stitch_function_num_per_pool=[64, 1, 1])对应的读取接口(同文件提供,便于回读与自测):
pypto.get_runtime_options() # 返回 {'stitch_function_num_per_pool': [64, 1, 1], ...}get_runtime_options从当前 scope 读取全部 runtime 选项(python/pypto/experimental/runtime.py),单元测试test_runtime_option_stitch_function_num_per_pool验证了默认值[0, 0, 0]、设置后回读一致、以及reset_options()后恢复默认的行为。
示例 1:精细 Workspace 模式
以下示例用来说明默认模式与精细控制的差异。示例包含三个 loop:Loop0 做 Exclusive write、Loop1 做 Assemble write、Loop2 做 Read:
B_STATIC, L_STATIC, H_STATIC, D_STATIC = 1, 64, 1, 16 pypto.experimental.set_runtime_options(stitch_function_num_per_pool=[64, 1, 1]) @pypto.frontend.jit def k_tmp_to_d_emb( dy: pypto.Tensor([B_STATIC, L_STATIC, H_STATIC, D_STATIC], pypto.DT_FP32), weight: pypto.Tensor([H_STATIC, D_STATIC, D_STATIC], pypto.DT_FP32), output1: pypto.Tensor([B_STATIC, L_STATIC, D_STATIC], pypto.DT_FP32), output2: pypto.Tensor([B_STATIC, L_STATIC, D_STATIC], pypto.DT_FP32), ): tmp_assemble = pypto.tensor([B_STATIC, L_STATIC, H_STATIC, D_STATIC], output1.dtype, "tmp_assemble") tmp_exclusive = pypto.tensor([B_STATIC, L_STATIC, H_STATIC, D_STATIC], output2.dtype, "tmp_exclusive") # Loop0:Exclusive write for i_idx, t in pypto.loop_unroll(0, 1, 1, name="l_loop_0"): pypto.set_vec_tile_shapes(1, 64, 1, 256) tmp_exclusive[:] = pypto.add(dy, dy) # Loop1:Assemble write for j_idx, t in pypto.loop_unroll(0, L_STATIC, 1, name="l_loop_1"): pypto.set_vec_tile_shapes(1, 64, 1, 256) dy_v = dy[0, j_idx : j_idx + t, 0] pypto.set_cube_tile_shapes([128, 128], [128, 128], [128, 128]) dx = pypto.matmul(dy_v, weight[0], pypto.DT_FP32, b_trans=True) pypto.set_vec_tile_shapes(1, 64, 1, 512) tmp_assemble[0, j_idx : j_idx + t, 0] = dx + 0.0 # Loop2:Read for k_idx, t in pypto.loop_unroll(0, L_STATIC, 1, name="l_loop_2"): pypto.set_vec_tile_shapes(1, 64, 1, 512) output1[0, k_idx : k_idx + t] = tmp_assemble[0, k_idx : k_idx + t, 0] output2[0, k_idx : k_idx + t] = tmp_exclusive[0, k_idx : k_idx + t, 0]该示例中 tensor 的内存分布如下:
| Tensor | 数据归属 |
|---|---|
| dy、weight、output1、output2 | 输入参数,不进 Workspace 内存池 |
| dy_v | dy 的切片视图,复用同一块内存 |
| dx | RootInner |
| tmp_assemble | Assemble outcast |
| tmp_exclusive | Exclusive outcast |
将stitch_function_num_per_pool配置为非全零后,三个子内存池可容纳的 stitch 构建的 loop 数量相互独立,可分别按实际需求设置。对本示例,运行时根据实际占用得到的推荐配置为[64, 1, 1],说明如下:
- root_inner:由默认的 128 下调为 64。
dx只存在于 loop1 的单次循环内,无需为 loop0、loop2 预留容量。 - assemble_outcast:由默认的 128 下调为 1。
tmp_assemble在循环外创建,多次循环共享同一块内存。 - exclusive_outcast:由默认的 128 下调为 1。
tmp_exclusive仅在 loop0 的一次循环中产生。
经过上述设置,在并行度基本不变的前提下降低 workspace 占用。
调优方法
精细模式的价值在于“有的放矢”,因此调优的第一步是采集运行时日志,观察每个内存池的真实占用,再针对性地修改配置。
采集日志
开启 INFO 级日志并将日志输出到指定目录:
export ASCEND_PROCESS_LOG_PATH=./wk export ASCEND_GLOBAL_LOG_LEVEL=1 python your_test.py运行结束后,用 grep 过滤 Workspace 相关日志:
grep -rE "\[Workspace Runtime (Pool|Tuning|Summary|Recommendation)\]" ./wk日志标识及重点字段说明:
| 日志标识 | 说明 | 重点字段 |
|---|---|---|
[Workspace Runtime Pool] | 单次任务提交时各池实际使用 | current、peak、capacity |
[Workspace Runtime Tuning] | 单次任务提交的配置与推荐 | taskId、stitchCount、configuredDepths、recommendedDepths |
[Workspace Runtime Summary] | 整次执行各池的最大实际占用与容量上限 | 各池peak、capacity |
[Workspace Runtime Recommendation] | 整次执行结束后的配置建议,以及某个内存池配置值加 1 时增加的内存 | recommendedDepths、rawPerParallelBytes、nextDepthTotalBytes |
其中recommendedDepths={rootInner, assembleOutcast, exclusive}按顺序对应stitch_function_num_per_pool的三个元素;actualDepths为当前各个内存池生效大小。
从源码看,这些日志由 Workspace 分配器在运行时产出:[Workspace Runtime Pool]记录每个并行单元各池的current/peak/capacity,[Workspace Runtime Tuning]记录taskId、stitchCount与configuredDepths/recommendedDepths(见 framework/src/machine/utils/dynamic/dev_workspace.cpp 中LogTuningUsage),其中recommendedDepths由实际峰值占用除以对应内存池的单位字节数向上取整得到。若内存不足,会出现[Workspace Runtime Alloc Failure]日志,表示并行度已被内存截断。
场景 1:并行度已满足预期,精细化控制以降低内存
目标:并行度已达到预期时,去掉已申请但并未使用的内存,降低 workspace,同时保持性能。
操作步骤:
- 仅使用
stitch_function_max_num(或不设置,默认 128)将端到端性能调至目标,不要同时开启本配置或max_workspace_kb。 - 按上文开启 INFO 日志并执行算子。若出现
[Workspace Runtime Alloc Failure],说明并行度已被内存截断,须先增大stitch_function_max_num或改走场景 2。 - 读取
[Workspace Runtime Recommendation]的recommendedDepths,写入本配置。例如recommendedDepths={rootInner=64, assembleOutcast=1, exclusive=1}对应[64, 1, 1]。 - 去掉配置
stitch_function_max_num后复测:workspace 应下降,端到端耗时相对步骤 1 应基本持平。若性能下降,查看[Workspace Runtime Summary]中实际占用已接近容量上限的内存池,将该元素加 1 后重试。 - 覆盖算子实际使用的 shape 与执行路径,对各样本的
recommendedDepths逐项取最大值后固化,再关闭 INFO 日志验收。
场景 2:优先内存,精细化控制以提升并行度
目标:在总内存存在使用限制时,精细控制子内存池大小,把内存用到真正限制 stitch 构建的 loop 数量的池上。
背景:max_workspace_kb按同一规模压缩三个子内存池,其推荐值反映的是当前内存限制下根据实际使用内存反推的并行度,不是内存充足时的最优并行度,不能保证内存被充分利用。内存未用满时,可按下面步骤提高并行度。
操作步骤:
- 使用
max_workspace_kb(须大于提示的最小可运行值)。例如限额 200MB 时配置max_workspace_kb=200*1024。 - 按上文采集日志。从
[Workspace Runtime Summary]对比各池实际占用与容量上限,从[Workspace Runtime Recommendation]读取recommendedDepths与nextDepthTotalBytes。 - 将
recommendedDepths写入本配置作为起点,并取消max_workspace_kb。 - 计算剩余内存:限额减去当前 workspace 占用。某个内存池的配置值再加 1,整次执行增加的字节数为
nextDepthTotalBytes中对应项。 - 优先增加实际占用更接近容量上限、且
nextDepthTotalBytes能被剩余内存覆盖的池(常见为第 1 个元素root_inner)。每次只将该元素加 1,复测端到端耗时与 workspace。 - 当再加 1 将超过限额,或耗时不再下降时停止。多 shape 时对各元素取最大值后固化。
示例:限额 200MB,实际峰值约 100MB,recommendedDepths={rootInner=32, assembleOutcast=1, exclusive=1}。剩余约 100MB 可用于提高root_inner,可增加的次数不超过剩余字节除以nextDepthTotalBytes.rootInner。提高后 workspace 上升、并行度变大;若出现[Workspace Runtime Alloc Failure]或性能回退,将该元素减回。
与配置文件的对应关系
stitch_function_num_per_pool的默认值与相邻运行时参数一同维护在 tile_fwk_config.json 的"runtime"小节:
"runtime": { "device_sched_mode": 0, "run_mode": 0, "stitch_function_max_num": 128, "max_workspace_kb": 0, "stitch_function_num_per_pool": [0, 0, 0], ... }可以看到默认模式下 Workspace 各子内存池由stitch_function_max_num=128统一决定深度,而max_workspace_kb=0表示不限制总内存。调用set_runtime_options(stitch_function_num_per_pool=...)后,运行时配置覆盖该默认值:三个池深度彼此独立,且stitch_function_max_num与max_workspace_kb不再生效。这一“默认配置 → 编程覆盖”的关系也被单元测试所印证:reset_options()后get_runtime_options()["stitch_function_num_per_pool"]恢复为[0, 0, 0](见 python/tests/ut/interface/test_config_options.py)。
使用建议与注意事项
- 先采集、后配置:精细模式的价值依赖对真实占用分布的判断,务必先按“调优方法”一节采集
[Workspace Runtime Recommendation]日志,再写入配置,避免凭经验盲目设置。 - 区分三种配置的适用时机:性能优先用
stitch_function_max_num,内存受限用max_workspace_kb,两者之后的精细化收尾用stitch_function_num_per_pool;三者不可同时作为生效手段,精细模式开启后前两者失效。 - 为 0 的元素需要谨慎:只有当算子确定不产生该内存池对应类型的中间 Tensor 时,才可将该维配为 0,否则编译期会因容量不足失败,日志会给出明确提示。
- 多 shape 取并集:算子覆盖多个 shape/执行路径时,按各样本
recommendedDepths逐项取最大值后固化,确保所有路径可运行。 - 实验性接口的稳定性:该接口面向尚未稳定的运行时特性,接口形态与语义可能在后续版本调整或移除,生产固化前建议关注版本发布说明。
相关文档
- 接口文档原文:docs/zh/api/tensor_api/config/pypto-experimental-set_runtime_options.md
- 接口实现:python/pypto/experimental/runtime.py
- 配置管理:python/pypto/config.py
- 运行时默认配置:framework/src/interface/configs/tile_fwk_config.json
- 运行时 Workspace 分配与日志:framework/src/machine/utils/dynamic/dev_workspace.cpp
- 内存池深度校验与预算计算:framework/src/machine/utils/dynamic/workspace_budget_calculator.cpp
- 单元测试:python/tests/ut/interface/test_config_options.py
- 人工智能
- 编译器
- 模型编译
- 高性能计算
- 深度学习
- CANN
【免费下载链接】pypto
PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。
相关推荐
Cyberpunk 2077存档编辑器终极指南:深度解析与技术实现
Cyberpunk 2077存档编辑器终极指南:深度解析与技术实现 Cyberpunk 2077存档编辑器是一款专业级的开源工具,专为《赛博朋克2077》玩家和
人工智能编译器模型编译高性能计算深度学习CANNLinux 内核 Multi-Gen LRU 完全指南:配置、运行时调优与实验特性详解
Linux 内核 Multi Gen LRU 完全指南:配置、运行时调优与实验特性详解 导读 Multi Gen LRU(多代 LRU,缩写 MGLRU)是 L
操作系统内核驱动驱动开发虚拟化嵌入式网络存储FrankenPHP 性能优化实战指南:线程池、Worker 模式与运行时调优
FrankenPHP 性能优化实战指南:线程池、Worker 模式与运行时调优 导读:FrankenPHP 默认在“开箱即用”与“性能”之间寻求平衡,但要让它在
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考