CANN pypto 逐元素除法算子 `pypto_pro.language.div`:Tile-Tile / Tile-Scalar 双模式使用指南
2026/9/19 21:14:51 网站建设 项目流程
  • 人工智能
  • 编译器
  • 模型编译
  • 高性能计算
  • 深度学习
  • CANN

【免费下载链接】pypto

PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。

项目地址:https://gitcode.com/cann/pypto
点击查看免费下载

本篇文章以 PyPTO 编程范式中 Tile 逐元素除法算子pypto_pro.language.div为讲解对象,完整覆盖其产品支持范围、两种计算模式(Tile-Tile 与 Tile-Scalar)、函数原型、参数与数据类型约束,并结合仓库源码与 ST 测试用例深入剖析其底层调度逻辑与精度控制实现。读完本文,你将能够在 Ascend 950(A5)设备上正确编写、验证并优化基于 Tile 的逐元素除法内核。

产品支持情况

pypto_pro.language.div目前仅在 Ascend 950 系列产品上受支持,其余产品线暂不支持,使用时请先确认目标硬件:

产品支持情况
Ascend 950PR / Ascend 950DT支持
Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持
Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持

仓库中的 ST 测试同样通过@pytest.mark.soc("950")标记并显式检查设备名包含 "Ascend950",否则直接跳过(见 test_vector_operations.py),与文档的产品支持声明相互印证。

功能说明

div对两个操作数对应位置的元素执行逐元素除法,支持两种计算模式,并且都支持原地计算(即out与某个输入为同一个 Tile):

  • Tile-Tile 模式:将lhs对应位置的元素除以rhs中的元素,把结果写入out,即out[i] = lhs[i] / rhs[i]
  • Tile-Scalar 模式:将lhs中的每个元素除以一个标量rhs,把结果写入out,即out[i] = lhs[i] / scalar

从源码看,该算子归属于python/pypto_pro/language/_api.py中 "Section B1: Binary element-wise (out, lhs, rhs)" 这一二元逐元素计算组(与addsubmul并列),其语义被定义为out = lhs / rhs,API 声明见 _api.py。

函数原型

pypto_pro.language.div( out: Tile, lhs: Tile, rhs: Union[Tile, Scalar], ) -> None

函数没有返回值,计算结果直接写入out

参数说明

参数输入/输出说明
out输出目的操作数,Tile 类型,存放逐元素除法的结果。数据类型与lhs一致,支持DT_INT16DT_UINT16DT_INT32DT_UINT32DT_INT64DT_UINT64DT_FP16DT_FP32。可与lhs或 Tile 类型的rhs为同一 Tile,实现原地计算。
lhs输入左操作数(被除数),Tile 类型。数据类型与out一致。
rhs输入右操作数(除数),Tile 或 Scalar 类型。传入 Tile 时执行 Tile-Tile 计算,数据类型与out一致,且 shape 与outlhs一致;传入 Scalar 时执行 Tile-Scalar 计算。

数据类型说明

与同组的add相比,div的整数支持范围更窄(不含DT_INT8/DT_UINT8),也不支持DT_BF16。这一差异在代码生成层面有所体现:除法、幂、取模等运算在向量二元指令生成时会被附加"精度类型"模板参数(见下节源码解析),因此对数据类型与算法选择有更严格的要求。实际使用中请以本文档表格列出的 8 种数据类型为准。

约束说明

官方文档声明无额外约束。从源码结构看,Section B1 组的公共约束同样适用于div,可作参考:

  • 不支持广播outlhsrhs(当rhs为 Tile 时)的 shape 必须完全一致;
  • 无隐式类型提升:所有操作数的数据类型必须一致(见 _api.py 中的注释约束)。

返回值说明

无返回值,结果写入out指向的 Tile。

源码实现与底层原理

1. 模式分发的 IR 层实现

div在语言 API 层声明后,前端解析阶段通过tensor_ops.py中的divdiv_scalar完成 IR 构造。核心逻辑在于根据rhs的类型自动选择 op:若rhsScalarType,则生成tensor.div_scalar调用;否则生成tensor.div调用,见 tensor_ops.py。

此外,标量操作数会被统一规范化为 FP32 表达式(_normalize_exprint_dtype=DataType.FP32, float_dtype=DataType.FP32),保证标量在参与除法前的类型一致性。

2. 向量指令生成的精度控制

在代码生成阶段,div对应的OP_DIV/OP_DIVS指令会由AddBinaryPrecisionTypeParm注入一个额外的模板参数pto::DivAlgorithm。当算子的precisionType属性为 1 时使用HIGH_PRECISION,否则使用默认的DEFAULT算法,见 codegen_vector_binary.cpp。这意味着除法内核在高精度需求场景下存在算法切换的扩展通道,是理解其数值精度行为的关键实现细节。

调用示例

Tile-Tile 模式

下面是一个完整的 64×64 FP32 数据逐元素除法内核:先在pl.section_vector()向量切片内通过pl.load将全局 Tensor 加载到 Vector 内存的 Tile,再执行pl.div,最后pl.store写回:

