PTO TINSERT 指令详解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 PTOParallel Tile Operation虚拟指令集中的TINSERT指令为对象系统讲解其在(indexRow, indexCol)偏移处将源子 Tile 插入目标 Tile 的数学语义、五种典型应用场景Acc→Mat / Acc→Vec / Vec→Vec / Vec→Mat / NZ Split、SSA 与 DPS 两级汇编语法、C 内建接口的完整重载族并结合本仓库的 NPU 后端实现与 ST 测试用例深入解析STPhaseunit flag 同步机制、标量/向量量化路径以及 Atlas A2/A3 与 Ascend 950PR/Ascend 950DT 两套实现检查约束。读完后你将能够在算子开发中正确选用TINSERT重载、理解其布局与数据类型合法性边界并学会借助 unit flag 机制省去显式set_flag/wait_flag完成 Cube 到 Fixpipe 的搬出同步。指令总览子 Tile 的“落位”操作TINSERTTile Insert在目标 Tile 的(indexRow, indexCol)偏移处写入一个源子 Tile。概念上它是TEXTRACT的逆操作TEXTRACT从目标 Tile 中切出子 Tile而TINSERT把子 Tile 放回目标 Tile 的指定位置。两者配合可实现 Tile 级数据搬移与排布重组。在数学语义上设R src.GetValidRow()、C src.GetValidCol()对0 i R、0 j C有$$ \mathrm{dst}{\mathrm{indexRow}i,;\mathrm{indexCol}j} \mathrm{src}{i,j} $$即源子 Tile 中(i, j)处的元素被写入目标 Tile 的(indexRow i, indexCol j)处其余位置的元素保持目标 Tile 原有内容不变。五大应用场景根据关联文档与后端实现TINSERT覆盖以下插入路径Acc → Mat 插入累加器L0C结果搬入 MatL1支持可选的 relu、标量量化或向量量化Acc → Vec 插入Ascend 950PR/Ascend 950DT累加器结果搬入 VecUB支持可选的AccToVecMode、relu、标量量化或向量量化Vec → Mat 插入Ascend 950PR/Ascend 950DTUB 数据搬入 L1支持 ND 与 NZ 布局Vec → Vec 插入Ascend 950PR/Ascend 950DTUB 内部搬移支持 ND 与 NZ 布局NZ Split 插入Ascend 950PR/Ascend 950DTSPLIT2/SPLIT4将一个 NZ 格式的 Vec 源 Tile 拆分为 2 或 4 个子传输写入 Mat 目标。可以看到TINSERT已从单纯的累加器搬出指令演进为覆盖 L0C/L1/UB 三大存储层之间多种排布转换的通用插入指令其中后四类路径仅在 Ascend 950PR/Ascend 950DT及其关联的 kirin 系列目标上提供。汇编语法从同步形式到两级抽象TINSERT在 PTO 指令集中以同步形式发射寄存器操作数%r0、%r1分别承载行、列索引%dst tinsert %src[%r0, %r1] : !pto.tile... - !pto.tile...AS Level 1SSASSA 形式把索引作为显式操作数传入类型为dtype%dst pto.tinsert %src, %idxrow, %idxcol : (!pto.tile..., dtype, dtype) - !pto.tile...AS Level 2DPSDPSdestructive pattern style形式使用ins(...)/outs(...)划分输入与输出操作数类型为带缓冲语义的!pto.tile_buf...pto.tinsert ins(%src, %idxrow, %idxcol : !pto.tile_buf..., dtype, dtype) outs(%dst : !pto.tile_buf...)三种形式表达同一指令同步形式面向寄存器级编码SSA 与 DPS 分别对应编译器中间表示的两个抽象层级便于调度器进行资源绑定与依赖分析。C 内建接口完整的重载族TINSERT的 C 内建接口声明于 include/pto/common/pto_instr.hpp公共包含头为pto/pto-inst.hpp即 include/pto/pto-inst.hpp。所有重载均返回PTO_INST RecordEvent且统一先调用detail::PtoWaitEvents(events...)等待事件再发射指令最后通过TINSERT_IMPL...分发到具体后端。核心重载族如下// 普通插入 template typename DstTileData, typename SrcTileData, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); // relu 形式 template typename DstTileData, typename SrcTileData, ReluPreMode reluMode, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); // 累加器到向量形式AccToVecMode relu template typename DstTileData, typename SrcTileData, AccToVecMode mode, ReluPreMode reluMode ReluPreMode::NoRelu, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); // 标量量化形式preQuantScalar 为预量化标量 template typename DstTileData, typename SrcTileData, ReluPreMode reluMode ReluPreMode::NoRelu, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint64_t preQuantScalar, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); template typename DstTileData, typename SrcTileData, AccToVecMode mode, ReluPreMode reluMode ReluPreMode::NoRelu, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint64_t preQuantScalar, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); // 向量量化形式fp 为 Scaling 类型的 FpTileData另有历史别名 TINSERT_FP template typename DstTileData, typename SrcTileData, typename FpTileData, ReluPreMode reluMode ReluPreMode::NoRelu, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, FpTileData fp, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); template typename DstTileData, typename SrcTileData, typename FpTileData, AccToVecMode mode, ReluPreMode reluMode ReluPreMode::NoRelu, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, FpTileData fp, uint16_t indexRow, uint16_t indexCol, WaitEvents ... events); // NZ Split 形式仅 Ascend 950PR/Ascend 950DT/kirin9030/kirinX90 #if defined(PTO_NPU_ARCH_A5) || defined(PTO_NPU_ARCH_KIRIN9030) || defined(PTO_NPU_ARCH_KIRINX90) template TInsertMode mode, typename DstTileData, typename SrcTileData, typename... WaitEvents PTO_INST RecordEvent TINSERT(DstTileData dst, SrcTileData src, uint16_t indexRow 0, uint16_t indexCol 0, WaitEvents ... events); #endif此外还有一组STPhase重载详见下文以及对应的TINSERT_FP历史兼容入口。从源码看普通无模板参数版本通过MAP_INSTR_IMPL(TINSERT, dst, src, indexRow, indexCol)完成指令映射include/pto/common/pto_instr.hpp而带ReluPreMode、AccToVecMode、STPhase等模板参数的重载直接进入TINSERT_IMPL最终由各目标后端如 include/pto/npu/a5/TInsert.hpp、include/pto/npu/a2a3/TInsert.hpp、kirin9030、kirinX90、kirinDev0000的TInsert.hpp实现。模板参数取值reluModeReluPreMode::{NoRelu, NormalRelu}控制插入前是否对源数据做 relumodeAccToVecMode::{SingleModeVec0, SingleModeVec1, DualModeSplitM, DualModeSplitN}仅 Acc → Vec 路径使用决定单目标/双目标M 切分/N 切分搬出方式TInsertModeSPLIT2/SPLIT4NZ Split 路径的拆分份数WaitEvents可变参数事件列表用于在指令发射前等待指定事件完成。运行时边界约束无论哪种重载都必须满足indexRow src.ValidRow dst.Rows indexCol src.ValidCol dst.Cols即源子 Tile 的有效区域必须完整落在目标 Tile 边界内越界插入属于非法使用。STPhase 重载用 unit flag 打通 Cube 到 Fixpipe 的同步TINSERT的STPhase重载是搬出侧store专用的相位控制它在 L0C 搬出指令上写入 unit flag单元标志与TMATMULAccPhase配对完成 Cube 到 Fixpipe 的硬件同步从而省去显式的set_flag/wait_flag指令对。该组重载仅在存在对应后端实现的目标上暴露Atlas A2/A3 训练系列产品、Atlas A2/A3 推理系列产品、Ascend 950PR/Ascend 950DT 和 CPU 模拟器。从源码看STPhase重载受#if defined(PTO_NPU_ARCH_A5) || defined(PTO_NPU_ARCH_A2A3) || defined(__CPU_SIM)保护include/pto/common/pto_instr.hpp并最终把相位值作为unitFlagCtrl传入底层搬移原语pto_copy_matrix_cc_to_cbufinclude/pto/npu/a5/TInsert.hpp。搬出侧的取值规则与累加侧不同产生该 L0C 结果的TMATMUL必须已经是AccPhase::Final即数据已就绪STPhase::Final用于最后一次搬出并释放 unit flagSTPhase::Partial只用于同一块 L0C 分多次搬出时的非末次那几条它不释放unit flag。需要特别警惕的错误配对把STPhase::Partial与AccPhase::Partial配对会让 fixpipe 等待一个永远不会到来的标志而挂死——该现象已在 Ascend 950PR 仿真器上复现。因此正确的模式是先TMATMULAccPhase::Final使数据就绪再对同一块 L0C 连续搬出时非末次用STPhase::Partial最后一次用STPhase::Final释放标志。适用路径限制STPhase重载仅支持TileType::Acc - TileType::MatL0C→L1路径目标为TileType::Vec时会在编译期报错。这一限制在 A5 后端同样有 static_assert 兜底STPhase is only supported for Acc-to-Mat TINSERTinclude/pto/npu/a5/TInsert.hpp。测试验证Acc→Mat 搬出已通过 A3 上板测试tmov_acc2mat覆盖了STPhase::Final以及STPhase::Partial后接STPhase::Final的场景。Ascend 950PR 仿真测试通过在 Ascend 950PR 板机、CANN 9.2.0 环境下tinsert的 4 个定向用例TInsertTest.case_acc2mat_*全部通过max diff 均为 0。仓库中的 ST 测试与文档描述一一对应见 tests/npu/a5/src/st/testcase/tinsert/main.cppTEST_F(TInsertTest, case_acc2mat_1) { testTInsertAcc2Mat1, uint16_t, float(16, 16, 16); } TEST_F(TInsertTest, case_acc2mat_2) { testTInsertAcc2Mat2, uint16_t, float(32, 32, 32); } TEST_F(TInsertTest, case_acc2mat_uf_final) { testTInsertAcc2Mat3, uint16_t, float(16, 16, 16); } TEST_F(TInsertTest, case_acc2mat_uf_multi_drain) { testTInsertAcc2Mat4, uint16_t, float(16, 16, 16); }其中case_acc2mat_uf_final对应Final搬出、case_acc2mat_uf_multi_drain对应Partial后接Final的多段搬出场景分别验证了 unit flag 的释放与保持语义。TINSERT_FP向量量化的历史兼容入口向量量化路径要求提供FpTileData类型的 Scaling 操作数TileType::Scaling。规范同名重载TINSERT(..., fp, ...)通过std::enable_if_t... (FpTileData::Loc TileType::Scaling) ...参与匹配include/pto/common/pto_instr.hpp只有FpTileData::Loc TileType::Scaling时才被选入重载集。TINSERT_FP(...)为历史 fp 量化形式保留源码兼容入口直接映射到无mode的TINSERT_IMPL(dst, src, fp, indexRow, indexCol)路径。TINSERT_FP同样提供STPhase版本与TMOV_FP/TSTORE_FP对齐语义与规范接口一致。在 A5 后端向量量化通过SetFPCInsert将 Scaling 张量地址经set_fpc写入反量化张量描述符寄存器include/pto/npu/a5/TInsert.hpp随后由pto_copy_matrix_cc_to_ub/pto_copy_matrix_cc_to_cbuf携带量化模式QuantPre完成搬出与量化的一体化处理。fp mode组合的向量量化重载仅在存在对应后端实现的目标上暴露A5、kirin9030、kirinX90 和 CPU 模拟器。约束与实现检查TINSERT的合法性检查随目标平台不同而不同下面分别给出通用约束与两套主要实现检查。通用约束 / 检查STPhase重载仅支持Acc - Mat路径目标为Vec编译期报错reluMode取值为ReluPreMode::{NoRelu, NormalRelu}mode取值为AccToVecMode::{SingleModeVec0, SingleModeVec1, DualModeSplitM, DualModeSplitN}运行时边界indexRow src.ValidRow dst.Rows且indexCol src.ValidCol dst.Cols向量量化fp mode重载仅在 A5、kirin9030、kirinX90 和 CPU 模拟器上暴露。Atlas A2/A3 训练系列产品 / Atlas A2/A3 推理系列产品实现检查支持的 tile 类型对仅TileType::Acc → TileType::Mat源布局必须为(BFractal: ColMajor, SFractal: RowMajor)目标布局必须为(BFractal: ColMajor, SFractal: RowMajor)且SFractalSize 512Dst.Cols * sizeof(DstDType)必须是32字节的倍数且非零普通 / relu非量化支持的 dtype 对floatAcc →half、bfloat16_t标量量化支持的 dtype 对floatAcc →int8_tint32_tAcc →int8_t、uint8_t、half、int16_t向量量化TINSERT含FpTileData历史TINSERT_FP别名支持的 dtype 对与标量量化相同。注意 A2/A3 的 Acc→Mat 路径目标要求SFractalSize 512这与 A5 的 NZ 格式要求不同移植算子时需按平台核对。Ascend 950PR/Ascend 950DT 实现检查除了 Acc → Mat 路径外Ascend 950PR/Ascend 950DT 还支持 Acc → Vec、Vec → Vec、Vec → Mat 和 NZ Split 路径。Acc → MatTileType::Acc → TileType::Mat源 Acc 类型必须是float或int32_t源布局必须为(BFractal: ColMajor, SFractal: RowMajor)目标布局必须为(!isRowMajor, SFractal: RowMajor)NZ 格式非量化普通 / relu目标类型floatAcc →half、bfloat16_t、floatint32_tAcc →int32_t标量量化目标类型floatAcc →int8_t、uint8_t、hifloat8_t、half、bfloat16_t、float8_e4m3_tint32_tAcc →int8_t、uint8_t、half、bfloat16_t向量量化目标类型与标量量化相同。Acc → VecTileType::Acc → TileType::Vec源 Acc 类型必须是float或int32_t源布局必须为(BFractal: ColMajor, SFractal: RowMajor)目标布局必须为以下三种之一NZ-to-NZ!isRowMajor, SFractal: RowMajor、NZ-to-NDisRowMajor, SFractal: NoneBox或 NZ-to-DN!isRowMajor, SFractal: NoneBoxAccToVecMode选择SingleModeVec0、SingleModeVec1、DualModeSplitM或DualModeSplitN双目标模式DualModeSplitM、DualModeSplitN要求QuantMode_t::NoQuant且不支持 NZ-to-DN 路径对于 32 位目标类型float/int32_t使用DualModeSplitN时切分前的ValidCol必须是32的整数倍目标 stride 必须非零且dstStride * sizeof(dstType)必须是32字节的倍数。A5 后端通过TInsertAccToVec实现上述三种目标布局源码中分别以enableNz2Nz、enableNz2Nd、enableNz2Dn三个编译期常量分支处理并针对DualModeSplitM/DualModeSplitN使用不同的validCol对齐策略FRACTAL_NZ_ROW或BLOCK_BYTE_SIZE见 include/pto/npu/a5/TInsert.hpp。Vec → VecTileType::Vec → TileType::VecDstTileData::DType必须等于SrcTileData::DType支持的元素类型half、bfloat16_t、float、int32_t、int8_t、hifloat8_t、float8_e4m3_t、float8_e5m2_t、float8_e8m0_t、float4_e2m1x2_t、float4_e1m2x2_t源和目标布局必须匹配均 ND 或均 NZND 路径源有效区域必须在目标边界内。分发选择copy_ubuf_to_ubuf对齐、vlds/vstsstride 对齐、未对齐 validCol、vlds/vstus未对齐 stride 或 indexCol或标量拷贝1×1 元素NZ 路径源列数不得超过目标列数使用ComputeNZBlockParams进行分形块copy_ubuf_to_ubuf。A2A3 后端的TInsertVecToVecNDUnaligned是 ND 未对齐路径的典型实现先按BLOCK_BYTE_SIZE32 字节对齐的 burst 用pto_copy_ubuf_to_ubuf搬主体剩余尾部字节再用set_vector_maskvcopy逐行补齐include/pto/npu/a2a3/TInsert.hpp。Vec → MatTileType::Vec → TileType::MatUB → L1DstTileData::DType必须等于SrcTileData::DType支持的元素类型与 Vec → Vec 相同ND 路径源必须为isRowMajor使用copy_ubuf_to_cbuf每行数据字节数必须与BLOCK_BYTE_SIZE32 字节对齐NZ 路径源必须为(!isRowMajor, SFractal: RowMajor)使用ComputeNZBlockParams进行分形块copy_ubuf_to_cbuf。NZ SplitTInsertMode::SPLIT2/TInsertMode::SPLIT4仅 Ascend 950PR/Ascend 950DT/kirin9030/kirinX90目标必须为TileType::Mat源必须为TileType::VecDstTileData::DType必须等于SrcTileData::DType源必须为 NZ 格式(!isRowMajor, SFractal: RowMajor)支持的元素类型与 Vec → Vec 相同validRow对齐到FRACTAL_NZ_ROW16用于 burst 计算将copy_ubuf_to_cbuf的总 burst 拆分为 2 或 4 个子传输每个处理totalBurstNum / SplitCount列块最后一个子传输承接余数。代码示例自动Auto模式Vec → Mat 插入NZ 布局自动模式下由编译器/运行时负责资源放置与调度只需构造 Tile 并调用接口#include pto/pto-inst.hpp using namespace pto; // Vec - Mat 插入NZ 布局 void example_auto() { using SrcT TileTileType::Vec, half, 16, 32, BLayout::ColMajor, 16, 32, SLayout::RowMajor; using DstT TileTileType::Mat, half, 16, 32, BLayout::ColMajor, -1, -1, SLayout::RowMajor; SrcT src; DstT dst(16, 32); TINSERT(dst, src, /*indexRow*/0, /*indexCol*/0); }注意DstT的BFractal/SFractal使用-1占位表示由编译器推断分形尺寸运行时通过构造参数dst(16, 32)指定行列数。手动Manual模式Vec → Mat 插入NZ 布局手动模式需先用TASSIGN显式绑定缓冲区地址再发射指令#include pto/pto-inst.hpp using namespace pto; // Vec - Mat 插入NZ 布局手动缓冲分配 void example_manual() { using SrcT TileTileType::Vec, half, 16, 32, BLayout::ColMajor, 16, 32, SLayout::RowMajor; using DstT TileTileType::Mat, half, 16, 32, BLayout::ColMajor, -1, -1, SLayout::RowMajor; SrcT src; DstT dst(16, 32); TASSIGN(src, 0x0); TASSIGN(dst, 0x0); TINSERT(dst, src, /*indexRow*/0, /*indexCol*/0); }带 unit flag 的 L0C→L1 搬出Atlas A2/A3 训练系列产品 / Atlas A2/A3 推理系列产品、Ascend 950PR/Ascend 950DT#include pto/pto-inst.hpp using namespace pto; void example_unit_flag() { TileLefthalf, 32, 32 a; TileRighthalf, 32, 32 b; TileAccfloat, 32, 32 c; TileTileType::Mat, float, 32, 32, BLayout::ColMajor, 32, 32, SLayout::RowMajor l1; TASSIGN(a, 0x0); TASSIGN(b, 0x0); TASSIGN(c, 0x0); TASSIGN(l1, 0x2000); // 数据就绪后再搬出两条指令之间不需要显式 set_flag/wait_flag TMATMULAccPhase::Final(c, a, b); TINSERTSTPhase::Final(l1, c, /*indexRow*/0, /*indexCol*/0); // 同一块 L0C 分多次搬出时非末次用 Partial 不释放 unit flag末次用 Final 释放 // TINSERTSTPhase::Partial(l1, c, /*indexRow*/0, /*indexCol*/0); // TINSERTSTPhase::Final(l1, c, /*indexRow*/0, /*indexCol*/0); }汇编示例ASM自动模式自动模式下由编译器/运行时负责资源放置与调度%dst pto.tinsert %src, %idxrow, %idxcol : (!pto.tile..., dtype, dtype) - !pto.tile...手动模式手动模式需先显式绑定资源pto.tassign为可选绑定方式再发射指令# 手动模式先显式绑定资源再发射指令。 # pto.tassign %arg0, tile(0x1000) # pto.tassign %arg1, tile(0x2000) %dst pto.tinsert %src, %idxrow, %idxcol : (!pto.tile..., dtype, dtype) - !pto.tile...PTO 汇编形式%dst tinsert %src[%r0, %r1] : !pto.tile... - !pto.tile... # AS Level 2 (DPS) pto.tinsert ins(%src, %idxrow, %idxcol : !pto.tile_buf..., dtype, dtype) outs(%dst : !pto.tile_buf...)测试与验证TINSERT在仓库中拥有成体系的 ST 测试。除上文提到的case_acc2mat_*外tests/npu/a5/src/st/testcase/tinsert/main.cpp 还覆盖了 NZ 路径case_nz_1至case_nz_7元素类型含float、int32_t尺寸从 16×32×4 到 64×64×4、ND 的 Vec→Mat 路径case_nd_1/case_nd_2int8_t以及 ND 的 Vec→Vec 路径case_nd_vec_1至case_nd_vec_9含float、uint16_t、int8_t及非正方形目标 16×24、32×48 等。测试配套的构建与数据生成文件位于同目录CMakeLists.txt、gen_data.py、tinsert_kernel.cppA5、kirin9030、kirinDev0000 等目标均有独立的tinsert测试目录。CPU 模拟器目标同样通过__CPU_SIM宏暴露STPhase重载可在无硬件环境下验证指令语义。总结TINSERT是 PTO 指令集中承担子 Tile“落位”的核心搬移指令与TEXTRACT互为逆操作。在实际算子开发中你可以按以下思路选用搬累加器结果到 L1/UBAcc → Mat 用普通/relu/量化重载Ascend 950PR/Ascend 950DT 上还可选 Acc → Vec 的AccToVecMode路由跨层数据搬移Vec → MatUB→L1、Vec → VecUB 内需保证源目标 dtype 一致并核对布局ND/NZ与对齐要求大块 NZ 数据拆分发写TInsertMode::SPLIT2/SPLIT4将 burst 拆分为多段子传输缓解单次搬移的压力追求极致同步开销在支持的后端上使用TMATMULAccPhase::FinalTINSERTSTPhase::Final组合以 unit flag 取代显式set_flag/wait_flag注意Partial仅用于非末次搬出且不可与AccPhase::Partial配对。编写算子时务必对照本节给出的平台实现检查核对 dtype 对、布局与 32 字节对齐约束并结合 docs/isa/conventions_zh.md 与 PTO-Virtual-ISA-Manual_zh.md 中的总体约定使用。【免费下载链接】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),仅供参考