
人工智能编译器模型编译高性能计算深度学习CANN【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址https://gitcode.com/cann/pypto点击查看免费下载vf.mul是 PyPTOParallel Tensor/Tile Operation 编程范式向量函数vector_functionVF编程模型中最重要的基础算术接口之一用于对两个reg_tensor向量寄存器执行逐元素乘法。本文以官方 API 文档 mul.md 为主线完整讲解其产品支持范围、掩码mask语义、MergeMode 行为、数据类型约束与寄存器存储原理并结合仓库源码与测试用例给出 FP32 与 INT64 两套可直接运行、可验证的完整示例帮助读者在 Ascend 950 系列上快速掌握寄存器级向量乘法的正确用法。产品支持情况vf.mul属于 PyPTO SIMD-API 中reg_computation/basic_arithmetic寄存器基本算术运算类别。根据文档声明的产品支持矩阵硬件平台支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持可见当前vf.mul仅面向 Ascend 950 系列950PR/950DT提供能力。在编写算子前请先确认目标部署硬件属于该支持范围否则需要改用其他兼容的乘法实现路径例如 Tile 级乘法接口pl.mul见下文对比。功能语义两个寄存器逐元素相乘vf.mul对两个源寄存器reg_tensor执行逐元素element-wise乘法。对掩码mask选中的每一个 lanei计算src0[i] × src1[i]并写入目的寄存器dst[i]$$ dstReg_i srcReg0_i \times srcReg1_i $$这一语义在源码的 API 声明中有完全一致的体现。python/pypto_pro/language/_vf_api.py 中mul的 docstring 写道For each laneiwheremask[i]is active, computes the product of the corresponding elements insrc0andsrc1and writes the result todst[i].即只有掩码位为 1活跃的元素参与乘法未选中元素的行为由mode参数决定见下文 MergeMode 说明。需要特别区分的是PyPTO 中存在两个层级的乘法接口寄存器级VF 内部本文主角vf.mul(src0, src1, preg, mode)作用于reg_tensor只能在pl.vector_function修饰的向量函数内使用Tile 级kernel 内pl.mul(out, lhs, rhs)定义于 python/pypto_pro/language/_api.py直接对 Tile 执行原地乘法。vf.mul定位为寄存器级计算原语是 Tile 数据进入向量寄存器后做精细运算的核心手段。函数原型与参数详解mul(src0, src1, preg, mode: Optional[MergeMode] None) - dst各参数含义如下参数输入/输出说明src0输入源操作数 0reg_tensor其数据类型必须与目的操作数dst保持一致。支持的数据类型为DT_INT16、DT_UINT16、DT_INT32、DT_UINT32、DT_FP16、DT_BF16、DT_FP32、DT_INT64、DT_UINT64。src1输入源操作数 1reg_tensor数据类型与src0一致。preg输入mask_reg 掩码寄存器控制哪些元素参与乘法。mode输入可选对应 MergeMode 类型-pypto_pro.language.MergeMode.ZEROING默认preg未筛选掩码位为 0的元素在dst中置 0。-pypto_pro.language.MergeMode.MERGING当前不支持。掩码寄存器 preg 的粒度语义preg是vf.mul中元素级有效性控制的载体。mask_reg 文档 明确了其物理规格总位宽固定为256 bit掩码粒度由关联的dtype决定dtype元素位宽元素个数每元素掩码位数总掩码位数DT_INT8 / DT_UINT8 等 8bit 类型8 bit2561 bitb8 粒度256 bitDT_FP16 / DT_UINT16 / DT_BF1616 bit1282 bitb16 粒度256 bitDT_FP32 / DT_INT32 / DT_UINT3232 bit644 bitb32 粒度256 bitDT_INT64 / DT_UINT6464 bit328 bitb64 粒度256 bit实践建议preg的 dtype 一般与配套的reg_tensor保持一致。当掩码位为 1 时元素参与乘法并将结果写入目的寄存器掩码位为 0 时在默认ZEROING模式下目的寄存器对应位置零。MergeMode 行为MergeMode 文档 定义了 mask 未选中元素在目标寄存器中的处理方式同样适用于vf.add、vf.sub、vf.div等 VF 计算接口class MergeMode(enum.Enum): ZEROING ... # mask 未选中位置置零默认 MERGING ... # mask 未选中位置保留目标寄存器原值在vf.mul中MERGING模式当前不支持因此实际可用的只有默认的ZEROING。从源码看python/pypto_pro/language/_vf_api.py 的接口注释也明确标注 MERGING mode is not supported on current device与文档保持一致。调用时可以不传mode参数直接使用默认置零行为。数据类型支持与寄存器存储原理vf.mul支持 9 种数据类型DT_INT16、DT_UINT16、DT_INT32、DT_UINT32、DT_FP16、DT_BF16、DT_FP32、DT_INT64、DT_UINT64。理解这些类型在寄存器中的排布有助于判断一次vf.mul实际覆盖的元素数量。根据 reg_tensor 文档RegTensor 是 VF 计算的基本数据容器用于存储从 UB Tile 加载的数据、VF 运算的中间结果和最终输出单个寄存器总大小固定为256 字节不同 dtype 对应不同元素个数dtype元素宽度元素个数DT_INT8 / DT_UINT8 等8 bit256DT_INT16 / DT_UINT16 / DT_FP16 / DT_BF1616 bit128DT_INT32 / DT_UINT32 / DT_FP3232 bit64DT_INT64 / DT_UINT6464 bit32由此可以推导FP32 乘法每个reg_tensor含 64 个元素一次vf.mul最多完成 64 lane 的逐元素乘法INT64 乘法每个reg_tensor含 32 个元素且 b64 数据在双寄存器模式下会被拆分为低位reg[0]DT_UINT32与高位reg[1]DT_UINT32两部分交错搬运DIST_DINTLV_B32 双搬入模式两个 RegTensor 共同存储 512B 数据量。这也是 INT64 示例中 Tile 形状取[1, 32]的原因。此外RegTensor 在使用上有两个值得注意的工程约束来源reg_tensor.mdRegTensor 寄存器数量上限为32超出上限的寄存器数据会写入预留的 8K UB 内存可能引起性能劣化编译器会自动复用生命周期结束的寄存器与预留内存创建寄存器后必须通过vf.load_align或vf.full初始化数据否则内容未定义。约束与返回值约束说明无。返回值说明返回目的操作数dst类型为 reg_tensor支持的数据类型与src0一致。调用示例基本调用示例FP32以下为文档给出的完整可运行示例展示了在向量函数中使用vf.mul完成两个 Tile 的逐元素乘法并与 PyTorch 的a * b结果做数值比对import os import pypto_pro.language as pl import torch import torch_npu pl.vector_function def example_vf(src_a, src_b, dst_tile): preg vf.create_mask(patternpl.MaskPattern.ALL, dtypepl.DT_FP32) reg_a vf.load_align(src_a, 0) reg_b vf.load_align(src_b, 0) reg_out vf.mul(reg_a, reg_b, preg) vf.store_align(dst_tile, reg_out, preg) pl.jit() def example_kernel( a: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_FP32], b: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_FP32], out: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_FP32], ): tf pl.TileType(shape[1, 64], dtypepl.DT_FP32, target_memorypl.MemorySpace.Vec) in_a_grp pl.make_tile_group(typetf, addrs0x0, mutex_ids[0]) in_a in_a_grp.current() in_b_grp pl.make_tile_group(typetf, addrs0x100, mutex_ids[1]) in_b in_b_grp.current() t_out_grp pl.make_tile_group(typetf, addrs0x200, mutex_ids[2]) t_out t_out_grp.current() with pl.section_vector(): pl.load(in_a, a, [0, 0]) pl.load(in_b, b, [0, 0]) example_vf(in_a, in_b, t_out) pl.store(out, t_out, [0, 0]) def test_example(): device_id int(os.environ.get(TILE_FWK_DEVICE_ID, 0)) device fnpu:{device_id} core_nums 1 torch.npu.set_device(device) a torch.randn([1, 64], devicedevice, dtypetorch.float32) b torch.randn([1, 64], devicedevice, dtypetorch.float32) out torch.empty([1, 64], devicedevice, dtypetorch.float32) example_kernelNone, core_nums torch.npu.synchronize() torch.testing.assert_close(out, a * b, rtol1e-5, atol1e-5) if __name__ __main__: test_example() print(PASSED)示例的关键链路可以拆解为声明向量函数pl.vector_function修饰example_vf函数内通过vf.create_mask创建全 1 掩码MaskPattern.ALL用vf.load_align将 Tile 数据加载为reg_tensor执行乘法vf.mul(reg_a, reg_b, preg)得到reg_out再经vf.store_align写回 Tile编排 kernelpl.jit()修饰的example_kernel中定义TileType(shape[1, 64], dtypepl.DT_FP32, target_memorypl.MemorySpace.Vec)通过pl.make_tile_group为输入/输出分配 UB 地址0x0、0x100、0x200地址按 256B 对齐错开在pl.section_vector()向量节内完成pl.load→ 向量函数 →pl.storehost 端校验使用torch.randn构造输入调用example_kernelNone, core_nums启动单核 kernel最终用torch.testing.assert_close(out, a * b, rtol1e-5, atol1e-5)验证逐元素乘法结果正确。INT64 数据类型示例针对 64 位整型乘法文档提供了专门示例。注意TileType形状为[1, 32]、三个 Tile 的地址以 256 字节为间隔0、256、512与 b64 类型每寄存器 32 元素的规格对应import os import pypto_pro.language as pl import torch import torch_npu pl.vector_function def example_vf_int64(src_a, src_b, dst_tile): preg vf.create_mask(patternpl.MaskPattern.ALL, dtypepl.DT_INT64) reg_a vf.load_align(src_a, 0) reg_b vf.load_align(src_b, 0) reg_out vf.mul(reg_a, reg_b, preg) vf.store_align(dst_tile, reg_out, preg) pl.jit() def example_kernel_int64( a: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT64], b: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT64], out: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT64], ): tf pl.TileType(shape[1, 32], dtypepl.DT_INT64, target_memorypl.MemorySpace.Vec) in_a_grp pl.make_tile_group(typetf, addrs0, mutex_ids[0]) in_a in_a_grp.current() in_b_grp pl.make_tile_group(typetf, addrs256, mutex_ids[1]) in_b in_b_grp.current() t_out_grp pl.make_tile_group(typetf, addrs512, mutex_ids[2]) t_out t_out_grp.current() with pl.section_vector(): pl.load(in_a, a, [0, 0]) pl.load(in_b, b, [0, 0]) example_vf_int64(in_a, in_b, t_out) pl.store(out, t_out, [0, 0]) def test_example_int64(): device_id int(os.environ.get(TILE_FWK_DEVICE_ID, 0)) device fnpu:{device_id} core_nums 1 torch.npu.set_device(device) a torch.randint(0, 100, [1, 32], devicedevice, dtypetorch.int64) b torch.randint(0, 100, [1, 32], devicedevice, dtypetorch.int64) out torch.empty([1, 32], devicedevice, dtypetorch.int64) example_kernel_int64None, core_nums torch.npu.synchronize() torch.testing.assert_close(out, a * b, rtol0, atol0) if __name__ __main__: test_example_int64() print(PASSED)与 FP32 示例相比INT64 示例有三个差异点值得关注掩码 dtypevf.create_mask(patternpl.MaskPattern.ALL, dtypepl.DT_INT64)掩码粒度自动切换为 b64每元素 8 bit 掩码Tile 形状[1, 32]匹配 64 位类型每寄存器 32 个元素的能力数值断言整型乘法为精确运算torch.testing.assert_close使用rtol0, atol0做严格相等校验host 端输入用torch.randint(0, 100, ...)构造避免溢出。源码佐证与测试现状vf.mul的接口声明位于 python/pypto_pro/language/_vf_api.py以staticmethod _api_decl形式暴露为 VF 内置 API其 docstring 中的数学公式与本文档完全一致dstReg_i srcReg0_i × srcReg1_i。同一文件中muls寄存器乘标量、mul_add_dst、mul_dst_add、mull寄存器级长整型乘法等接口与其同族分别覆盖标量乘、乘加融合与 64 位扩展等场景可作为乘法相关 VF 原语的横向参考。在测试侧仓库的前端与算子测试中大量使用vf.mul作为基础计算原语例如 python/tests/st/pypto_pro/frontend/auto_pipeline/test_fa_serial_dn_auto.py、python/tests/st/pypto_pro/frontend/control_flow/test_cond_tile_mutex_generalize.py、python/tests/st/pypto_pro/frontend/element_wise/test_cast_dedup_double_buffer.py 等用例均通过vf.mul完成寄存器级逐元素乘法说明该接口已在前端自动流水auto pipeline、条件 Tile 互斥cond tile mutex、类型转换去重cast dedup等真实场景中被反复验证。读者可在运行环境就绪后参考本文两个示例编写自己的最小复现用例与torch逐元素乘法结果比对即可完成正确性验证。使用建议与注意事项掩码与数据类型对齐preg的 dtype 应尽量与reg_tensor一致如 FP32 配 b32 粒度、INT64 配 b64 粒度不一致时需要自行判断结果行为mask_reg.md 有明确提示。默认置零语义vf.mul只支持ZEROING模式掩码未选中的元素在结果中为 0若业务需要保留原值语义当前硬件上无法通过MERGING实现需在算子逻辑层面自行处理。寄存器资源预算VF 内 RegTensor 上限 32、MaskReg 上限 16乘法链路较长时注意让编译器复用寄存器避免触发预留 8K UB 内存导致性能劣化。数据类型适用性FP8/FP4 等低比特浮点类型仅支持搬运、填充与类型转换不支持直接参与vf.mul算术运算见 reg_tensor.md 的 FP8/FP4 说明需先用vf.astype转为 FP32/BF16/FP16 再计算。硬件匹配当前仅 Ascend 950PR/Ascend 950DT 支持A2/A3 系列需确认替代实现路径。相关文档导航reg_tensor寄存器数据容器mask_reg掩码寄存器MergeMode掩码未选中元素处理模式基本算术运算目录vf.mul 接口源码声明赞分享人工智能编译器模型编译高性能计算深度学习CANN【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址https://gitcode.com/cann/pypto点击查看免费下载相关推荐CANN PyPTO 逐元素乘法 pypto.mul 详解接口语义、广播规则、TileShape 切分与源码验证CANN PyPTO 逐元素乘法 pypto.mul 详解接口语义、广播规则、TileShape 切分与源码验证 导读 pypto.mul 是 CANN Py人工智能编译器模型编译高性能计算深度学习CANNPyPTO vf.create_mask 详解VF 掩码寄存器创建与元素级运算控制PyPTO vf.create_mask 详解VF 掩码寄存器创建与元素级运算控制 导读 vf.create_mask 是 PyPTOParallel Te人工智能编译器模型编译高性能计算深度学习CANNCANN PyPTO vf.min 接口详解掩码控制下的逐元素最小值运算CANN PyPTO vf.min 接口详解掩码控制下的逐元素最小值运算 vf.min 是 CANN PyPTOParallel Tensor/Tile O人工智能编译器模型编译高性能计算深度学习CANN创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考