import pypto_pro.language as pl @pl.jit(auto_mutex=True) def div_kernel(a: pl.Tensor[[64, 64], pl.DT_FP32], b: pl.Tensor[[64, 64], pl.DT_FP32], out: pl.Tensor[[64, 64], pl.DT_FP32]): tt = pl.TileType(shape=[64, 64], dtype=pl.DT_FP32, target_memory=pl.MemorySpace.Vec) tile_a = pl.make_tile_group(type=tt, addrs=0x0000, mutex_ids=[0]) tile_b = pl.make_tile_group(type=tt, addrs=0x4000, mutex_ids=[1]) tile_out = pl.make_tile_group(type=tt, addrs=0x8000, mutex_ids=[2]) with pl.section_vector(): cur_a = tile_a.current() cur_b = tile_b.current() cur_out = tile_out.current() pl.load(cur_a, a, [0, 0]) pl.load(cur_b, b, [0, 0]) pl.div(cur_out, cur_a, cur_b) pl.store(out, cur_out, [0, 0])

要点说明:

  • pl.TileType通过shapedtypetarget_memory=pl.MemorySpace.Vec声明 Tile 的布局,div要求三个 Tile 的 shape 与 dtype 完全一致;
  • pl.make_tile_groupaddrs为 Tile 在对应内存空间中的偏移地址,mutex_ids用于向量算子的互斥与自动同步(配合auto_mutex=True使用);
  • pl.section_vector()界定向量指令执行区间,保证load → div → store处于同一向量流水上下文。

实测结果示例如下。

输入数据a:[[1 1.25 1.5 1.75 2 2.25 2.5 2.75 ...], [17 17.25 17.5 17.75 18 18.25 18.5 18.75 ...], [33 33.25 33.5 33.75 34 34.25 34.5 34.75 ...], [49 49.25 49.5 49.75 50 50.25 50.5 50.75 ...], ...] 输入数据b:[[10 10.5 11 11.5 12 12.5 13 13.5 ...], [42 42.5 43 43.5 44 44.5 45 45.5 ...], [74 74.5 75 75.5 76 76.5 77 77.5 ...], [106 106.5 107 107.5 108 108.5 109 109.5 ...], ...] 输出数据out:[[0.1 0.119048 0.136364 0.152174 0.166667 0.18 0.192308 0.203704 ...], [0.404762 0.405882 0.406977 0.408046 0.409091 0.410112 0.411111 0.412088 ...], [0.445946 0.446309 0.446667 0.44702 0.447368 0.447712 0.448052 0.448387 ...], [0.462264 0.462441 0.462617 0.462791 0.462963 0.463134 0.463303 0.46347 ...], ...]

可以看到,out每个元素严格等于a对应元素除以b对应元素,例如1 / 10 = 0.11.25 / 10.5 ≈ 0.119048

Tile-Scalar 模式

Tile-Scalar 模式只需将第二个操作数替换为 Python 标量即可,适合归一化、缩放等"每个元素除以同一个常数"的场景:

# Tile每个元素除以Scalar值。 pl.div(out, lhs, 2.0)

原地计算

由于div支持原地计算,out可以与lhs或 Tile 类型的rhs为同一个 Tile,例如:

# 将 tile_a 原地除以 tile_b,结果仍写回 tile_a。 pl.div(tile_a, tile_a, tile_b)

测试验证

仓库的 ST 测试 test_vector_operations.py 中同时覆盖了div的两种模式:

  • Tile-Tilepl.div(cur_out, cur_a, cur_b)store到输出区域偏移[256, 0]
  • Tile-Scalarpl.div(cur_out, cur_a, DIVISOR)DIVISOR = 4.0)后store到偏移[576, 0]

测试将内核输出与 torch 参考结果(a / ba / DIVISOR)通过torch.testing.assert_close对比,容差为rtol=1e-2, atol=1e-2,见 test_vector_operations.py。该测试同时验证了divaddsubmul等算子共享同一套 64×64 Tile 模板的复用模式,是编写自定义逐元素算子的良好参考蓝本。

小结

  • pypto_pro.language.div是 PyPTO Tile 编程范式中的二元逐元素除法算子,支持 Tile-Tile、Tile-Scalar 两种模式及原地计算;
  • 仅支持 Ascend 950PR / Ascend 950DT,数据类型限定为DT_INT16DT_UINT16DT_INT32DT_UINT32DT_INT64DT_UINT64DT_FP16DT_FP32
  • 底层由 tensor_ops.py 依据rhs类型自动分发到tensor.div/tensor.div_scalar,并在代码生成阶段通过DivAlgorithm模板参数支持精度算法切换;
  • 实战中可参照 test_vector_operations.py 中的测试模式验证结果正确性。
  • 人工智能
  • 编译器
  • 模型编译
  • 高性能计算
  • 深度学习
  • CANN

【免费下载链接】pypto

PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。

项目地址:https://gitcode.com/cann/pypto
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询