- 人工智能
- 指令集
- 算子库
- CANN
- Ascend
【免费下载链接】pto-isa
Parallel Tile Operation (PTO) is a virtual instruction set architecture designed by Ascend CANN, focusing on tile-level operations. This repository offers high-performance, cross-platform tile operations across Ascend platforms.
TORS(Tile OR with Scalar)是 CANN PTO(Parallel Tile Operation)虚拟指令集中将向量 Tile 与标量逐元素做按位或(bitwise OR)的指令,适用于对整型数据做掩码置位、标志位合并等场景。本文基于仓库文档与源码,完整讲解 TORS 的数学语义、三级汇编语法、C++ 内建接口签名、A2A3/A5/CPU 三套平台实现原理、使用约束与有效区域规则,并给出可编译的调用示例和测试用例佐证。
指令概述与数学语义
TORS 是 PTO 指令集中的"标量二元位运算"指令:它将一个向量 Tile(src)中的每个元素与一个标量(scalar)进行按位或,结果写入目标 Tile(dst),属于逐元素(element-wise)运算。官方文档对该指令的定义位于 docs/isa/TORS.md(中文版见 docs/isa/TORS_zh.md)。
对有效区域内的每个元素(i, j),其数学语义为:
$$ \mathrm{dst}{i,j} = \mathrm{src}{i,j} ;|; \mathrm{scalar} $$
即按位或(bitwise OR)。scalar是类型与src/dst元素类型一致的标量值,运算结果直接写回对应位置,不做累加、不做取反,是一条"读-算-写"的单步运算。由于按位或对每个位独立进行,scalar中为 1 的位会在结果中强制置 1,因此常用于:
- 将 Tile 中数据的特定位域置位(如设置状态标志);
- 与掩码标量合并,把掩码位写入批量数据;
- 配合
TAND/TNOT等指令构造更复杂的位逻辑表达式。
注意:TORS 只接受整型(integral)元素类型,浮点类型不适用——这与其按位语义一致,浮点数据的位模式运算应由专门的位转换指令完成。
指令语法体系
PTO 汇编为同一条指令提供了三种表达层次,覆盖从"纯 SSA 形式"到"显式 DPS(Data Parallel Semantics)"的编码需求。
同步形式
TORS 的基础汇编写法(同步、无显式事件依赖):
%dst = tors %src, %scalar : !pto.tile<...>, i32AS Level 1(SSA)
抽象汇编第一级,采用 SSA 形式,操作数类型为抽象!pto.tile<...>,标量携带具体数据类型dtype:
%dst = pto.tors %src, %scalar : (!pto.tile<...>, dtype) -> !pto.tile<...>AS Level 2(DPS)
抽象汇编第二级,采用 DPS 形式,显式区分输入(ins)与输出(outs),操作数绑定到具体存储缓冲!pto.tile_buf<...>:
pto.tors ins(%src, %scalar : !pto.tile_buf<...>, dtype) outs(%dst : !pto.tile_buf<...>)C++ 内建接口
函数签名
TORS 的 C++ 内建接口(intrinsic)声明位于 include/pto/common/pto_instr.hpp(第 2475-2481 行),用户通过公共头文件 include/pto/pto-inst.hpp 引入:
template <typename TileDataDst, typename TileDataSrc, typename... WaitEvents> PTO_INST RecordEvent TORS(TileDataDst &dst, TileDataSrc &src, typename TileDataDst::DType scalar, WaitEvents &... events);参数说明:
| 参数 | 含义 |
|---|---|
dst | 目标 Tile,结果写入对象,类型TileDataDst |
src | 源 Tile,参与运算的操作数,类型TileDataSrc |
scalar | 标量操作数,类型为TileDataDst::DType(即与dst元素类型一致) |
events... | 变长的等待事件列表,用于建立指令间的数据依赖(可选) |
返回值类型为PTO_INST RecordEvent,即调用会返回一个事件对象,可继续传递给后续指令以构成依赖链。从源码看,函数体先通过detail::PtoWaitEvents(events...)等待传入事件,再经MAP_INSTR_IMPL(TORS, dst, src, scalar)宏根据编译目标平台分发到对应的TORS_IMPL实现:
template <typename TileDataDst, typename TileDataSrc, typename... WaitEvents> PTO_INST RecordEvent TORS(TileDataDst& dst, TileDataSrc& src, typename TileDataDst::DType scalar, WaitEvents&... events) { detail::PtoWaitEvents(events...); MAP_INSTR_IMPL(TORS, dst, src, scalar); return {}; }事件(Event)机制
TORS返回RecordEvent,可与TLOAD、TSTORE等指令通过Event<Op, Op>模板建立流水线依赖。在 A5 平台测试内核 中可以清晰看到这种用法:
Event<Op::TLOAD, Op::TORS> event0; Event<Op::TORS, Op::TSTORE_VEC> event1; event0 = TLOAD(src0Tile, src0Global); event1 = TORS(dstTile, src0Tile, src1, event0); // 等待 TLOAD 完成后才执行 TSTORE(dstGlobal, dstTile, event1); // 等待 TORS 完成后才执行这种"事件即依赖"的编程模型让编译器/运行时可以在保证数据正确性的前提下对指令进行流水线调度与重排,是 PTO 高性能编程的核心机制之一。
多平台实现与底层原理
MAP_INSTR_IMPL宏会将TORS分发到目标平台的TORS_IMPL,仓库中至少有三套实现,分别对应 CPU 仿真、A2A3 系列与 A5 系列。
CPU 实现(仿真/调试)
CPU 仿真实现在 include/pto/cpu/TBinSOps.hpp(第 233-237 行),直接复用通用的"一元 Tile-标量算子"实现框架:
template <typename TileDst, typename TileSrc> PTO_INTERNAL void TORS_IMPL(TileDst& dst, TileSrc& src, typename TileSrc::DType scalar) { UnaryTileScalarOpImpl<TileDst, TileSrc, ElementOp::OP_ORS>(dst, src, scalar); }这里通过模板参数ElementOp::OP_ORS指定运算类型,与TANDS(OP_ANDS)、TXORS(OP_XORS)等共用同一套UnaryTileScalarOpImpl基础设施,体现了标量位运算指令族的统一设计。
A2A3 实现(Atlas A2/A3 训练与推理系列产品)
A2A3 平台的实现在 include/pto/npu/a2a3/TBitwiseSOp.hpp(第 110-120 行)。它并不是一条硬件指令直接完成,而是将 TORS 分解为"广播标量 + Tile 间按位或"两条子操作:
template <typename TileDataDst, typename TileDataSrc> PTO_INTERNAL void TORS_IMPL(TileDataDst& dst, TileDataSrc& src, typename TileDataSrc::DType scalar) { #ifndef __PTO_AUTO__ PTO_ASSERT( dst.data() != src.data(), "Setting the source Tile and destination Tile to the same memory is unsupported"); #endif TEXPANDS_IMPL(dst, scalar); // 将标量广播展开为向量 pipe_barrier(PIPE_V); // 向量流水线屏障,保证广播完成 TOR_IMPL(dst, src, dst); // dst = src | dst(Tile 间按位或) }实现细节值得注意:
- 先调用
TEXPANDS_IMPL把标量展开成与 Tile 形状匹配的向量(写入dst),再调用TOR_IMPL(dst, src, dst)完成dst = src | dst; - 两步之间通过
pipe_barrier(PIPE_V)(向量管道屏障)保证流水线顺序; - 在手动模式(非
__PTO_AUTO__)下,通过PTO_ASSERT检查dst与src不能指向同一块内存,否则编译期即报错。
A5 实现(Ascend 950PR/Ascend 950DT)
A5 平台的实现在 include/pto/npu/a5/TOrS.hpp(第 40-78 行),是一套更完备的独立实现:
template <typename TileDataDst, typename TileDataSrc> PTO_INTERNAL void TORS_IMPL(TileDataDst& dst, TileDataSrc& src0, typename TileDataSrc::DType src1) { using T = typename TileDataDst::DType; static_assert( sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "Fix: TORS has invalid data type."); static_assert(TileDataDst::isRowMajor && TileDataSrc::isRowMajor, "Fix: TORS only support row major layout."); static_assert( std::is_same_v<T, typename TileDataSrc::DType>, "Fix: TORS input tile src0, src1 and dst tile data type mismatch."); unsigned validRow = dst.GetValidRow(); unsigned validCol = dst.GetValidCol(); PTO_ASSERT( src0.GetValidRow() == validRow && src0.GetValidCol() == validCol, "Fix: TORS input tile src0 valid shape mismatch with output tile dst shape."); TOrS<T, TileDataDst, TileDataSrc>(dst.data(), src0.data(), src1, validRow, validCol); }其底层按位或逻辑在TOrS中通过BinaryInstr<OrSOp<T>, ...>驱动vor向量指令完成;当元素类型为 64 位整型(int64_t/uint64_t)时,走专用的Int64Scalar<Int64Op::Or, ...>路径处理,以适配 64 位数据的指令宽度约束。
使用约束与有效区域
平台约束
官方文档(docs/isa/TORS.md)对两个平台分别给出约束,与上述源码中的static_assert/PTO_ASSERT一一对应:
A2A3 系列(Atlas A2/A3 训练与推理系列产品):
- 适用于整数元素类型;
dst与src必须使用相同的元素类型;dst与src必须是向量 Tile(TileType::Vec);- 运行时要求
src.GetValidRow() == dst.GetValidRow()且src.GetValidCol() == dst.GetValidCol(); - 手动模式下,不支持将源 Tile 与目标 Tile 设置为同一块内存。
A5 系列(Ascend 950PR/Ascend 950DT):
- 适用于
TEXPANDS与TOR所支持的整数元素类型; dst与src必须使用相同的元素类型;dst与src必须是向量 Tile;- 手动模式下,不支持将源 Tile 与目标 Tile 设置为同一块内存。
从 A5 源码 还可以看到额外约束:static_assert要求元素大小为 1/2/4/8 字节,并要求dst、src均为 RowMajor 布局(TORS only support row major layout),运行时还校验源与目标的 valid shape 必须一致。
有效区域(Valid Region)
TORS 的迭代域由目标 Tile 的有效区域决定:指令以dst.GetValidRow()/dst.GetValidCol()作为遍历范围,源 Tile 的有效区域只需与之相等即可(由运行时断言保证),超出有效区域之外的数据不参与运算。因此在使用时,应通过 Tile 构造参数或设置 valid 行列数来精确控制参与运算的数据范围。
编程示例
基础调用
文档示例(docs/isa/TORS.md)展示了最简调用方式——定义 16×16 的 uint16 向量 Tile 并执行按位或:
#include <pto/pto-inst.hpp> using namespace pto; void example() { using TileDst = Tile<TileType::Vec, uint16_t, 16, 16>; using TileSrc = Tile<TileType::Vec, uint16_t, 16, 16>; TileDst dst; TileSrc src; TORS(dst, src, 0xffu); }完整的 Kernel 调用链
参照 CPU 测试内核,一个完整的 TORS 使用流程是:定义全局张量 → 绑定 Tile 内存(TASSIGN)→TLOAD载入数据 →TORS计算 →TSTORE写回:
#include <pto/pto-inst.hpp> #include <pto/common/constants.hpp> using namespace pto; template <typename T, int kGRows_, int kGCols_, int kTRows_, int kTCols_> AICORE void runTOrs(__gm__ T __out__* out, __gm__ T __in__* src, __gm__ T __in__* scalar) { using DynShapeDim5 = Shape<1, 1, 1, kGRows_, kGCols_>; using DynStridDim5 = Stride<1, 1, 1, kGCols_, 1>; using GlobalData = GlobalTensor<T, DynShapeDim5, DynStridDim5>; using TileData = Tile<TileType::Vec, T, kTRows_, kTCols_, BLayout::RowMajor, -1, -1>; TileData srcTile(kTRows_, kTCols_); TileData dstTile(kTRows_, kTCols_); GlobalData srcGlobal(src); GlobalData dstGlobal(out); TASSIGN(srcTile, 0); TASSIGN(dstTile, kTRows_ * kTCols_ * sizeof(typename TileData::DType)); TLOAD(srcTile, srcGlobal); TORS(dstTile, srcTile, scalar[0]); TSTORE(dstGlobal, dstTile); out = dstGlobal.data(); }手动模式与自动模式
TORS 支持两种资源管理模式:
- 自动模式(Auto Mode):由编译器/运行时负责 Tile 的资源放置与调度,用户只需写出 SSA 形式即可:
# Auto mode: compiler/runtime-managed placement and scheduling. %dst = pto.tors %src, %scalar : (!pto.tile<...>, dtype) -> !pto.tile<...>- 手动模式(Manual Mode):需要先用
pto.tassign将操作数显式绑定到具体地址,再发射指令:
# Manual mode: resources must be bound explicitly before issuing the instruction. # Optional for tile operands: # pto.tassign %arg0, @tile(0x1000) # pto.tassign %arg1, @tile(0x2000) %dst = pto.tors %src, %scalar : (!pto.tile<...>, dtype) -> !pto.tile<...>手动模式下同一内存绑定会触发前述的PTO_ASSERT检查(dst.data() != src.data()),这正是文档"不支持源与目标同内存"约束的落地之处。
测试与验证
仓库为 TORS 提供了覆盖多平台、多类型、多形状的完整测试集,可用作正确性验证与性能调优的参照:
| 测试位置 | 覆盖内容 |
|---|---|
| tests/cpu/st/testcase/tors/ | CPU 仿真侧,含main.cpp(gtest 用例与 golden 比对)、tors_kernel.cpp(内核实现)、gen_data.py(测试数据生成) |
| tests/npu/a2a3/src/st/testcase/tors/ | A2A3 系列产品侧测试 |
| tests/npu/a5/src/st/testcase/tors/ | A5 系列产品侧测试 |
以 CPU 测试 为例,测试流程为:ACL 初始化 → 分配 host/device 内存 → 读取input1.bin与scalar.bin→ 拷贝到 device → 启动内核 → 回拷结果 → 与golden.bin比对,最后通过ResultCmp<T>(golden, devFinal, 0.001f)断言结果一致。测试用例覆盖了int16_t、int32_t、uint32_t以及 64×64、16×256、77×96、8×32、12×128 等多种 global/tile 形状。
A5 侧测试 的覆盖更全面,其显式实例化展示了 TORS 对数据类型的支持矩阵:
- 无符号类型:
uint8_t、uint16_t、uint32_t、uint64_t; - 有符号类型:
int8_t、int16_t、int32_t、int64_t; - 形状覆盖:从常规的 64×64、32×32、16×16、8×8,到极端形状如
1×16384、2048×16、1×1024,以及非对齐形状(如 63×63、4×15 的 valid 区域)。
这从测试角度印证了文档约束中"整数元素类型"的适用范围,也说明 TORS 可处理各类大/小、对齐/非对齐 Tile 形状。
与相关指令的关系
TORS 属于 PTO 的"标量位运算"指令族,与以下指令形成互补:
| 指令 | 语义 | 关系 |
|---|---|---|
TOR | Tile 与 Tile 的逐元素按位或 | TORS 的"A2A3 实现"在标量广播后复用其逻辑 |
TAND/TANDS | Tile 与 Tile / Tile 与标量的按位与 | 与 TORS 同族,CPU 实现共享UnaryTileScalarOpImpl框架 |
TXORS | Tile 与标量的按位异或 | 从 A2A3 源码 可见,其实现由TORS_IMPL+TANDS_IMPL+TNOT_IMPL+TAND_IMPL组合而成 |
TEXPANDS | 标量广播展开 | TORS 在 A2A3 平台上的前置子操作 |
TNOT | 逐元素按位取反 | 与 TORS/TAND 组合可构造任意位逻辑表达式 |
这种"指令组合成新指令"的设计在 A2A3 的TXORS_IMPL中体现得尤为明显:TXORS = (TORS) 取反后与 (TANDS) 做与,说明位运算指令族共享底层vor/vand/vnot向量指令,用户也可以按相同思路在算子中组合这些内建接口实现更复杂的位操作。
小结
TORS 是 PTO 中实现"向量 Tile 与标量按位或"的入口指令,其核心要点可归纳为:
- 语义:
dst[i][j] = src[i][j] | scalar,逐元素、整型专用; - 接口:C++ 侧通过
TORS(dst, src, scalar, events...)调用,返回RecordEvent支持事件依赖链;汇编侧提供 SSA 与 DPS 两种形式; - 实现:CPU 走
UnaryTileScalarOpImpl框架,A2A3 分解为"标量广播 + Tile 间或",A5 通过OrSOp/vor直接执行,64 位数据有专门路径; - 约束:要求整型、向量 Tile、行列有效区域一致、RowMajor(A5)、手动模式下源与目标不得同内存;
- 验证:CPU、A2A3、A5 三侧均有覆盖 8/16/32/64 位整型与多种形状的 golden 比对测试可供参考。
建议读者在编写涉及掩码、标志位置位、位域合并的向量算子时,将TORS与TAND/TOR/TNOT/TXORS组合使用,并借助Event机制构建高效的流水线依赖。
- 人工智能
- 指令集
- 算子库
- CANN
- Ascend
【免费下载链接】pto-isa
Parallel Tile Operation (PTO) is a virtual instruction set architecture designed by Ascend CANN, focusing on tile-level operations. This repository offers high-performance, cross-platform tile operations across Ascend platforms.
相关推荐
PTO ISA TORS 指令详解:Tile 与标量逐元素按位或操作
PTO ISA TORS 指令详解:Tile 与标量逐元素按位或操作 导读 本文深入解析 CANN PTO(Parallel Tile Operation)虚拟
人工智能指令集算子库CANNAscendCANN PTO-ISA TSUBS 指令详解:Tile 逐元素减标量的汇编语法、C++ 内建接口与多平台实现
CANN PTO ISA TSUBS 指令详解:Tile 逐元素减标量的汇编语法、C++ 内建接口与多平台实现 TSUBS(Tile Subtract Scal
人工智能指令集算子库CANNAscendCANN pto-isa TANDS 指令详解:Tile 与标量按位与(Bitwise AND with Scalar)的实现与使用
CANN pto isa TANDS 指令详解:Tile 与标量按位与(Bitwise AND with Scalar)的实现与使用 导读 TANDS 是 CA
人工智能指令集算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考