news 2026/9/19 23:51:57

PTO TORS 指令详解:Tile 与标量按位或(Elementwise Bitwise OR)的语法、内建接口与多平台实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PTO TORS 指令详解:Tile 与标量按位或(Elementwise Bitwise OR)的语法、内建接口与多平台实现
  • 人工智能
  • 指令集
  • 算子库
  • 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.

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

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<...>, i32

AS 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,可与TLOADTSTORE等指令通过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 间按位或) }

实现细节值得注意:

  1. 先调用TEXPANDS_IMPL把标量展开成与 Tile 形状匹配的向量(写入dst),再调用TOR_IMPL(dst, src, dst)完成dst = src | dst
  2. 两步之间通过pipe_barrier(PIPE_V)(向量管道屏障)保证流水线顺序;
  3. 在手动模式(非__PTO_AUTO__)下,通过PTO_ASSERT检查dstsrc不能指向同一块内存,否则编译期即报错。

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 训练与推理系列产品):

  • 适用于整数元素类型;
  • dstsrc必须使用相同的元素类型;
  • dstsrc必须是向量 Tile(TileType::Vec);
  • 运行时要求src.GetValidRow() == dst.GetValidRow()src.GetValidCol() == dst.GetValidCol()
  • 手动模式下,不支持将源 Tile 与目标 Tile 设置为同一块内存。

A5 系列(Ascend 950PR/Ascend 950DT):

  • 适用于TEXPANDSTOR所支持的整数元素类型;
  • dstsrc必须使用相同的元素类型;
  • dstsrc必须是向量 Tile;
  • 手动模式下,不支持将源 Tile 与目标 Tile 设置为同一块内存。

从 A5 源码 还可以看到额外约束:static_assert要求元素大小为 1/2/4/8 字节,并要求dstsrc均为 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.binscalar.bin→ 拷贝到 device → 启动内核 → 回拷结果 → 与golden.bin比对,最后通过ResultCmp<T>(golden, devFinal, 0.001f)断言结果一致。测试用例覆盖了int16_tint32_tuint32_t以及 64×64、16×256、77×96、8×32、12×128 等多种 global/tile 形状。

A5 侧测试 的覆盖更全面,其显式实例化展示了 TORS 对数据类型的支持矩阵:

  • 无符号类型:uint8_tuint16_tuint32_tuint64_t
  • 有符号类型:int8_tint16_tint32_tint64_t
  • 形状覆盖:从常规的 64×64、32×32、16×16、8×8,到极端形状如1×163842048×161×1024,以及非对齐形状(如 63×63、4×15 的 valid 区域)。

这从测试角度印证了文档约束中"整数元素类型"的适用范围,也说明 TORS 可处理各类大/小、对齐/非对齐 Tile 形状。

与相关指令的关系

TORS 属于 PTO 的"标量位运算"指令族,与以下指令形成互补:

指令语义关系
TORTile 与 Tile 的逐元素按位或TORS 的"A2A3 实现"在标量广播后复用其逻辑
TAND/TANDSTile 与 Tile / Tile 与标量的按位与与 TORS 同族,CPU 实现共享UnaryTileScalarOpImpl框架
TXORSTile 与标量的按位异或从 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 与标量按位或"的入口指令,其核心要点可归纳为:

  1. 语义dst[i][j] = src[i][j] | scalar,逐元素、整型专用;
  2. 接口:C++ 侧通过TORS(dst, src, scalar, events...)调用,返回RecordEvent支持事件依赖链;汇编侧提供 SSA 与 DPS 两种形式;
  3. 实现:CPU 走UnaryTileScalarOpImpl框架,A2A3 分解为"标量广播 + Tile 间或",A5 通过OrSOp/vor直接执行,64 位数据有专门路径;
  4. 约束:要求整型、向量 Tile、行列有效区域一致、RowMajor(A5)、手动模式下源与目标不得同内存;
  5. 验证:CPU、A2A3、A5 三侧均有覆盖 8/16/32/64 位整型与多种形状的 golden 比对测试可供参考。

建议读者在编写涉及掩码、标志位置位、位域合并的向量算子时,将TORSTAND/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.

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

相关推荐

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 23:49:57

给 Hermes Desktop 装上跨会话记忆:Hindsight 记忆配置完整指南

给 Hermes Desktop 装上跨会话记忆&#xff1a;Hindsight 记忆配置完整指南 【免费下载链接】hindsight Hindsight: Agent Memory That Learns 项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight Hermes Desktop 是 Nous Research 推出的 Hermes Age…

作者头像 李华
网站建设 2026/9/19 23:49:38

PowerDesigner16 的 comment 不显示?TaoToken 这样让 Codex 查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 23:44:20

AI 论文降重改写,几款常用降AIGC网站怎么选才最稳妥

摘要&#xff1a;本文围绕论文写作中的改写与降重需求&#xff0c;比较了几款常见的AI辅助工具&#xff0c;从改写能力、语言润色、引用规范等维度做横向梳理&#xff0c;并给出按写作阶段和语种匹配的选型思路。结论是先看清自己卡在改写还是润色&#xff0c;再决定用哪一类工…

作者头像 李华
网站建设 2026/9/19 23:44:13

5款AI写论文哪个好?我拿毕业论文实测了一圈,答案有点意外

aigcbiye官网www.aigcbiye.com 微信公众号搜一搜 aigcbiye 做论文写作科普这几年&#xff0c;被问最多的问题就是“到底哪款AI写论文工具靠谱”。 网上的答案基本两类&#xff1a;一类是拿着通用大模型当论文工具吹&#xff0c;另一类是收了推广费闭眼说好话。但写论文这件事…

作者头像 李华
网站建设 2026/9/19 23:44:06

Claw 生态横评:OpenClaw 的多 Agent 协作,Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 23:44:02

三菱PLC电气控制入门:从低压电器到梯形图编程实战

简介&#xff1a;课件围绕中职电气控制基础与PLC技术应用课程&#xff0c;面向中职学生、电气自动化初学者及三菱PLC入门者。内容先讲低压电器与典型电气控制电路&#xff0c;再引入PLC定义、硬件结构、扫描周期&#xff0c;并以三菱FX2N系列为载体讲解编程软元件、基本逻辑指令…

作者头像 李华