PyPTO AccToVecMode 详解:L0C Buffer 到 UB 搬运的双目标切分模式与尾块处理 PyPTO AccToVecMode 详解L0C Buffer 到 UB 搬运的双目标切分模式与尾块处理【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto导读pypto_pro.language.AccToVecMode是 CANN PyPTO 并行张量/瓦片编程范式中用于L0C BufferAcc→ UBVec数据搬运的双目标控制枚举也是 pypto_pro.language.move 的关键可选参数。本指南将完整解析该枚举的四个取值单目标 SingleModeVec0/1、双目标 DualModeSplitM/N深入讲解双目标模式在尾块场景下框架自动对齐 valid_M/valid_N 的行为与 UB 侧的手工切分策略并给出可直接复用的可运行代码示例帮助你在 Cube 侧矩阵乘结果回搬至 Vector 侧时正确选择搬运模式、规避尾块精度与卡死风险。产品支持情况AccToVecMode仅在特定昇腾硬件上提供能力使用时请先确认目标产品Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持该支持矩阵与 move 接口保持一致L0C→UB 回搬路径由 Fixpipe 硬件单元执行仅在 Ascend 950 系列即仓库源码中的 arch35 / A5 架构参见 copy_l0c_to_ub_impl.h上实现。功能说明双目标控制的枚举AccToVecMode是一个双目标控制的枚举用于move的 L0C Buffer→UB 数据搬运场景决定矩阵乘累加结果从 L0C BufferAcc 存储空间搬运到 UBVec 存储空间时的目的地分配策略单目标模式整个矩阵只写入一个 UB TileVec0 或 Vec1双目标模式整个矩阵按 M 轴或 N 轴对半拆分分别写入两个 UB TileVec0 / Vec1从而把 Fixpipe 的搬出带宽同时打向两个 Vector 目的地为后续 Vector 侧双缓冲/流水并行创造条件。从 PyPTO 的符号定义看该枚举与ReluPreMode、STPhase、RoundMode等同属 Block 级 DSL 参数枚举在 IR 层由宏PYPTO_DECLARE_ENUM声明见 op_attr_types.hPYPTO_DECLARE_ENUM(AccToVecMode, SingleModeVec0, SingleModeVec1, DualModeSplitM, DualModeSplitN)Python 侧经 pypto.ir 重新导出为pl.AccToVecMode因此代码中可直接使用pl.AccToVecMode.DualModeSplitM等写法。原型定义PYPTO_DECLARE_ENUM(AccToVecMode, SingleModeVec0, SingleModeVec1, DualModeSplitM, DualModeSplitN )参数说明参数值说明SingleModeVec0单目标模式将整个矩阵写入 Vec0 的目标 UB。SingleModeVec1单目标模式将整个矩阵写入 Vec1 的目标 UB。DualModeSplitM双目标模式按 M 维度拆分M/2*N 个元素写入每个 UB。尾块场景下框架会自动在搬运之前对 valid_ML0C Buffer M 轴方向的尾块大小向上对齐到 2 的倍数获得 aligned_M用户只需要了解 UB 侧的切分策略Vec0sub_id0得到前 aligned_M / 2 行Vec1sub_id1得到剩余 valid_M - aligned_M / 2 行。详见调用示例。注意当 valid_M 为 1 时仅切分给 Vec0。DualModeSplitN双目标模式按 N 维度拆分M*N/2 个元素写入每个 UB。尾块场景下框架会自动在搬运之前对 valid_NL0C Buffer N 轴方向的尾块大小向上对齐到 32 的倍数获得 aligned_N用户只需要了解 UB 侧的切分策略Vec0sub_id0得到前 aligned_N / 2 列Vec1sub_id1得到剩余 valid_N - aligned_N / 2 列。详见调用示例。注意当 valid_N 不超过 16 时仅切分给 Vec0。关键行为要点框架自动对齐用户只算 UB 侧切分双目标模式下尾块的 M/N 对齐由框架在搬运前自动完成SplitM 对齐到 2 的倍数、SplitN 对齐到 32 的倍数用户无需在 Cube 侧手动对齐 valid shape只需在 Vector 侧按 aligned 后的半宽计算 Vec0/Vec1 各自的 UB 大小。单行/窄列退化为单目标valid_M 1SplitM或valid_N ≤ 16SplitN时数据仅切分给 Vec0Vec1 不参与此时应在 Vector 侧只使用 sub_id 0 的路径。与move其他参数的配合约束详见 move.mdDualModeSplitN与phase同时使用时若 N 未 32 对齐可能出现卡死现象建议在矩阵乘运算前对 L0B Buffer 的 N 设置 valid shape使其向上对齐到 32 的倍数按列独立比例的scaleTile 类型量化不支持与双目标搬运DualModeSplitM / DualModeSplitN同时使用尾块场景下需搭配pl.set_validshape与TileType中的 compact 参数使用否则可能出现精度失败或卡死。源码中的落点move 与 L0C→UB 搬运实现move 接口签名在 python/pypto_pro/language/_api.py 中move的acc_to_vec_mode参数声明如下_api_decl def move( dst_tile: Tile, src_tile: Tile, offset: Optional[Offset] None, *, acc_to_vec_mode: Optional[AccToVecMode] None, relu_pre_mode: Optional[ReluPreMode] None, scale: Optional[Union[float, Scalar, Tile]] None, phase: Optional[STPhase] None, ) - None:其中acc_to_vec_mode仅在src 为 AccL0C Buffer、dst 为 VecUB时才有意义取值即上述四个枚举值。从接口文档可见move支持L0C→UBfix 流水、L1→L0A/L0Bmte1、L1→UBv、UB→L1mte3等多条搬运路径而AccToVecMode专用于其中的 L0C→UB 回搬路径。底层硬件指令映射在 Ascend 950 系列的 tileop 实现 copy_l0c_to_ub_impl.h 中四种模式最终映射为pto::TEXTRACT/pto::TINSERT指令的模板参数非双目标路径TExtractL0CToUB/TInsertL0CToUB按subblockId选择SingleModeVec0或SingleModeVec1量化场景下还会透传preQuantScalar与 ReLU 融合模式双目标路径TExtractL0CToUBDualDst由DualDstMode::DUAL_DST_SPLIT_M/DUAL_DST_SPLIT_N分别映射到DualModeSplitM/DualModeSplitN且通过static_assert明确禁止与 Fixpipe 在线量化scale同时使用——这与 Python 侧文档的约束一致。因此AccToVecMode不是纯粹的软件语义标志而是直接对应到 Fixpipe 硬件搬出指令的模式选择这也是为什么它被称为“双目标控制”枚举。调用示例DualModeSplitM 模式下的尾块场景以TILE64、valid_M33的尾块为例Cube 侧只需设置真实 valid shape框架自动把 valid_M 对齐到 aligned_M34再按行对半切分Vector 侧按(valid_M 1) // 2 * 2 // 2计算 v0、用valid_M - v0计算 v1并在对应sub_id下设置各自的 valid shapeimport pypto_pro.language as pl # cube section: 用户只需设置实际 valid_M无需手动对齐 pl.set_validshape(ac, [valid_M, N]) # valid_M33 pl.matmul(ac, al, br) pl.move(vec, ac, acc_to_vec_modepl.AccToVecMode.DualModeSplitM) # 框架自动对齐aligned_M34 # vector section: 用户需要自行计算 Vec0/Vec1 中 UB 实际大小 v0 (valid_M 1) // 2 * 2 // 2 # v0 17 v1 valid_M - v0 # v1 16 if sub_id 0: pl.set_validshape(vec, [v0, N]) else: pl.set_validshape(vec, [v1, N])DualModeSplitN 模式下的尾块场景以valid_N33的尾块为例框架自动将 valid_N 向上对齐到 32 的倍数得到 aligned_N64前 32 列写入 Vec0、剩余 1 列写入 Vec1import pypto_pro.language as pl # cube section: 用户只需设置实际 valid_N无需手动对齐 pl.set_validshape(ac, [TILE, valid_N]) # valid_N33 pl.matmul(ac, al, br) pl.move(vec, ac, acc_to_vec_modepl.AccToVecMode.DualModeSplitN) # 框架自动对齐aligned_N64 # vector section: V 侧用户自行计算 v0/v1 v0 (valid_N 31) // 32 * 32 // 2 # v0 32 v1 valid_N - v0 # v1 1 if sub_id 0: pl.set_validshape(vec, [TILE, v0]) else: pl.set_validshape(vec, [TILE, v1])仓库测试用例参考仓库的 ST 测试 test_dual_mode_tail.py 对 DualModeSplitM / DualModeSplitN 在奇偶 valid 尺寸尾块下的行为做了系统覆盖以恒等矩阵 BKN构造 C A按 TILE 步长沿 M 轴SplitM或 N 轴SplitN循环最后一轮迭代即尾块同时验证了奇数/偶数 M、奇数/偶数 N 与两种双目标模式的组合是学习“Cube 侧 matmul 双目标 move、Vector 侧按 sub_id 分片 store 到 GM”这一完整写法的直接范例。相关单目标尾块场景可参考同目录下的 test_single_mode_tail.py。选择建议追求最大搬出吞吐、Vector 侧有足够双缓冲空间时优先使用DualModeSplitM/DualModeSplitN让 Fixpipe 同时写满 Vec0 与 Vec1 两个目的地需要随路量化scale、随路 ReLU 或输出规模极小时退回SingleModeVec0/SingleModeVec1双目标模式与 Fixpipe 在线量化互斥使用 DualModeSplitN 且同时开启 phase 流水握手时务必保证 N 侧 32 对齐避免出现硬件卡死。相关文档与索引枚举定义与支持矩阵docs/zh/api/pro_api/SIMD-API/basic_data_structures/AccToVecMode.md搬运接口docs/zh/api/pro_api/SIMD-API/memory_data_movement/move.md基础数据结构索引docs/zh/api/pro_api/SIMD-API/basic_data_structures/index.md【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考