尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CANN pto-isa TXORS 指令详解:Tile 与标量逐元素按位异或的跨平台实现

CANN pto-isa TXORS 指令详解:Tile 与标量逐元素按位异或的跨平台实现 CANN pto-isa TXORS 指令详解Tile 与标量逐元素按位异或的跨平台实现【免费下载链接】pto-isaParallel 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.项目地址: https://gitcode.com/cann/pto-isa导读本文深入解析 CANN pto-isaParallel Tile Operation ISA虚拟指令集中的TXORS指令——它实现 Tile 与一个标量之间的逐元素按位异或XOR运算。文章以 docs/isa/TXORS.md 为骨架从数学语义、三层汇编语法PTO 汇编 / AS Level 1 SSA / AS Level 2 DPS、C 内建函数签名与调用方式到 A2A3 与 A5 两条硬件后端在临时空间tmp使用上的关键差异逐一展开并结合 include/pto/cpu/TBinSOps.hpp、include/pto/npu/a2a3/TBitwiseSOp.hpp、include/pto/npu/a5/TXorS.hpp 等源码及 CPU/A5 测试用例给出可复制、可验证的编程范式与约束清单。读完本文你将掌握在 pto-isa 中编写标量位运算 Tile kernel 的完整方法理解不同芯片后端在指令实现与资源要求上的差异并能通过仓库内现有测试用例快速验证自己的实现。指令概览TXORS属于Tile-Scalar / Tile-Immediate类指令在指令清单 docs/isa/manifest.yaml 中的定义为Elementwise bitwise XOR of a tile and a scalar.Tile 与标量的逐元素按位异或。其操作数为dst、src、scalar三个语义直观把 Tile 中的每个元素与同一个标量按位异或后写入目标 Tile。数学语义对有效区域valid region内的每一个元素(i, j)运算定义为$$ \mathrm{dst}{i,j} \mathrm{src}{i,j} \oplus \mathrm{scalar} $$其中src是源 Tilescalar是与元素类型一致的标量立即数dst为输出 Tile。该运算在有效区域内逐元素执行不涉及跨行/跨列的归约属于典型的 element-wise逐元素操作——源码中TXOR的实现也标注了OP_TYPE(element_wise)见 include/pto/npu/a5/TXorS.hpp。汇编语法从 PTO 汇编到 DPS 三级表达TXORS在 pto-isa 中按照抽象层次分为三级表示便于编译器、运行时与底层调度器逐级降级。PTO 汇编同步形式%dst txors %src, %scalar : !pto.tile..., i32这是最贴近硬件的助记符形式txors接收一个 Tile 操作数与一个i32类型的标量操作数输出新的 Tile。AS Level 1SSA 形式%dst pto.txors %src, %scalar : (!pto.tile..., dtype) - !pto.tile...SSA静态单赋值形式显式给出类型签名src的类型为!pto.tile...菱形占位符表示具体的形状与布局参数scalar的类型为dtype具体标量类型如i32、i16、u8等返回值仍为!pto.tile...。AS Level 2DPS 形式pto.txors ins(%src, %scalar : !pto.tile_buf..., dtype) outs(%dst : !pto.tile_buf...)DPSData Path Scheduler数据通路调度形式使用ins/outs显式声明输入输出缓冲区src与scalar为输入insdst为输出outs操作数类型从!pto.tile...细化为!pto.tile_buf...即已经绑定到具体片上缓冲区UB的 Tile。自动模式与手动模式的差异Auto Mode自动模式由编译器/运行时负责 Tile 的放置与调度开发者只需写指令本身%dst pto.txors %src, %scalar : (!pto.tile..., dtype) - !pto.tile...Manual Mode手动模式在发射指令前必须先通过pto.tassign把 Tile 操作数显式绑定到具体地址例如# Optional for tile operands: # pto.tassign %arg0, tile(0x1000) # pto.tassign %arg1, tile(0x2000) %dst pto.txors %src, %scalar : (!pto.tile..., dtype) - !pto.tile...这种两级编程模型与 pto-isa 的整体设计一致自动模式面向快速原型与框架集成手动模式面向需要精确控制片上存储布局的性能调优场景。C 内建函数IntrinsicTXORS的 C 内建函数声明于 include/pto/common/pto_instr.hpptemplate typename TileDataDst, typename TileDataSrc, typename TileDataTmp, typename... WaitEvents PTO_INST RecordEvent TXORS(TileDataDst dst, TileDataSrc src0, typename TileDataSrc::DType scalar, TileDataTmp tmp, WaitEvents ... events);参数说明参数含义dst目标 Tile类型TileDataDst承载运算结果src0源 Tile类型TileDataSrc被异或的数据scalar标量类型为TileDataSrc::DType即源 Tile 的元素类型tmp临时 Tile类型TileDataTmpA2A3 后端用作中间暂存A5 后端忽略详见下文events...变长的等待事件WaitEvents用于建立与前后指令的依赖关系返回值RecordEvent也可作为后续指令的依赖函数内部首先调用detail::PtoWaitEvents(events...)等待前置事件随后通过宏MAP_INSTR_IMPL(TXORS, dst, src0, scalar, tmp)分派到当前平台的具体实现CPU / A2A3 / A5 / CostModel最后返回RecordEvent。因此该内建函数天然支持异步流水例如在 A5 测试中常见TLOAD - TXORS - TSTORE_VEC的事件链见下文测试用例。完整调用示例以下示例来自 docs/isa/TXORS.md 的 Examples 小节使用uint32_t类型、16×16 的 Vec Tile#include pto/pto-inst.hpp using namespace pto; void example() { using TileDst TileTileType::Vec, uint32_t, 16, 16; using TileSrc TileTileType::Vec, uint32_t, 16, 16; using TileTmp TileTileType::Vec, uint32_t, 16, 16; TileDst dst; TileSrc src; TileTmp tmp; TXORS(dst, src, 0x1u, tmp); }要点三个 Tile 均使用TileType::Vec向量计算单元上的 Tile元素类型统一为uint32_t标量直接传字面量0x1u其类型须与TileDataSrc::DType一致tmp在 A2A3 上必须提供且形状与类型和dst一致在 A5 上会被忽略但为保持 API 兼容仍需传入。约束条件Constraints元素类型支持不同后端的支持范围不同这是跨平台移植时最需要关注的差异后端支持的元素类型A2A3uint8_t、int8_t、uint16_t、int16_t、uint32_t、int32_tA5上述六种之外额外支持int64_t、uint64_t源码层面A5 实现 include/pto/npu/a5/TXorS.hpp 通过static_assert(sizeof(T) 8 || sizeof(T) 4 || sizeof(T) 2 || sizeof(T) 1)校验 1/2/4/8 字节整数类型并用if constexpr将 64 位类型int64_t/uint64_t分流到Int64ScalarInt64Op::Xor, ...路径其余类型走通用BinaryInstrXorSOpT, ...路径include/pto/npu/a5/TXorS.hpp。类型一致性与形状匹配dst、src、tmp必须使用相同的元素类型A5 实现通过static_assert(std::is_same_vT, typename TileDataSrc::DType)在编译期强制dst与src类型一致include/pto/npu/a5/TXorS.hpp。A5 要求src.GetValidRow() / GetValidCol()与dst完全一致运行时以PTO_ASSERT校验include/pto/npu/a5/TXorS.hpp。布局要求A5 实现只支持行主序row majorTilestatic_assert(TileDataDst::isRowMajor TileDataSrc::isRowMajor)在编译期拒绝非行主序布局。内存不重叠要求A2A3 手动模式dst、src、tmp三块存储必须互不重叠。源码 include/pto/npu/a2a3/TBitwiseSOp.hpp 在非自动模式#ifndef __PTO_AUTO__下断言dst.data() ! src.data() dst.data() ! tmp.data() src.data() ! tmp.data()。A5从源码实现看dst与src0通过__cce_get_tile_ptr分别取指针tmp完全不参与计算因此不存在三块内存混用的风险。有效区域Valid Region语义指令以dst.GetValidRow()/dst.GetValidCol()作为迭代域即运算只覆盖目标 Tile 的有效行 × 有效列区域而不一定是物理分配的整块缓冲。这与 pto-isa 中逻辑形状Shape与物理缓冲Buffer分离的 Tile 模型一致也是支持非 32/16 对齐形状如 A5 测试中的64x63、4x15等的基础。临时空间Temporary SpaceA2A3 与 A5 的根本差异TXORS的接口签名中携带tmp参数但两个硬件后端对它的态度截然不同这是理解该指令实现原理的关键。A2A3tmp参与标量异或分解A2A3 后端的实现位于 include/pto/npu/a2a3/TBitwiseSOp.hpp。由于硬件向量指令集没有Tile 与标量直接异或的原生指令TXORS_IMPL把标量异或分解为四步位运算组合TORS_IMPL(tmp, src, scalar)先把scalar与src逐元素或结果存入tmppipe_barrier(PIPE_V)向量流水屏障保证上一步写完成TANDS_IMPL(dst, src, scalar)再把scalar与src逐元素与结果存入dstpipe_barrier(PIPE_V)TNOT_IMPL(dst, dst)对dst按位取反pipe_barrier(PIPE_V)TAND_IMPL(dst, dst, tmp)最后把取反结果与tmp逐元素与得到src ⊕ scalar。其数学依据是布尔代数恒等式 $a \oplus b (a \lor b) \land \lnot(a \land b)$。因此 A2A3 上tmp是必须的中间暂存且要求与dst同类型、同有效形状。这也是为什么 A2A3 约束手动模式下dst、src、tmp不能重叠——分解过程涉及对三块缓冲的读写交织。A5tmp仅为 API 兼容保留A5 后端实现位于 include/pto/npu/a5/TXorS.hpp。其核心是XorSOp操作类同文件 L21-L38构造函数中对标量执行vbr(reg_src1, scalar)即把标量广播进向量寄存器BinSInstr直接调用向量指令vxor((RegTensorU)reg_dst, (RegTensorU)reg_src0, (RegTensorU)reg_src1, preg)完成按位异或。也就是说 A5 用标量广播 vxor一条原生向量指令即可完成整个运算不需要任何 scratch Tile 存储。tmp之所以保留在 C 内建函数签名中纯粹是为了与 A2A3 保持 API 兼容避免上层 kernel 代码因平台差异改写调用形式。一个直观的佐证来自 A5 的测试用例 tests/npu/a5/src/st/testcase/txors/txors_kernel.cpp调用时直接把dstTile当作tmp传入event1 TXORS(dstTile, src0Tile, src1, dstTile /*not used*/, event0);并注释/*not used*/——即使tmp与dst指向同一块缓冲A5 实现也不会出错。这从实践上印证了A5 不使用 tmp的文档结论。源码级实现原理三条后端路径TXORS通过MAP_INSTR_IMPL宏根据编译目标分派到不同实现CPU 仿真路径CPU 后端实现在 include/pto/cpu/TBinSOps.hppTXORS_IMPL直接委托给UnaryTileScalarOpImplTileDst, TileSrc, ElementOp::OP_XORS后者按dst.GetValidRow()/GetValidCol()遍历有效区域对每个元素调用ElementOpCalT, OP_XORS::apply(dst[i], src[i], scalar)并支持行主序/列主序以及不同 SFractal 布局NoneBox与其他分形布局的寻址差异。值得注意CPU 路径对TXORS的分类是NO_CONSTRAINTinclude/pto/cpu/TBinSOps.hpp即不强制 RowMajor 或 Vec 类型比 NPU 路径更宽松。同时 CPU 的带tmp重载L245-L250直接忽略tmp与 A5 行为一致。CPU 测试位于 tests/cpu/st/testcase/txors/txors_kernel.cpp其 kernel 展示了完整的数据流GlobalTensor描述全局内存 5 维 shape/stride →TASSIGN给三个 Tile 分配不同的 UB 偏移 →TLOAD载入 →TXORS(dstTile, srcTile, scalar[0], tmpTile)→TSTORE写回。其中tmpTile被TASSIGN到独立的偏移2 * kTRows_ * kTCols_ * sizeof(T)体现了 A2A3 风格三块缓冲互不重叠的编程习惯。CostModel 路径仓库还提供了成本模型后端 include/pto/costmodel/pto_instr.hpp在__COSTMODEL编译选项下对指令进行周期仿真通过perf_sim命名空间的 recorder、tile_dep_tracker、latency 等模块。这意味着TXORS可以在未接入真实硬件前先通过性能仿真估算其开销相关用法可参考 docs/costmodel/perf-sim-user-guide_zh.md。测试与验证仓库内的可执行依据仓库为TXORS提供了跨 CPU 与多款 NPU 平台的软件测试ST用例是验证理解的最佳样本CPUtests/cpu/st/testcase/txors/main.cpp 中的TXORSTest用例覆盖int32_t、int16_t的 64×64 Tilegolden 数据对比使用ResultCmpT(golden, devFinal, 0.001f)A5tests/npu/a5/src/st/testcase/txors/txors_kernel.cpp 的实例化列表覆盖uint16_t、uint8_t、uint32_t、int8_t、int16_t、int32_t、int64_t、uint64_t等全部 A5 支持类型且包含多种形状正方形64x64、非对齐64x63、4x15、单行超长1x16384、1x1024、超高窄列2048x16等用于验证有效区域迭代与行主序 stride 的正确性A2A3 与 Kirin 系列在 tests/npu/a2a3/src/st/testcase/txors/、tests/npu/kirin9030/src/st/testcase/txors/、tests/npu/kirinDev0000/src/st/testcase/txors/ 等目录均有同名测试用例各含main.cpp、txors_kernel.cpp与数据生成脚本gen_data.py。每个测试用例目录下都有gen_data.py生成input1.bin、scalar.bin与golden.binmain.cpp通过 ACL 接口完成 host/device 内存管理、数据搬运与结果比对。测试调度可通过 tests/run_st.sh 或 tests/run_cpu_tests.sh 运行具体平台适配请参考 tests/README_zh.md。在 kernel 中串联异步事件A5 测试还演示了TXORS与事件机制的配合tests/npu/a5/src/st/testcase/txors/txors_kernel.cppEventOp::TLOAD, Op::TXORS event0; EventOp::TXORS, Op::TSTORE_VEC event1; event0 TLOAD(src0Tile, src0Global); event1 TXORS(dstTile, src0Tile, src1, dstTile /*not used*/, event0); TSTORE(dstGlobal, dstTile, event1);TLOAD返回的event0作为TXORS的等待事件TXORS返回的event1再交给TSTORE形成TLOAD → TXORS → TSTORE_VEC的流水依赖链保证数据在向量流水上按序流动。这也解释了内建函数签名中WaitEvents...与RecordEvent返回值的设计动机。常见问题与移植要点在 A5 上能否不传tmp不能省略参数但可以传任意同类型 Tile甚至直接传dstA5 实现不会读写它若代码需要同时兼容 A2A3 与 A5则必须为 A2A3 提供独立的、与dst/src不重叠的tmp。浮点类型是否支持不支持。TXORS只面向整数位运算A2A3/A5 支持类型均为有符号/无符号整数源码中的static_assert与文档约束一致。dst与src的 Tile 形状Shape可以不同吗有效形状必须一致否则 A5 的PTO_ASSERT会在运行时拦截但物理缓冲Buffer大小与布局可以不同迭代域以dst的有效区域为准。非对齐形状如 63 列可用吗可以。有效区域迭代 行主序 stride 的设计天然支持非 32/64 对齐的形状A5 测试用例中的64x63、4x15即为此类场景。如何快速验证复用仓库测试直接参考对应平台tests/.../txors/目录下的 kernel 与 golden 数据生成脚本或对照 docs/isa/TXORS.md 与 docs/isa/manifest.yaml 检查指令语义一致性仓库还提供 docs/tools/check_isa_consistency.py 这类一致性校验工具可延伸用于指令文档与实现核对。总结TXORS是 pto-isa 中实现Tile ⊕ 标量的标准指令数学语义简单但跨平台实现路径差异显著——A2A3 通过或、与、取反、与四步组合完成标量异或分解必须提供独立的tmp暂存A5 则借助vbr标量广播与原生vxor向量指令一步到位tmp仅为 API 兼容而保留。理解这一差异是编写可移植、高性能 pto-isa kernel 的基础。开发者可依据本文的语法、约束与测试样例在 CPU 仿真、A2A3、A5 等任意目标上快速落地并验证自己的位运算 Tile kernel。【免费下载链接】pto-isaParallel 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.项目地址: https://gitcode.com/cann/pto-isa创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表