
CANN pto-isa 中的 TSORT32基于 VBS32 的 32 元素塊值-索引排序指令詳解【免費下載鏈接】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-isaPTOParallel Tile Operation虛擬指令集中的TSORT32指令用于對 Tile 中每個 32 元素塊連同其索引一起做降序排序并將排序后的值-索引對寫入目標 Tile底層由 SFU 硬件指令VBS32vbitsort支撐。本文以倉庫中 TSORT32_zh.md 指令文檔為主體結(jié)合 A2/A3 實現(xiàn)、A5 實現(xiàn)、CPU 仿真實現(xiàn) 與 ST 測試用例完整講清該指令的數(shù)學語義、Tile 尺寸規(guī)則、尾部非對齊處理策略以及跨平臺實現(xiàn)差異讀完后可直接在 PTO kernel 中正確調(diào)用TSORT32并完成tmp緩沖規(guī)劃與流水線同步。指令語義每 32 元素塊的值-索引對排序TSORT32對src的每個 32 元素塊與idx中對應的索引一起排序并將排序后的值-索引對寫入dst。對每一行rsrc按獨立的 32 元素塊處理設(shè)塊b覆蓋列32b … 32b31n_b min(32, C - 32b)為其有效元素數(shù)則構(gòu)成值-索引對$$ (v_k, i_k) (\mathrm{src}{r,32bk},; \mathrm{idx}{r,32bk}), \quad 0 \le k n_b $$按值降序排序輸出重排后的序列$$ [(v_{\pi(0)}, i_{\pi(0)}),; (v_{\pi(1)}, i_{\pi(1)}),; \ldots] $$其中π為該塊的排序置換值相同時索引小者優(yōu)先tie-break。兩個容易誤解的要點idx是輸入Tile索引隨值一起被重排不是輸出dst存儲的是排序后的值-索引對而非僅排序后的值。這一語義在 CPU 仿真實現(xiàn) 中可得到直接印證其ScoreIndexPair比較器先按分數(shù)降序、分數(shù)相同再按原始索引升序并使用std::stable_sort保證穩(wěn)定性與硬件的 tie-break 規(guī)則一致。硬件基礎(chǔ)VBS32vbitsortVBS32 運行在SFU非向量流水線上。一次調(diào)用可排序repeat個連續(xù)的 32 元素塊每個塊由 32 個值 32 個索引組成void vbitsort(__ubuf__ T *dst, // 排序后的值-索引對輸出 __ubuf__ T *src0, // 每塊 32 個值 × repeat __ubuf__ uint32_t *src1, // 每塊 32 個索引 × repeat uint8_t repeat); // 32 元素塊的數(shù)量1..255repeat上限REPEAT_MAX 255打包到指令字config[63:56]塊在內(nèi)存中連續(xù)分布、步長為 32 個元素塊b讀取src0[b*32 : b*3232]和src1[b*32 : b*3232]寫入dst[b*32*coef : ...]其中coef 2float或 4half——即值-索引對的擴展因子排序順序按值降序相同值時索引小者優(yōu)先。從源碼結(jié)構(gòu)看REPEAT_MAX與BLOCK_SIZE等常量定義在 common/constants.hpp被各平臺實現(xiàn)統(tǒng)一 includeMAX_UB_TMP 32 * 255 8160在 a2a3/TSort32.hpp 中定義它同時是單次vbitsort調(diào)用可處理元素數(shù)的上限255 塊 × 32 元素。當repeat超過 255 塊時A2/A3 實現(xiàn) 會將一行拆分為多次vbitsort調(diào)用前若干組各處理 255 塊最后一組處理余下塊。C 內(nèi)建接口接口聲明于 include/pto/common/pto_instr.hpp公共包含頭為pto/pto-inst.hpp// TSORT32 does not take wait events. Wait on events before calling it if needed. template typename DstTileData, typename SrcTileData, typename IdxTileData PTO_INST RecordEvent TSORT32(DstTileData dst, SrcTileData src, IdxTileData idx); // 角色映射 OIO1 個輸出 2 個輸入 template typename DstTileData, typename SrcTileData, typename IdxTileData, typename TmpTileData PTO_INST RecordEvent TSORT32(DstTileData dst, SrcTileData src, IdxTileData idx, TmpTileData tmp); // 角色映射 OIOI1 個輸出 3 個輸入要點3 參數(shù)版本要求src列數(shù) 32 對齊validCol % 32 0直接排序4 參數(shù)版本支持非 32 對齊尾部validCol % 32 ! 0通過tmp做尾部填充該指令不接受WaitEvents...參數(shù)、也不做內(nèi)部事件同步——如需同步調(diào)用者須在調(diào)用前顯式等待相關(guān) event。這在頭文件注釋中被明確寫出也體現(xiàn)在約束表中。各平臺的底層實現(xiàn)通過MAP_INSTR_IMPL_ROLES宏分發(fā)到TSORT32_IMPLpto_instr_impl.hpp 中按目標平臺分別 include 了pto/npu/a2a3/TSort32.hpp、pto/npu/a5/TSort32.hpp與pto/cpu/TSort32.hpp。Tile 尺寸與數(shù)據(jù)類型對于src形狀為 $R \times C$有效區(qū)域、塊大小 32Tiledtype尺寸元素數(shù)說明srchalf或float$T$$R \times C$待排序的值idxuint32_t$R \times C$或 $1 \times C$ 廣播隨值重排的索引dst$T$$R \times (2C)$ float$R \times (4C)$ half排序后的值-索引對tmp僅4參數(shù)$T$見下方 tmp 尺寸公式尾部填充 scratchdst擴展因子typeCoef每個輸入元素生成一個 8 Byte 的 tuple[value (4Byte), index (4Byte)]——float的 value 占滿 4 Bytehalf的 2 Byte value 零擴展至 4 Byte。因此dst恒為 $C \times 8$ 字節(jié)dtype每個src列對應的dst列數(shù)dtype 單位tuple 布局字節(jié)/tuplefloat×22 個 float 槽位[value_f32, index_u32]8half×44 個 half 槽位[value_f16, 0x0000, index_u32]8源碼印證a2a3 實現(xiàn) 定義了FLOAT_DST_STRIDE_COEF 2與HALF_DST_STRIDE_COEF 4寫dst時按typeCoef推進偏移CPU 仿真 中t totalByte / sizeof(T)totalByte 8推進輸出指針half 時還顯式寫入一個 0 槽位與上表 tuple 布局完全一致。關(guān)于idx廣播實現(xiàn)中idxStride idx.GetValidRow() 1 ? 0 : RowStride見 a2a3/TSort32.hpp即當idx只有一行時行步長取 0實現(xiàn) $1 \times C$ 的列廣播。約束匯總約束原因dst/srcdtype half或float須一致idxuint32_tVBS32 類型分派所有 Tile 為TileType::Vec、BLayout::RowMajorSFU 尋址validCol % 32 03參數(shù)每塊恰為 32 個元素validCol任意4參數(shù)尾塊通過tmp填充至 32填充值為 $-\infty$repeat validCol/323參數(shù)或ceil(validCol/32)4參數(shù)VBS32 repeat 計數(shù)每次調(diào)用 ≤ 255更大的validCol拆分為多次vbitsort調(diào)用tmp4參數(shù)≥tmpSize元素見下方公式保存填充后的行/尾塊副本無WaitEvents.../ 無內(nèi)部 event synchronization如需同步須顯式調(diào)用這些約束在編譯期由CheckStatic以static_assert強制檢查見 a2a3/TSort32.hppdst/src 必須同為half或float、idx 必須為uint32_t、三個 Tile 均須TileType::Vec且行主序。違反任一條件將直接觸發(fā)編譯錯誤。tmp尺寸公式4參數(shù)設(shè) $C$ validCol$b$ sizeof(T)字節(jié)數(shù)$G$ 32塊大小。實現(xiàn)根據(jù)整行大小是否滿足MAX_UB_TMP 8160進行分支且閾值單位因目標平臺而異$$ \mathrm{tmpSize} \begin{cases} \mathrm{ceil}_{G}(C) \text{A2/A3} C \le 8160 \text{元素數(shù)} ;; \text{A5/950PR/950DT} C \cdot b \le 8160 \text{字節(jié)} \ G 32 \text{A2/A3} C 8160 \text{元素數(shù)} ;; \text{A5} C \cdot b 8160 \text{字節(jié)} \end{cases} $$ceil_G(C) $C$ 向上取整到 32 的倍數(shù)Atlas A2/A3 訓練/推理系列產(chǎn)品閾值單位為元素數(shù)。源碼 的判斷是srcShapeBytesPerRow / sizeof(T) MAX_UB_TMP即 $C \le 8160$與 dtype 無關(guān)float、half 均為 $C \le 8160$A5Ascend 950PR/950DT閾值單位為字節(jié)。源碼 的判斷是validCol * sizeof(T) MAX_UB_TMP即 $C \cdot b \le 8160$float → $C \le 2040$half → $C \le 4080$。該閾值為pto_copy_ubuf_to_ubufMOV_UB_TO_UB的 repeat 上限 255 塊 × 32 Byte尾塊 $t C \bmod G$ 個元素末尾不完整塊擴展至 $G$ 并以 $-\infty$ 填充Path A小行從行首整行復制到tmp然后原地填充最后 32 個元素Path B大行僅復制尾塊到tmp完整塊直接從src排序VBS32 硬件上限每次調(diào)用repeat ≤ 255塊≤ 8160 元素超過 255 塊的行拆分為多次vbitsort調(diào)用UB 布局tmp應緊接dst之后放置32 Byte 對齊大小為ceil(C·b, 32)字節(jié)因 $b \in {2,4}$ 整除 32等價于ceil(ceil(C, 32)·b, 32)——不應使用固定的 8KB 偏移因為 Path AA2/A3在接近閾值時對 float 需要最多約 32KB$C \le 8160$ 元素 32KB。4 參數(shù)尾部處理路徑當validCol % 32 ! 0時末尾不完整塊$t C \bmod 32$ 個元素須填充為完整的 32 元素塊后才能送入vbitsortA2/A3$C \le 8160$元素數(shù) / A5$C \cdot b \le 8160$字節(jié)小行整行復制到tmp然后原地覆蓋最后 32 個元素為 $-\infty$ 填充從tmp排序整行。A2/A3 路徑用vector_dup完成填充見 源碼A5 路徑則通過vlds/vdup/vsts向量指令配合掩碼完成見 源碼A2/A3$C 8160$元素數(shù) / A5$C \cdot b 8160$字節(jié)大行僅復制尾塊到tmp并填充完整塊直接從src排序僅尾塊從tmp排序。該邏輯封裝在LargeTmpBufferImpl中a2a3 版本先對前面各滿組做vbitsort(..., REPEAT_MAX)最后一組用srcTailRepeatNum - 1處理剩余滿塊再將尾塊拷入tmp、用set_vector_maskvector_dup填充 $-\infty$、最后單獨vbitsort(..., 1)。填充值$-\infty$ -(0.0/0.0)即負 NaN等價于std::numeric_limitsT::lowest()落在降序排序的底部不影響有效元素的相對順序。若validCol 32 × 255行按REPEAT_MAX大小的組拆分每組通過獨立的vbitsort調(diào)用排序。平臺實現(xiàn)差異從源碼看三條執(zhí)行路徑PTO 為同一TSORT32內(nèi)建指令提供了三套實現(xiàn)理解差異有助于排查跨平臺行為A2/A3Atlas A2/A3 系列——include/pto/npu/a2a3/TSort32.hpp每個vbitsort調(diào)用后都插入pipe_barrier(PIPE_V)保證 SFU 結(jié)果在下一調(diào)用前就緒行步長直接取Tile::RowStridedstStride/srcStride為編譯期常量小行閾值按元素數(shù)判斷srcShapeBytesPerRow / sizeof(T) MAX_UB_TMP。A5——include/pto/npu/a5/TSort32.hpp不插入pipe_barrier(PIPE_V)流水線語義由編譯器/硬件保證行步長按 32 Byte 對齊計算PTO_CEIL(Cols * byteSize, 32) / byteSize尾部填充改走__VEC_SCOPE__內(nèi)的vlds/vdup/vsts向量指令且閾值按字節(jié)數(shù)判斷dst與src的行步長按各自的列寬獨立向上取整到 32 字節(jié)這解釋了為何dst尺寸公式中 half 的擴展因子是 4一個 tuple 占 8 字節(jié) 4 個 half。CPU 仿真——include/pto/cpu/TSort32.hpp用std::stable_sort 自定義比較器分數(shù)降序、同分按索引升序逐塊模擬硬件行為保證 CPU 結(jié)果可作 golden reference靜態(tài)斷言比 NPU 路徑更寬松額外允許int32_t/int16_t/bfloat16_t且 4 參數(shù)版本直接復用 3 參數(shù)邏輯validCol任意值天然被std::min(sortNum, validCol - j)截斷無需顯式填充。測試用例如何在倉庫中驗證倉庫為多個平臺提供了完整的 STSystem Test用例可直接編譯運行驗證語義。以 A2/A3 為例tests/npu/a2a3/src/st/testcase/tsort32/main.cpp 定義了 4 個用例恰好覆蓋了文檔的全部關(guān)鍵路徑TEST_F(TSort32Test, case1) { tsort32_test1, float(2, 32, 32); } // 32 對齊單塊 TEST_F(TSort32Test, case2) { tsort32_test2, uint16_t(4, 64, 64); } // halfuint16_t 即 f16 存儲雙塊 TEST_F(TSort32Test, case3) { tsort32_test3, float(1, 32 * 256, 32 * 256); } // 256 塊 REPEAT_MAX(255)驗證分組拆分 TEST_F(TSort32Test, case4) { tsort32_test4, float(2, 13, 16); } // 非 32 對齊尾部13 列4 參數(shù) tmp對應 kernel tsort32_kernel.cpp 展示了完整的 UB 規(guī)劃與 Manual 模式同步寫法// Tile 規(guī)劃ALIGN_C 為 32 對齊后的列寬TYPE_COEF sizeof(float)/sizeof(T) using SrcTileData TileTileType::Vec, T, ROWS_, ALIGN_C, BLayout::RowMajor, -1, -1; using IdxTileData TileTileType::Vec, uint32_t, ROWS_, ALIGN_C, BLayout::RowMajor, -1, -1; using DstTileData TileTileType::Vec, T, ROWS_, TYPE_COEF * 2 * ALIGN_C, BLayout::RowMajor, -1, -1; using TmpTileData TileTileType::Vec, T, 1, ALIGN_C, BLayout::RowMajor; TASSIGN(srcTile, 0x0); // src 0x0 TASSIGN(idxTile, 0x8000); // idx 0x800032 字節(jié)對齊偏移 TASSIGN(dstTile, 0x16000); // dst 0x16000 TASSIGN(tmpTile, 0x20000); // tmp 0x20000 TLOAD(srcTile, srcGlobal); TLOAD(idxTile, idxGlobal); TLOAD(tmpTile, tmpGlobal); #ifndef __PTO_AUTO__ set_flag(PIPE_MTE2, PIPE_V, EVENT_ID0); // Manual 模式顯式等待 MTE2 加載完成 wait_flag(PIPE_MTE2, PIPE_V, EVENT_ID0); #endif TSORT32(dstTile, srcTile, idxTile, tmpTile); // 無 wait event 參數(shù) #ifndef __PTO_AUTO__ set_flag(PIPE_V, PIPE_MTE3, EVENT_ID0); // Manual 模式SFU 完成后通知 MTE3 寫回 wait_flag(PIPE_V, PIPE_MTE3, EVENT_ID0); #endif TSTORE(dstGlobal, dstTile);注意dst的有效列數(shù)為VALID_C * TYPE_COEF * 2、分配總列數(shù)為TYPE_COEF * 2 * ALIGN_C與文檔的擴展因子規(guī)則一致tmp分配為ceil32(C)元素測試中tmpByteSize colsAlign * typeSize也印證了 tmp 尺寸公式。A5、kirin9030、kirinDev0000、kirinX90 及 CPU 仿真均有同構(gòu)用例A5、CPU、kirin9030每個目錄都附帶gen_data.py生成數(shù)據(jù)與 golden 校驗。匯編語法與示例AS Level 1SSA%dst pto.tsort32 %src, %idx : (!pto.tile..., !pto.tile...) - !pto.tile...AS Level 2DPSpto.tsort32 ins(%src, %idx : !pto.tile_buf..., !pto.tile_buf...) outs(%dst : !pto.tile_buf...)C 調(diào)用示例32 對齊與非對齊尾部#include pto/pto-inst.hpp using namespace pto; // 32 對齊每行單個塊 using SrcT TileTileType::Vec, float, 1, 32; using IdxT TileTileType::Vec, uint32_t, 1, 32; using DstT TileTileType::Vec, float, 1, 64; // 2× src 列數(shù)float SrcT src; IdxT idx; DstT dst; TSORT32(dst, src, idx); // 非 32 對齊尾部4 參數(shù) tmp using SrcT2 TileTileType::Vec, half, 1, 100; using IdxT2 TileTileType::Vec, uint32_t, 1, 100; using DstT2 TileTileType::Vec, half, 1, 400; // 4× src 列數(shù)half using TmpT TileTileType::Vec, half, 1, 128; // ≥ ceil32(100)128 TmpT tmp; TSORT32(dst2, src2, idx2, tmp);Manual 模式 ASM 形式Manual 模式下需先用pto.tassign綁定 tile 地址偏移需 32 字節(jié)對齊再發(fā)射排序指令與上文 kernel 中的TASSIGN序列一一對應# pto.tassign %arg0, tile(0x1000) # pto.tassign %arg1, tile(0x2000) # pto.tassign %arg2, tile(0x3000) %dst pto.tsort32 %src, %idx : (!pto.tile..., !pto.tile...) - !pto.tile...小結(jié)與實踐要點選接口validCol % 32 0用 3 參數(shù)版本否則用 4 參數(shù)版本并預留tmp規(guī)劃 UBdst按 8 字節(jié)/元素對擴展float ×2 列、half ×4 列tmp按tmpSize公式放置于dst之后、32 字節(jié)對齊勿用固定 8KB 偏移注意閾值單位差異A2/A3 按元素數(shù)$C \le 8160$、A5 按字節(jié)數(shù)float $C \le 2040$、half $C \le 4080$走小行/大行兩條路徑顯式同步TSORT32不接收 wait eventManual 模式下須按set_flag/wait_flag在 MTE2→V、V→MTE3 邊界顯式同步Auto 模式下編譯器自動處理驗證手段跨平臺行為可用 cpu 仿真用例 生成 golden再用各 NPU ST 用例比對。參考路徑指令文檔docs/isa/TSORT32_zh.md、docs/isa/TSORT32.md公共聲明include/pto/common/pto_instr.hpp平臺實現(xiàn)include/pto/npu/a2a3/TSort32.hpp、include/pto/npu/a5/TSort32.hpp、include/pto/cpu/TSort32.hpp測試用例tests/npu/a2a3/src/st/testcase/tsort32/、tests/npu/a5/src/st/testcase/tsort32/、tests/cpu/st/testcase/tsort32/【免費下載鏈接】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創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考