- 人工智能
- 指令集
- 算子库
- 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.
TFILLPAD 是 CANN PTO-ISA(Parallel Tile Operation 虚拟指令集)中的 Tile 级数据填充指令:它将源 Tile 复制到目标 Tile,并在运行时有效区域(Valid Region)之外,用编译期确定的 PadValue 位模式填充剩余元素,从而在完整静态 Tile 形状上物化确定值。本文以 docs/isa/TFILLPAD.md 为骨架,结合仓库内 CPU 模拟器与 NPU(A5/A2A3)后端的真实实现和测试用例,系统讲解其数学语义、三档汇编语法、C++ Intrinsic 接口、Normal/InPlace/Expand 三种模式、PadValue 位模式映射表及全部编译期约束,并给出可直接编译运行的示例代码,帮助算子开发者在处理动态形状补齐、边界值初始化、低精度量化填充等场景时正确选型与使用。
指令概述:为什么需要 TFILLPAD
在 Tile 编程模型中,Tile 的静态形状(Rows/Cols,编译期确定,决定内存分配与寻址)与有效形状(GetValidRow()/GetValidCol(),运行期确定,表示真实数据范围)往往不一致。例如处理非对齐的矩阵行、动态 batch 的最后一块等场景时,Tile 中超出有效区域的部分包含未定义数据。后续算子(如 TMATMUL、TSTORE、归约类指令)通常要求输入拥有完整的静态形状,直接对"脏数据"运算会污染结果。
TFILLPAD 正是解决这一问题的指令:它把源 Tile 的有效数据复制到目标 Tile,并在其余位置写入由TileDataDst::PadVal在编译期选定的填充值(如PadValue::Min/PadValue::Max/PadValue::Zero,甚至是自定义位模式),实现"确定性地物化有效区域之外的值,使后续操作能在完整静态 Tile 形状上安全运算"。这一设计在 PTO-ISA 中与 TFILLPAD_EXPAND.md、TFILLPAD_INPLACE.md 两个变体指令共同组成完整族系。
数学语义
设VR = src.GetValidRow(),VC = src.GetValidCol(),即源 Tile 的有效行数和有效列数。对目标 Tile 的每个元素(i, j),TFILLPAD 定义如下:
$$ \mathrm{dst}{i,j} = \begin{cases} \mathrm{src}{i,j} & \text{if } i < VR \text{ and } j < VC \ \mathrm{pad} & \text{otherwise} \end{cases} $$
即:有效区域[0, VR) × [0, VC)内的元素逐元素拷贝(不做任何算术变换),其余元素统一写入pad。pad的具体取值由TileDataDst::PadVal与元素类型共同决定:浮点类型通常取±inf(IEEE 语义),整型取std::numeric_limits<T>::max()/min()或0,低精度浮点(fp8/fp4)则使用有限极值或 HiF8 的±inf位模式,详见下文 PadValue 填充值映射。
从 CPU 参考实现可以看到这一语义的直白表达,include/pto/cpu/TFillPad.hpp 中的TFillPad模板对每个目标元素判断if (i < validSrcRow && j < validSrcCol),命中则dst.SetElement(i, j, src.GetElement(i, j)),否则写入解码后的padVal。NPU 侧则通过向量指令将"有效拷贝 + 尾部填充"拆成两段执行,避免逐元素分支(见后文 多后端实现剖析)。
汇编语法
TFILLPAD 在 PTO-ISA 的多个抽象层级上有对应形式:
- 同步形式(概念性):
%dst = tfillpad %src : !pto.tile<...> -> !pto.tile<...> - AS Level 1(SSA 形式):
%dst = pto.tfillpad %src : !pto.tile<...> -> !pto.tile<...> - AS Level 2(DPS 形式,显式区分输入/输出缓冲区):
pto.tfillpad ins(%src : !pto.tile_buf<...>) outs(%dst : !pto.tile_buf<...>)其中 Level 1 面向编译器/调度器的 SSA 中间表示,操作数类型为抽象的!pto.tile<...>;Level 2 面向资源已绑定的目标机表示,操作数为!pto.tile_buf<...>缓冲区类型。两种形式描述的是同一指令在不同抽象层级的投影。
C++ Intrinsic 接口
TFILLPAD 的 C++ 内建接口由公共指令头 include/pto/common/pto_instr.hpp 声明,后端实现由include/pto/common/pto_instr_impl.hpp引入的架构相关头文件(CPU/A2A3/A5)提供。接口通过 SFINAE 分为两个重载,分别面向 Vec 与 Mat 两类 Tile:
// 重载一:Vec 类型 Tile,模板参数可指定 PadVal 与模式 template <typename TileData, PadValue PadVal = PadValue::Zero, typename... WaitEvents> PTO_INST RecordEvent TFILLPAD(TileData &dst, TileData &src, WaitEvents &... events); template < TFillPadMode mode = TFillPadMode::Normal, typename DstTileData, typename SrcTileData, typename... WaitEvents> PTO_INST RecordEvent TFILLPAD(DstTileData &dst, SrcTileData &src, WaitEvents &... events); // 重载二:Mat 类型 Tile(仅限 TileType::Mat) template < typename TileData, PadValue PadVal = PadValue::Zero, std::enable_if_t<(TileData::Loc == TileType::Mat), int> = 0, typename... WaitEvents> PTO_INST RecordEvent TFILLPAD(TileData &dst, TileData &src, WaitEvents &... events);所有重载返回RecordEvent并接受可变的WaitEvents&...事件参数(调用前通过detail::PtoWaitEvents等待同步),保持与 PTO 其他指令一致的异步事件模型。Vec 重载的mode模板参数选择操作变体,对应的模式枚举定义在 include/pto/common/type.hpp:
| 模式 | 枚举值 | 语义与形状要求 |
|---|---|---|
TFillPadMode::Normal | 0 | 目标与源 Tile 的静态形状必须完全一致(Rows/Cols相等) |
TFillPadMode::InPlace | 1 | 目标与源必须别名同一块存储(原地操作) |
TFillPadMode::Expand | 2 | 目标静态形状允许大于源(Dst::Rows >= Src::Rows且Dst::Cols >= Src::Cols) |
TFILLPAD_INPLACE与TFILLPAD_EXPAND仍是可用的一等接口,内部只是转发到带模式的通用入口:
template <typename DstTileData, typename SrcTileData, typename... WaitEvents> PTO_INST RecordEvent TFILLPAD_INPLACE(DstTileData &dst, SrcTileData &src, WaitEvents &... events) { return TFILLPAD<TFillPadMode::InPlace>(dst, src, events...); } template <typename DstTileData, typename SrcTileData, typename... WaitEvents> PTO_INST RecordEvent TFILLPAD_EXPAND(DstTileData &dst, SrcTileData &src, WaitEvents &... events) { return TFILLPAD<TFillPadMode::Expand>(dst, src, events...); }若传入非法模式,通用入口中的static_assert("TFILLPAD: invalid mode.")会在编译期直接报错。Vec 与 Mat 两个重载由std::enable_if_t依据TileData::Loc是否为TileType::Mat区分,互不冲突。
PadValue 填充值映射
PadValue枚举(定义于 include/pto/common/type.hpp)采用uint64_t作为底层类型,从而能够承载自定义位模式:
enum class PadValue : uint64_t { Null = 0, Zero = 1, Max = 2, Min = 3, // CustomBase marks the start of custom values (bit 32 set) CustomBase = 0x100000000ULL, };内置的Zero/Min/Max为类型相关的位模式,查表实现位于include/pto/common/constants.hpp中的PadValueMap<DType, PadVal>模板特化族;PadValue::Null恒为 0;自定义值PadValueCustom(...)(及其辅助函数PadCustom<...>)则把原始位直接透传。完整映射如下(Vec 类型):
| DType | Zero | Min | Max | Notes |
|---|---|---|---|---|
float/half/bfloat16_t | 0 | -inf | +inf | IEEE inf |
| integer types | 0 | type min | type max | |
float8_e4m3_t | 0x00 | 0xFE | 0x7E | no inf; finite max/min |
float8_e5m2_t | 0x00 | 0xFC | 0x7C | ±inf |
hifloat8_t | 0x00 | 0xEF | 0x6F | HiF8±inf(S1101111) |
float4_e2m1x2_t | 0x00 | 0xFF | 0x77 | 两个 nibble 均为-6/+6 |
float4_e1m2x2_t | 0x00 | 0xFF | 0x77 | 两个 nibble 均为有限 min/max |
使用注意点:
float8_e8m0_t没有 Zero/Min/Max 语法糖,只能通过PadValueCustom指定;- 低精度映射(fp8/fp4)仅适用于 A5 后端(CPU 模拟器对 fp8/fp4 也提供支持),
hifloat8_t为 A5 专属类型; - 对
bfloat16_t,CPU 模拟器默认将 bf16 别名到half(复用 half 的映射表);若为独立的标准std::bfloat16_t,则回退到std::numeric_limits路径(见 include/pto/cpu/TFillPad.hpp 中的if constexpr分支)。
自定义位模式的典型用法在测试 tests/cpu/st/testcase/tfillpad/tfillpad_kernel.cpp 中给出:
// Custom pad value constant for -1.0f (bit pattern 0xBF800000) constexpr PadValue PadCustomNeg1 = PadValueCustom(-1.0f); constexpr PadValue PadCustomNeg1_Half = PadValueCustom16(0xBC00); // fp16 -1.0编译期约束
TFILLPAD 对类型、形状与布局有严格的编译期(static_assert)约束,违反即编译失败:
- Vec 类型重载:
TileDataDst::PadVal != PadValue::Null(目标填充值不能为 Null)。 - 类型一致性:
sizeof(TileDataDst::DType) == sizeof(TileDataSrc::DType),且元素大小必须为1、2或4字节。打包类型fp4x2按 1 字节 DType 计(每元素两个 nibble),与s8/u8同级;在 A5 上,fp4x2的ValidCol/Cols按 nibble 计数(与 TLOAD/TSTORE/TCVT 一致),填充长度为ceil(Cols/2)个打包字节。 TFILLPAD(Normal):TileDataDst::Rows/Cols必须与TileDataSrc::Rows/Cols完全一致,见 CPU 实现中"TFillPad: dst and src should have the same rows/cols!"断言(include/pto/cpu/TFillPad.hpp)。TFILLPAD_EXPAND:TileDataDst::Rows >= TileDataSrc::Rows且TileDataDst::Cols >= TileDataSrc::Cols,目标只允许比源大或相等(include/pto/cpu/TFillPad.hpp)。- Mat 类型重载:当
TileData::TileType == Mat时,布局必须满足!TileData::isRowMajor && TileData::SLayout::RowMajor(即 NZ 布局),且PadVal必须为PadValue::Zero或PadValue::Null。该 Mat 重载与首条 Vec 重载(PadVal != PadValue::Null)分属不同 SFINAE 重载,二者并不矛盾。
这些约束在 NPU A5 后端同样以static_assert形式存在(include/pto/npu/a5/TFillPad.hpp 与 L233-L240),其中 Mat 路径的报错信息明确提示"dst matTile now only support NZ layout",帮助开发者在双端保持一致行为。
实战示例
以下示例直接取自指令文档,编译时只需包含统一的指令头pto/pto-inst.hpp并using namespace pto;:
#include <pto/pto-inst.hpp> using namespace pto; void example1() { // Vec 类型:源与目标静态形状均为 16x16,目标额外指定 SLayout 与 PadValue::Min using SrcT = Tile<TileType::Vec, float, 16, 16>; using DstT = Tile<TileType::Vec, float, 16, 16, BLayout::RowMajor, 16, 16, SLayout::NoneBox, TileConfig::fractalABSize, PadValue::Min>; SrcT src; DstT dst; TFILLPAD(dst, src); // 有效区域拷贝,其余填充 -inf } void example2() { // Mat 类型:NZ 布局矩阵,PadValue 取默认 Zero using TileMatData = Tile<TileType::Mat, float, 16, 256, BLayout::ColMajor, 1, 224, SLayout::RowMajor, 512>; TileMatData matTile; TFILLPAD(matTile, matTile); }example1演示 Vec 填充:PadValue::Min在TileDataDst的模板参数列表中指定,因此调用处无需再传 PadVal 模板参数,直接TFILLPAD(dst, src)即可将有效区域外的 float 元素填充为-inf。example2演示 Mat 重载:Tile<TileType::Mat, ...>使用列主布局(BLayout::ColMajor)配合SLayout::RowMajor分形,满足 NZ 布局约束,PadVal保持默认PadValue::Zero,且原地使用同一 Tile 作为源与目标。
仓库测试 tests/cpu/st/testcase/tfillpad/(含tfillpad_kernel.cpp、main.cpp与README.md)覆盖了静态/动态形状、RowMajor/ColMajor、PadValue::Null/Min/Max/自定义值、inplace与expand等组合,是阅读 TFILLPAD 用法的第一手参考。
ASM 形式示例
自动模式(Auto Mode)
自动模式下,Tile 的放置与调度由编译器/运行时管理,指令以 SSA 形式直接发射:
# Auto mode: compiler/runtime-managed placement and scheduling. %dst = pto.tfillpad %src : !pto.tile<...> -> !pto.tile<...>手动模式(Manual Mode)
手动模式下,资源必须在使用前显式绑定。对 Tile 操作数,可选地先用pto.tassign将参数绑定到具体 tile 缓冲区地址:
# 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.tfillpad %src : !pto.tile<...> -> !pto.tile<...>PTO 汇编形式
%dst = pto.tfillpad %src : !pto.tile<...> -> !pto.tile<...> # AS Level 2 (DPS) pto.tfillpad ins(%src : !pto.tile_buf<...>) outs(%dst : !pto.tile_buf<...>)多后端实现剖析
TFILLPAD 在仓库中拥有 CPU 模拟器与 NPU(A2A3/A5)多套后端实现,源码结构清晰:
- CPU 参考实现include/pto/cpu/TFillPad.hpp:
TFILLPAD_IMPL系列模板先做static_assert形状检查,随后调用TFillPad核心函数。后者通过GetPadValue<TileDataDst>()解码 PadValue 位模式,再经std::bit_cast按 4/2/1 字节宽度还原为元素值;拷贝循环使用cpu::parallel_for_1d并行化,并标注PTO_CPU_VECTORIZE_LOOP供向量化,模拟真实硬件并行行为。有效区域为 0 时直接返回,避免无意义拷贝。 - NPU A5 实现include/pto/npu/a5/TFillPad.hpp:Vec 路径按"三段式"展开——先用
vlds+vsts(带CreatePredicate谓词)逐行拷贝有效元素,再用vdup生成填充向量、vstus按POST_UPDATE写尾列,最后用vsts一次性写满剩余行;对fp4x2,行列跨度通过GetByteSize换算成打包字节数,确保与 TSTORE 的突发长度对齐。Mat 路径走 Cube 单元:通过pto_create_cbuf_matrix配置 repeat 参数([30:16]block 数、[46:32]repeat gap、[14:0]repeat 次数),对 NZ 分形矩阵补齐行尾与列尾,CompactMode::RowAlignedPadding模式下只对向上对齐到 16 行的部分做填充。
可以看到,CPU 实现刻意复用与 NPU 相同的GetPadValue位图(注释明确说明"so fp8/fp4/custom share the NPU bit maps"),保证模拟器与硬件行为逐位一致;NPU 实现则把填充开销摊到批量向量指令上,避免逐元素标量分支——这正是 TFILLPAD 在真实 kernel 中填充"无效区"的高效形态。
总结
TFILLPAD 是 PTO-ISA 中处理"静态形状完整、动态数据有效"这一核心矛盾的填充指令,其价值在于把运行时边界问题转化为编译期确定的位模式物化,使下游指令可以无条件地在完整 Tile 上运算。使用时的关键决策点有三:一是依据形状关系选择Normal/InPlace/Expand模式;二是依据元素类型与数值语义从PadValue::Zero/Min/Max/PadValueCustom中选定填充位模式;三是严格遵守 DType 大小一致、Vec 形状相等或扩大、Mat 仅支持 NZ 布局等编译期约束。结合 CPU 模拟器与 A5 后端的实现对照,开发者可以在编写、验证与调优三个阶段快速定位 TFILLPAD 的预期行为,将其无缝接入完整的 PTO 指令流水线。
- 人工智能
- 指令集
- 算子库
- 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 的 TFILLPAD 填充指令详解:标准 PadValue 与自定义填充值 API 的测试与实现
PTO ISA 的 TFILLPAD 填充指令详解:标准 PadValue 与自定义填充值 API 的测试与实现 TFILLPAD(Tile Fill Pad)
人工智能指令集算子库CANNAscendCANN PTO-ISA TFILLPAD 指令详解:Tile 编译时填充值的复制与边界物化
CANN PTO ISA TFILLPAD 指令详解:Tile 编译时填充值的复制与边界物化 TFILLPAD 是 CANN PTO ISA(Parallel
人工智能指令集算子库CANNAscendCANN PTO-ISA TDIV 指令详解:Tile 逐元素除法从汇编到 C++ Intrinsic 的完整指南
CANN PTO ISA TDIV 指令详解:Tile 逐元素除法从汇编到 C++ Intrinsic 的完整指南 本篇技术指南以 CANN pto isa 仓
人工智能指令集算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考