已合并
feat: mla算子优化 — KV-split均衡分核调度和精度修复 + cpu_low.bin读取修复 #794
华工-林鑫创建于 7月1日
feat: mla算子优化 — KV-split均衡分核调度和精度修复 + cpu_low.bin读取修复 #794
已合并
共 34 个文件变更+5628-2230
| @@ -7,9 +7,10 @@ | |||
| 7 | │ ├── CMakeLists.txt # CMake编译文件 | 7 | │ ├── CMakeLists.txt # CMake编译文件 |
| 8 | │ ├── gen_data.py | 8 | │ ├── gen_data.py |
| 9 | │ ├── kernel_common.hpp #两个不同的kernel实现中的共同变量与宏 | 9 | │ ├── kernel_common.hpp #两个不同的kernel实现中的共同变量与宏 |
| 10 | -│ ├── main.cpp | 10 | +│ ├── mla.cpp |
| 11 | │ ├── mla_kernel.cpp # MLA TP 2/4/8 模板 | 11 | │ ├── mla_kernel.cpp # MLA TP 2/4/8 模板 |
| 12 | │ ├── mla_kernel_tp1_spec.cpp # MLA TP 1 模板 | 12 | │ ├── mla_kernel_tp1_spec.cpp # MLA TP 1 模板 |
| 13 | +│ ├── amla_kernel_tp1_spec.cpp # AMLA TP 1 模板 | ||
| 13 | │ └── README.md | 14 | │ └── README.md |
| 14 | ``` | 15 | ``` |
| 15 | 16 | ||
| @@ -20,7 +21,7 @@ | |||
| 20 | 21 | ||
| 21 | ``` | 22 | ``` |
| 22 | # 在./examples/19_mla目录下执行 | 23 | # 在./examples/19_mla目录下执行 |
| 23 | -python gen_data.py 1 1 128 16 16 128 half | 24 | +python gen_data.py 4 "1,2,3,4" "128,256,512,1024" 16 64 128 half |
| 24 | # 输入参数分别对应 batchSize,qSeqlen,kvSeqlen, qheadNum,numBlock, blockSize | 25 | # 输入参数分别对应 batchSize,qSeqlen,kvSeqlen, qheadNum,numBlock, blockSize |
| 25 | # qSeqlen表示需要推理的token个数,支持范围为1~4,即常规decode与mtp场景 | 26 | # qSeqlen表示需要推理的token个数,支持范围为1~4,即常规decode与mtp场景 |
| 26 | # kvSeqlen表示输入的序列长度 | 27 | # kvSeqlen表示输入的序列长度 |
| @@ -49,9 +50,9 @@ python gen_data.py 1 1 128 16 16 128 half | |||
| 49 | # 编译指定用例(在CATLASS代码仓目录下) | 50 | # 编译指定用例(在CATLASS代码仓目录下) |
| 50 | bash scripts/build.sh 19_mla | 51 | bash scripts/build.sh 19_mla |
| 51 | cd output/bin | 52 | cd output/bin |
| 52 | -./19_mla 1 1 128 16 16 128 | 53 | +./19_mla 4 "1,2,3,4" "128,256,512,1024" 16 64 128 |
| 53 | # 此处的参数和生成数据的参数保持一致 | 54 | # 此处的参数和生成数据的参数保持一致 |
| 54 | -# 完整参数为 batchSize, qSeqlen, kvSeqlen, qheadNum, numBlock, blockSize [--dtype DTYPE --datapath DATA_PATH --device DEVICE_ID],dtype默认为half, datapath默认为../../examples/19_mla/data, device默认为0。 | 55 | +# 完整参数为 batch "qSeqlenList" "kvSeqlenList" numHeads numBlocks blockSize [--dtype DTYPE --datapath DATA_PATH --device DEVICE_ID],dtype默认为half, datapath默认为../../examples/19_mla/data, device默认为0。 |
| 55 | ``` | 56 | ``` |
| 56 | 57 | ||
| 57 | 执行结果如下,说明精度比对成功。 | 58 | 执行结果如下,说明精度比对成功。 |
| @@ -0,0 +1,565 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
S | |||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +using namespace Catlass; | ||
| 27 | +/* | ||
| 28 | +This example demonstrates how to compute amla. | ||
| 29 | +*/ | ||
| 30 | +template <class BlockMmadQK, class BlockMmadAMLAPV, class EpilogueAMLASoftmax, class EpilogueAMLARescaleO, | ||
| 31 | + class EpilogueMLAFDRescaleO> | ||
| 32 | +class AMLAKernelTp1Spec { | ||
| 33 | +public: | ||
| 34 | + using ArchTag = typename BlockMmadQK::ArchTag; | ||
| 35 | + using L1TileShape = typename BlockMmadQK::L1TileShape; | ||
| 36 | + using ElementQ = typename BlockMmadQK::ElementA; | ||
| 37 | + using LayoutQ = typename BlockMmadQK::LayoutA; | ||
| 38 | + using ElementK = typename BlockMmadQK::ElementB; | ||
| 39 | + using LayoutK = typename BlockMmadQK::LayoutB; | ||
| 40 | + using ElementS = typename BlockMmadQK::ElementC; | ||
| 41 | + using LayoutS = typename BlockMmadQK::LayoutC; | ||
| 42 | + | ||
| 43 | + using ElementP = typename BlockMmadAMLAPV::ElementA; | ||
| 44 | + using LayoutP = typename BlockMmadAMLAPV::LayoutA; | ||
| 45 | + using ElementV = typename BlockMmadAMLAPV::ElementB; | ||
| 46 | + using LayoutV = typename BlockMmadAMLAPV::LayoutB; | ||
| 47 | + | ||
| 48 | + using ElementMask = half; | ||
| 49 | + | ||
| 50 | + using ElementO = typename EpilogueAMLARescaleO::ElementOutput; | ||
| 51 | + using LayoutO = typename EpilogueAMLARescaleO::LayoutOutput; | ||
| 52 | + | ||
| 53 | + using ElementOTmp = typename EpilogueAMLARescaleO::ElementInput; | ||
| 54 | + using LayoutOTmp = typename EpilogueAMLARescaleO::LayoutInput; | ||
| 55 | + | ||
| 56 | + using ElementUpdate = typename EpilogueAMLARescaleO::ElementUpdate; | ||
| 57 | + using LayoutUpdate = typename EpilogueAMLARescaleO::LayoutUpdate; | ||
| 58 | + | ||
| 59 | + static constexpr uint32_t KV_SPLIT_MAX = EpilogueMLAFDRescaleO::KV_SPLIT_MAX; | ||
| 60 | + static constexpr uint32_t HEADS_PROCESS_MAX = EpilogueMLAFDRescaleO::HEADS_PROCESS_MAX; | ||
| 61 | + static constexpr uint32_t COMPUTE_ELE_NUM = EpilogueMLAFDRescaleO::COMPUTE_ELE_NUM; | ||
| 62 | + | ||
| 63 | + /// Parameters structure | ||
| 64 | + struct Params { | ||
| 65 | + // Data members | ||
| 66 | + GM_ADDR q; | ||
| 67 | + GM_ADDR qRope; | ||
| 68 | + GM_ADDR k; | ||
| 69 | + GM_ADDR kRope; | ||
| 70 | + GM_ADDR blockTables; | ||
| 71 | + GM_ADDR o; | ||
| 72 | + GM_ADDR s; | ||
| 73 | + GM_ADDR p; | ||
| 74 | + GM_ADDR oTmp; | ||
| 75 | + GM_ADDR oUpdate; | ||
| 76 | + GM_ADDR oCoreTmp; | ||
| 77 | + GM_ADDR l; | ||
| 78 | + GM_ADDR tiling; | ||
| 79 | + | ||
| 80 | + // Methods | ||
| 81 | + CATLASS_DEVICE | ||
| 82 | + Params() {} | ||
| 83 | + | ||
| 84 | + CATLASS_DEVICE | ||
| 85 | + Params(GM_ADDR q_, GM_ADDR qRope_, GM_ADDR k_, GM_ADDR kRope_, GM_ADDR blockTables_, GM_ADDR o_, GM_ADDR s_, | ||
| 86 | + GM_ADDR p_, GM_ADDR oTmp_, GM_ADDR oUpdate_, GM_ADDR oCoreTmp_, GM_ADDR l_, GM_ADDR tiling_) | ||
| 87 | + : q(q_), qRope(qRope_), k(k_), kRope(kRope_), blockTables(blockTables_), o(o_), s(s_), p(p_), oTmp(oTmp_), | ||
| 88 | + oUpdate(oUpdate_), oCoreTmp(oCoreTmp_), l(l_), tiling(tiling_) | ||
| 89 | + { | ||
| 90 | + } | ||
| 91 | + }; | ||
| 92 | + | ||
| 93 | + // Methods | ||
| 94 | + CATLASS_DEVICE | ||
| 95 | + AMLAKernelTp1Spec() {} | ||
| 96 | + | ||
| 97 | + CATLASS_DEVICE void operator()(Params const ¶ms) | ||
| 98 | + { | ||
| 99 | + | ||
| 100 | + AscendC::SetFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID0); | ||
| 101 | + AscendC::SetFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID1); | ||
| 102 | + AscendC::SetFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID2); | ||
| 103 | + AscendC::SetFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID3); | ||
| 104 | + | ||
| 105 | + AscendC::SetFlag<AscendC::HardEvent::FIX_M>(EVENT_ID0); | ||
| 106 | + AscendC::SetFlag<AscendC::HardEvent::FIX_M>(EVENT_ID1); | ||
| 107 | + | ||
| 108 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID0); | ||
| 109 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID1); | ||
| 110 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID2); | ||
| 111 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID3); | ||
| 112 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID4); | ||
| 113 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID5); | ||
| 114 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID6); | ||
| 115 | + AscendC::SetFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID7); | ||
| 116 | + | ||
| 117 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID0); | ||
| 118 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID0); | ||
| 119 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | ||
| 120 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID2); | ||
| 121 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID3); | ||
| 122 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID4); | ||
| 123 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID5); | ||
| 124 | + | ||
| 125 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID0); | ||
| 126 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID1); | ||
| 127 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID4); | ||
| 128 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | ||
| 129 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | ||
| 130 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID5); | ||
| 131 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID2); | ||
| 132 | + | ||
| 133 | + | ||
| 134 | + // Get the memory offset address of the input on Global Memory | ||
| 135 | + | ||
| 136 | + AscendC::GlobalTensor<ElementQ> gQ; | ||
| 137 | + gQ.SetGlobalBuffer((__gm__ ElementQ *)params.q); | ||
| 138 | + AscendC::GlobalTensor<ElementQ> gQRope; | ||
| 139 | + gQRope.SetGlobalBuffer((__gm__ ElementQ *)params.qRope); | ||
| 140 | + AscendC::GlobalTensor<ElementK> gK; | ||
| 141 | + gK.SetGlobalBuffer((__gm__ ElementK *)params.k); | ||
| 142 | + AscendC::GlobalTensor<ElementK> gKRope; | ||
| 143 | + gKRope.SetGlobalBuffer((__gm__ ElementK *)params.kRope); | ||
| 144 | + AscendC::GlobalTensor<int32_t> gblockTable; | ||
| 145 | + gblockTable.SetGlobalBuffer((__gm__ int32_t *)(params.blockTables)); | ||
| 146 | + | ||
| 147 | + AscendC::GlobalTensor<ElementO> gO; | ||
| 148 | + gO.SetGlobalBuffer((__gm__ ElementO *)params.o); | ||
| 149 | + AscendC::GlobalTensor<ElementOTmp> gOUpdate; | ||
| 150 | + gOUpdate.SetGlobalBuffer((__gm__ ElementOTmp *)params.oUpdate); | ||
| 151 | + AscendC::GlobalTensor<ElementOTmp> gOCoreTmp; | ||
| 152 | + gOCoreTmp.SetGlobalBuffer((__gm__ ElementOTmp *)params.oCoreTmp); | ||
| 153 | + AscendC::GlobalTensor<ElementOTmp> gl; | ||
| 154 | + gl.SetGlobalBuffer((__gm__ ElementOTmp *)params.l); | ||
| 155 | + AscendC::GlobalTensor<float> gTilingFp64; | ||
| 156 | + gTilingFp64.SetGlobalBuffer((__gm__ float *)params.tiling); | ||
| 157 | + | ||
| 158 | + AscendC::GlobalTensor<ElementS> gS; | ||
| 159 | + gS.SetGlobalBuffer((__gm__ ElementS *)params.s); | ||
| 160 | + AscendC::GlobalTensor<ElementP> gP; | ||
| 161 | + gP.SetGlobalBuffer((__gm__ ElementP *)params.p); | ||
| 162 | + AscendC::GlobalTensor<ElementOTmp> gOTmp; | ||
| 163 | + gOTmp.SetGlobalBuffer((__gm__ ElementOTmp *)params.oTmp); | ||
| 164 | + | ||
| 165 | + AscendC::GlobalTensor<int32_t> &gOTmpInt32 = reinterpret_cast<AscendC::GlobalTensor<int32_t> &>(gOTmp); | ||
| 166 | + | ||
| 167 | + AscendC::GlobalTensor<uint32_t> gTiling; | ||
| 168 | + gTiling.SetGlobalBuffer((__gm__ uint32_t *)params.tiling); | ||
| 169 | + | ||
| 170 | + | ||
| 171 | + uint32_t coreIdx = AscendC::GetBlockIdx(); | ||
| 172 | + | ||
| 173 | + uint32_t coreIdx = AscendC::GetBlockIdx() / AscendC::GetSubBlockNum(); | ||
| 174 | + uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | ||
| 175 | + float tor = gTilingFp64.GetValue(TILING_TOR); | ||
| 176 | + | ||
| 177 | + uint32_t coreNum = AscendC::GetBlockNum(); | ||
| 178 | + | ||
| 179 | + // Get tiling parameters | ||
| 180 | + uint32_t batch = gTiling.GetValue(TILING_BATCH); | ||
| 181 | + uint32_t qHeads = gTiling.GetValue(TILING_NUMHEADS); | ||
| 182 | + uint32_t blockSize = gTiling.GetValue(TILING_BLOCKSIZE); | ||
| 183 | + uint32_t maxNumBlocksPerQuery = gTiling.GetValue(TILING_MAXBLOCKS); | ||
| 184 | + uint32_t totalTaskNumSpec = gTiling.GetValue(TILING_TOTAL_QTOKENS); | ||
| 185 | + uint32_t tilingHeadSize = gTiling.GetValue(TILING_HEADSIZE); | ||
| 186 | + uint32_t tilingParaSize = gTiling.GetValue(TILING_PARASIZE); | ||
| 187 | + uint32_t maxKvSplitCoreNum = gTiling.GetValue(TILING_KVCORENUM); | ||
| 188 | + uint32_t formerTaskNum = gTiling.GetValue(TILING_FORMERTASKNUM); | ||
| 189 | + uint32_t tailTaskNum = gTiling.GetValue(TILING_TAILTASKNUM); | ||
| 190 | + | ||
| 191 | + uint32_t embed = NUM512; | ||
| 192 | + uint32_t embedRope = NUM64; | ||
| 193 | + uint32_t kvHeads = NUM1; | ||
| 194 | + uint32_t strideQO = qHeads * embed; | ||
| 195 | + uint32_t strideQORope = qHeads * embedRope; | ||
| 196 | + uint32_t embedRound = RoundUp<BLOCK_SIZE>(embed); | ||
| 197 | + uint32_t glFlag[2] = {1, 1}; | ||
| 198 | + | ||
| 199 | + BlockMmadQK blockMmadQK(resource); | ||
| 200 | + BlockMmadAMLAPV blockMmadAMLAPV(resource); | ||
| 201 | + | ||
| 202 | + EpilogueAMLASoftmax epilogueAMLATP1Softmax(resource, tor, maxKvSplitCoreNum); | ||
| 203 | + EpilogueAMLARescaleO epilogueAMLATP1RescaleO(resource, maxKvSplitCoreNum); | ||
| 204 | + | ||
| 205 | + | ||
| 206 | + uint32_t pingpongIdx = 0; | ||
| 207 | + uint32_t pvLoopPingpongIdx = 0; | ||
| 208 | + uint32_t qkInLoopPingpongIdx = 0; | ||
| 209 | + uint32_t qkLoopPingpongIdx = 0; | ||
| 210 | + bool isForward = true; | ||
| 211 | + uint32_t taskPingPongFlag = 0; | ||
| 212 | + for (uint32_t process = coreIdx; process < formerTaskNum; process += uint32_t(coreNum)) { | ||
| 213 | + uint32_t bigProcess = process - (process % coreNum) + (coreNum - 1); | ||
| 214 | + bigProcess = (bigProcess > formerTaskNum - 1) ? (formerTaskNum - 1) : bigProcess; | ||
| 215 | + uint32_t realProcess = isForward ? process : (bigProcess - process % uint32_t(coreNum)); | ||
| 216 | + isForward = !isForward; | ||
| 217 | + | ||
| 218 | + // Get the offset of each core on the GM | ||
| 219 | + uint32_t offsetTiling = tilingHeadSize + tilingParaSize * realProcess; | ||
| 220 | + uint32_t curBatch = gTiling.GetValue(offsetTiling); | ||
| 221 | + uint32_t curTokenWiseOffset = gTiling.GetValue(offsetTiling + 1); | ||
| 222 | + uint32_t kvSeqlen = gTiling.GetValue(offsetTiling + 2); | ||
| 223 | + uint64_t gmOffsetQ = (uint64_t)(curTokenWiseOffset * strideQO); | ||
| 224 | + uint64_t gmOffsetQRope = (uint64_t)(curTokenWiseOffset * strideQORope); | ||
| 225 | + uint64_t gmOffsetO = curTokenWiseOffset * qHeads * embed; | ||
| 226 | + | ||
| 227 | + if (kvSeqlen == 0) { | ||
| 228 | + continue; | ||
| 229 | + } | ||
| 230 | + uint32_t nLoop = (kvSeqlen + blockSize - 1) / blockSize; | ||
| 231 | + uint32_t stackSeqTile = blockSize * UNIT_BLOCK_STACK_NUM; | ||
| 232 | + uint32_t rowNum = qHeads; | ||
| 233 | + uint32_t rowNumRound = RoundUp<BLOCK_SIZE>(rowNum); | ||
| 234 | + uint64_t gmOffsetBlockTable = curBatch * maxNumBlocksPerQuery; | ||
| 235 | + | ||
| 236 | + if (process == coreIdx) { | ||
| 237 | + uint32_t nIdx = 0; | ||
| 238 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop - 1) { | ||
| 239 | + stackSeqTile = kvSeqlen - nIdx * blockSize; | ||
| 240 | + } else { | ||
| 241 | + stackSeqTile = blockSize * UNIT_BLOCK_STACK_NUM; | ||
| 242 | + } | ||
| 243 | + uint32_t stackSeqTileRound = RoundUp<BLOCK_SIZE>(stackSeqTile); | ||
| 244 | + uint32_t gSPingPongFlag = (pingpongIdx / UNIT_BLOCK_STACK_NUM) % 2; | ||
| 245 | + | ||
| 246 | + LayoutQ layoutQ(rowNum, embed); | ||
| 247 | + LayoutQ layoutQRope(rowNum, embedRope); | ||
| 248 | + LayoutK layoutK(embed, stackSeqTile); | ||
| 249 | + LayoutK layoutKRope(embedRope, stackSeqTile); | ||
| 250 | + LayoutS layoutS(rowNumRound, stackSeqTileRound); | ||
| 251 | + GemmCoord actualBlockShapeQK{rowNum, stackSeqTile, embed + embedRope}; | ||
| 252 | + uint64_t gmOffseS = | ||
| 253 | + (uint64_t)coreIdx * TMP_SIZE_DECODER * 4 + (uint64_t)gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 254 | + // Calculate Q * K^T | ||
| 255 | + blockMmadQK(gQ[gmOffsetQ], gQRope[gmOffsetQRope], gK, gKRope, gblockTable[gmOffsetBlockTable], | ||
| 256 | + gS[gmOffseS], layoutQ, layoutQRope, layoutK, layoutKRope, layoutS, actualBlockShapeQK, | ||
| 257 | + nIdx, nLoop, blockSize, kvSeqlen, qkInLoopPingpongIdx, qkLoopPingpongIdx); | ||
| 258 | + Arch::CrossCoreSetFlag<0x2, PIPE_FIX>(qkReady); | ||
| 259 | + | ||
| 260 | + LayoutP layoutP(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 261 | + LayoutS layoutS(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 262 | + LayoutOTmp layoutOTmp(rowNum, embed, embedRound); | ||
| 263 | + GemmCoord actualBlockShapeQK{rowNum, stackSeqTile, embed}; | ||
| 264 | + uint32_t gmOffsetP = (uint64_t)coreIdx * TMP_SIZE * 2 + | ||
| 265 | + (uint64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 266 | + (uint64_t)gSPingPongFlag * TMP_SIZE; | ||
| 267 | + uint32_t gmOffsetS = (int64_t)coreIdx * TMP_SIZE_DECODER * 4 + | ||
| 268 | + (int64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 269 | + (uint64_t)gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 270 | + uint64_t gmOffsetOTmp = (uint64_t)(coreIdx * TMP_SIZE * 2 + | ||
| 271 | + subBlockIdx * rowNum * embedRound / 2 + | ||
| 272 | + taskPingPongFlag * TMP_SIZE); | ||
| 273 | + uint32_t isLastNTile = (nIdx + UNIT_BLOCK_STACK_NUM > nLoop - 1) ? 1 : 0; | ||
| 274 | + // Softmax one-stage calculation | ||
| 275 | + epilogueAMLATP1Softmax(gP[gmOffsetP], gS[gmOffsetS], gOTmpInt32[gmOffsetOTmp], layoutP, layoutS, | ||
| 276 | + layoutOTmp, actualBlockShapeQK, nIdx, isLastNTile, glFlag, taskPingPongFlag, | ||
| 277 | + gSPingPongFlag); | ||
| 278 | + | ||
| 279 | + pingpongIdx += UNIT_BLOCK_STACK_NUM; | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + // Split k seqlen | ||
| 283 | + for (uint32_t nIdx = UNIT_BLOCK_STACK_NUM; nIdx < nLoop + UNIT_BLOCK_STACK_NUM; | ||
| 284 | + nIdx += UNIT_BLOCK_STACK_NUM, pingpongIdx += UNIT_BLOCK_STACK_NUM) { | ||
| 285 | + if (nIdx < nLoop) { | ||
| 286 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop - 1) { | ||
| 287 | + stackSeqTile = kvSeqlen - nIdx * blockSize; | ||
| 288 | + } else { | ||
| 289 | + stackSeqTile = blockSize * UNIT_BLOCK_STACK_NUM; | ||
| 290 | + } | ||
| 291 | + uint32_t stackSeqTileRound = RoundUp<BLOCK_SIZE>(stackSeqTile); | ||
| 292 | + uint32_t gSPingPongFlag = (pingpongIdx / UNIT_BLOCK_STACK_NUM) % 2; | ||
| 293 | + | ||
| 294 | + // Calculate Q * K^T | ||
| 295 | + LayoutQ layoutQ(rowNum, embed); | ||
| 296 | + LayoutQ layoutQRope(rowNum, embedRope); | ||
| 297 | + LayoutK layoutK(embed, stackSeqTile); | ||
| 298 | + LayoutK layoutKRope(embedRope, stackSeqTile); | ||
| 299 | + LayoutS layoutS(rowNumRound, stackSeqTileRound); | ||
| 300 | + GemmCoord actualBlockShapeQK{rowNum, stackSeqTile, embed + embedRope}; | ||
| 301 | + uint64_t gmOffseS = | ||
| 302 | + (uint64_t)coreIdx * TMP_SIZE_DECODER * 4 + (uint64_t)gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 303 | + blockMmadQK(gQ[gmOffsetQ], gQRope[gmOffsetQRope], gK, gKRope, gblockTable[gmOffsetBlockTable], | ||
| 304 | + gS[gmOffseS], layoutQ, layoutQRope, layoutK, layoutKRope, layoutS, actualBlockShapeQK, | ||
| 305 | + nIdx, nLoop, blockSize, kvSeqlen, qkInLoopPingpongIdx, qkLoopPingpongIdx); | ||
| 306 | + Arch::CrossCoreSetFlag<0x2, PIPE_FIX>(qkReady); | ||
| 307 | + | ||
| 308 | + LayoutP layoutP(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 309 | + LayoutS layoutS(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 310 | + LayoutOTmp layoutOTmp(rowNum, embed, embedRound); | ||
| 311 | + GemmCoord actualBlockShapeQK{rowNum, stackSeqTile, embed}; | ||
| 312 | + uint32_t gmOffsetP = (uint64_t)coreIdx * TMP_SIZE * 2 + | ||
| 313 | + (uint64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 314 | + gSPingPongFlag * TMP_SIZE; | ||
| 315 | + uint32_t gmOffsetS = (int64_t)coreIdx * TMP_SIZE_DECODER * 4 + | ||
| 316 | + (int64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 317 | + gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 318 | + uint64_t gmOffsetOTmp = (uint64_t)(coreIdx * TMP_SIZE * 2 + | ||
| 319 | + subBlockIdx * rowNum * embedRound / 2 + | ||
| 320 | + taskPingPongFlag * TMP_SIZE); | ||
| 321 | + uint32_t isLastNTile = (nIdx + UNIT_BLOCK_STACK_NUM > nLoop - 1) ? 1 : 0; | ||
| 322 | + // Softmax one-stage calculation | ||
| 323 | + epilogueAMLATP1Softmax(gP[gmOffsetP], gS[gmOffsetS], gOTmpInt32[gmOffsetOTmp], layoutP, layoutS, | ||
| 324 | + layoutOTmp, actualBlockShapeQK, nIdx, isLastNTile, glFlag, taskPingPongFlag, | ||
| 325 | + gSPingPongFlag); | ||
| 326 | + | ||
| 327 | + } | ||
| 328 | + uint32_t nextProcess = process + uint32_t(coreNum); | ||
| 329 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop + UNIT_BLOCK_STACK_NUM - 1 && nextProcess < formerTaskNum) { | ||
| 330 | + bool nextIsForward = isForward; | ||
| 331 | + uint32_t nextBigProcess = nextProcess - (nextProcess % coreNum) + (coreNum - 1); | ||
| 332 | + nextBigProcess = (nextBigProcess > formerTaskNum - 1) ? (formerTaskNum - 1) : nextBigProcess; | ||
| 333 | + uint32_t nextRealProcess = | ||
| 334 | + nextIsForward ? nextProcess : (nextBigProcess - nextProcess % uint32_t(coreNum)); | ||
| 335 | + | ||
| 336 | + // Get the offset of each core on the GM | ||
| 337 | + uint32_t nextOffsetTiling = tilingHeadSize + tilingParaSize * nextRealProcess; | ||
| 338 | + uint32_t nextCurBatch = gTiling.GetValue(nextOffsetTiling); | ||
| 339 | + uint32_t nextCurTokenWiseOffset = gTiling.GetValue(nextOffsetTiling + 1); | ||
| 340 | + uint32_t nextKvSeqlen = gTiling.GetValue(nextOffsetTiling + 2); | ||
| 341 | + uint64_t nextGMOffsetQ = (uint64_t)(nextCurTokenWiseOffset * strideQO); | ||
| 342 | + uint64_t nextGMOffsetQRope = (uint64_t)(nextCurTokenWiseOffset * strideQORope); | ||
| 343 | + uint32_t nextNLoop = (nextKvSeqlen + blockSize - 1) / blockSize; | ||
| 344 | + uint64_t nextGMOffsetBlockTable = nextCurBatch * maxNumBlocksPerQuery; | ||
| 345 | + uint32_t nextNIdx = 0; | ||
| 346 | + if (nextNIdx + UNIT_BLOCK_STACK_NUM > nextNLoop - 1) { | ||
| 347 | + stackSeqTile = nextKvSeqlen - nextNIdx * blockSize; | ||
| 348 | + } else { | ||
| 349 | + stackSeqTile = blockSize * UNIT_BLOCK_STACK_NUM; | ||
| 350 | + } | ||
| 351 | + uint32_t stackSeqTileRound = RoundUp<BLOCK_SIZE>(stackSeqTile); | ||
| 352 | + uint32_t gSPingPongFlag = (pingpongIdx / UNIT_BLOCK_STACK_NUM) % 2; | ||
| 353 | + | ||
| 354 | + LayoutQ layoutQ(rowNum, embed); | ||
| 355 | + LayoutQ layoutQRope(rowNum, embedRope); | ||
| 356 | + LayoutK layoutK(embed, stackSeqTile); | ||
| 357 | + LayoutK layoutKRope(embedRope, stackSeqTile); | ||
| 358 | + LayoutS layoutS(rowNumRound, stackSeqTileRound); | ||
| 359 | + GemmCoord nextActualBlockShapeQK{rowNum, stackSeqTile, embed + embedRope}; | ||
| 360 | + uint64_t nextGMOffseS = | ||
| 361 | + (uint64_t)coreIdx * TMP_SIZE_DECODER * 4 + (uint64_t)gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 362 | + // Calculate Q * K^T | ||
| 363 | + blockMmadQK(gQ[nextGMOffsetQ], gQRope[nextGMOffsetQRope], gK, gKRope, | ||
| 364 | + gblockTable[nextGMOffsetBlockTable], gS[nextGMOffseS], layoutQ, layoutQRope, layoutK, | ||
| 365 | + layoutKRope, layoutS, nextActualBlockShapeQK, nextNIdx, nextNLoop, blockSize, | ||
| 366 | + nextKvSeqlen, qkInLoopPingpongIdx, qkLoopPingpongIdx); | ||
| 367 | + Arch::CrossCoreSetFlag<0x2, PIPE_FIX>(qkReady); | ||
| 368 | + | ||
| 369 | + LayoutP nextLayoutP(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 370 | + LayoutS nextLayoutS(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 371 | + LayoutOTmp nextLayoutOTmp(rowNum, embed, embedRound); | ||
| 372 | + GemmCoord nextActualBlockShapeQK{rowNum, stackSeqTile, embed}; | ||
| 373 | + uint32_t nextGMOffsetP = (uint64_t)coreIdx * TMP_SIZE * 2 + | ||
| 374 | + (uint64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 375 | + gSPingPongFlag * TMP_SIZE; | ||
| 376 | + uint32_t nextGMOffsetS = (int64_t)coreIdx * TMP_SIZE_DECODER * 4 + | ||
| 377 | + (int64_t)subBlockIdx * rowNum / 2 * stackSeqTileRound + | ||
| 378 | + gSPingPongFlag * TMP_SIZE_DECODER * 2; | ||
| 379 | + uint64_t gmOffsetOTmp = (uint64_t)(coreIdx * TMP_SIZE * 2 + | ||
| 380 | + subBlockIdx * rowNum * embedRound / 2 + | ||
| 381 | + (1 - taskPingPongFlag) * TMP_SIZE); | ||
| 382 | + uint32_t isLastNTile = (nextNIdx + UNIT_BLOCK_STACK_NUM > nextNLoop - 1) ? 1 : 0; | ||
| 383 | + // Softmax one-stage calculation | ||
| 384 | + epilogueAMLATP1Softmax(gP[nextGMOffsetP], gS[nextGMOffsetS], gOTmpInt32[gmOffsetOTmp], | ||
| 385 | + nextLayoutP, nextLayoutS, nextLayoutOTmp, nextActualBlockShapeQK, nextNIdx, | ||
| 386 | + isLastNTile, glFlag, 1 - taskPingPongFlag, gSPingPongFlag); | ||
| 387 | + | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + // Wait for the four Q * K^T calculations to complete before calculating P * V | ||
| 391 | + if (nIdx >= UNIT_BLOCK_STACK_NUM) { | ||
| 392 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop + UNIT_BLOCK_STACK_NUM - 1) { | ||
| 393 | + stackSeqTile = kvSeqlen - (nIdx - UNIT_BLOCK_STACK_NUM) * blockSize; | ||
| 394 | + } else { | ||
| 395 | + stackSeqTile = blockSize * UNIT_BLOCK_STACK_NUM; | ||
| 396 | + } | ||
| 397 | + uint32_t stackSeqTileRound = RoundUp<BLOCK_SIZE>(stackSeqTile); | ||
| 398 | + | ||
| 399 | + LayoutP layoutP(rowNum, stackSeqTile, stackSeqTileRound); | ||
| 400 | + LayoutV layoutV(stackSeqTile, embed); | ||
| 401 | + LayoutOTmp layoutOTmp(rowNumRound, embedRound); | ||
| 402 | + GemmCoord actualBlockShapePV{rowNum, embed, stackSeqTile}; | ||
| 403 | + uint32_t gPPingPongFlag = (pingpongIdx / UNIT_BLOCK_STACK_NUM - 1) % 2; | ||
| 404 | + uint64_t gmOffseP = (uint64_t)coreIdx * TMP_SIZE * 2 + (uint64_t)gPPingPongFlag * TMP_SIZE; | ||
| 405 | + uint64_t gmOffseOtmp = (uint64_t)(coreIdx * TMP_SIZE * 2 + taskPingPongFlag * TMP_SIZE); | ||
| 406 | + // Calculate P * V | ||
| 407 | + blockMmadAMLAPV(gP[gmOffseP], gK, gblockTable[gmOffsetBlockTable], gOTmp[gmOffseOtmp], layoutP, | ||
| 408 | + layoutV, layoutOTmp, actualBlockShapePV, nIdx, gPPingPongFlag, nLoop, blockSize, | ||
| 409 | + kvSeqlen, softmaxReady, pvLoopPingpongIdx, softmaxAutoAddReady); | ||
| 410 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop + UNIT_BLOCK_STACK_NUM - 1) { | ||
| 411 | + Arch::CrossCoreSetFlag<0x2, PIPE_FIX>(pvReady); | ||
| 412 | + } else { | ||
| 413 | + Arch::CrossCoreSetFlag<0x2, PIPE_FIX>(preAutoAddReady); | ||
| 414 | + } | ||
| 415 | + | ||
| 416 | + if (nIdx + UNIT_BLOCK_STACK_NUM > nLoop + UNIT_BLOCK_STACK_NUM - 1) { | ||
| 417 | + // Wait for P * V calculation to complete | ||
| 418 | + uint32_t rescaleOPingPongFlag = (pingpongIdx / UNIT_BLOCK_STACK_NUM - 1) % 2; | ||
| 419 | + Arch::CrossCoreWaitFlag(pvReady); | ||
| 420 | + LayoutO layoutO(rowNum, embed); | ||
| 421 | + LayoutOTmp layoutOTmp(rowNum, embed, embedRound); | ||
| 422 | + LayoutUpdate layoutUpdate(rowNum, embed, embedRound); | ||
| 423 | + GemmCoord actualBlockShapePV{rowNum, embed, stackSeqTile}; | ||
| 424 | + uint64_t gmOffsetOTmp = (uint64_t)(coreIdx * TMP_SIZE * 2 + taskPingPongFlag * TMP_SIZE); | ||
| 425 | + uint64_t gmOffsetUpdate = (uint64_t)(coreIdx * TMP_SIZE); | ||
| 426 | + // Softmax two-stage update | ||
| 427 | + epilogueAMLATP1RescaleO(gOTmp[gmOffsetOTmp], gOUpdate[gmOffsetUpdate], gO[gmOffsetO], | ||
| 428 | + gOCoreTmp[0], gl[0], layoutOTmp, layoutUpdate, layoutO, | ||
| 429 | + actualBlockShapePV, nIdx, rescaleOPingPongFlag, glFlag, | ||
| 430 | + taskPingPongFlag); | ||
| 431 | + } | ||
| 432 | + | ||
| 433 | + } | ||
| 434 | + } | ||
| 435 | + taskPingPongFlag = 1 - taskPingPongFlag; | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + | ||
| 439 | + AscendC::WaitFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID0); | ||
| 440 | + AscendC::WaitFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID1); | ||
| 441 | + AscendC::WaitFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID2); | ||
| 442 | + AscendC::WaitFlag<AscendC::HardEvent::M_MTE1>(EVENT_ID3); | ||
| 443 | + | ||
| 444 | + AscendC::WaitFlag<AscendC::HardEvent::FIX_M>(EVENT_ID0); | ||
| 445 | + AscendC::WaitFlag<AscendC::HardEvent::FIX_M>(EVENT_ID1); | ||
| 446 | + | ||
| 447 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID0); | ||
| 448 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID1); | ||
| 449 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID2); | ||
| 450 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID3); | ||
| 451 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID4); | ||
| 452 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID5); | ||
| 453 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID6); | ||
| 454 | + AscendC::WaitFlag<AscendC::HardEvent::MTE1_MTE2>(EVENT_ID7); | ||
| 455 | + | ||
| 456 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID0); | ||
| 457 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID0); | ||
| 458 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | ||
| 459 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID2); | ||
| 460 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID3); | ||
| 461 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID4); | ||
| 462 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID5); | ||
| 463 | + | ||
| 464 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID4); | ||
| 465 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID0); | ||
| 466 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID1); | ||
| 467 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | ||
| 468 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | ||
| 469 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID5); | ||
| 470 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID2); | ||
| 471 | + | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | +private: | ||
| 475 | + Arch::Resource<ArchTag> resource; | ||
| 476 | + Arch::CrossCoreFlag qkReady{QK_READY_ID}; | ||
| 477 | + Arch::CrossCoreFlag softmaxReady{SOFTMAX_READY_ID}; | ||
| 478 | + Arch::CrossCoreFlag pvReady{PV_READY_ID}; | ||
| 479 | + Arch::CrossCoreFlag preAutoAddReady{PRE_AUTOADD_READY_ID}; | ||
| 480 | + Arch::CrossCoreFlag softmaxAutoAddReady{SM_AUTOADD_READY_ID}; | ||
| 481 | +}; | ||
| 482 | + | ||
| 483 | +template <class Dtype> | ||
| 484 | +CATLASS_GLOBAL void AMLATp1Spec(uint64_t hardwareSyncAddr, | ||
| 485 | + GM_ADDR q, | ||
| 486 | + GM_ADDR qRope, | ||
| 487 | + GM_ADDR k, | ||
| 488 | + GM_ADDR kRope, | ||
| 489 | + GM_ADDR blockTables, | ||
| 490 | + GM_ADDR o, | ||
| 491 | + GM_ADDR s, | ||
| 492 | + GM_ADDR p, | ||
| 493 | + GM_ADDR oTmp, | ||
| 494 | + GM_ADDR oUpdate, | ||
| 495 | + GM_ADDR oCoreTmp, | ||
| 496 | + GM_ADDR l, | ||
| 497 | + GM_ADDR tiling) | ||
| 498 | +{ | ||
| 499 | + // Set hardware sync address | ||
| 500 | + AscendC::SetSyncBaseAddr(hardwareSyncAddr); | ||
| 501 | + | ||
| 502 | + using ArchTag = Arch::AtlasA2; | ||
| 503 | + using ElementQ = Dtype; | ||
| 504 | + using LayoutQ = layout::RowMajor; | ||
| 505 | + using ElementK = Dtype; | ||
| 506 | + using LayoutK = layout::ColumnMajor; | ||
| 507 | + using ElementV = Dtype; | ||
| 508 | + using LayoutV = layout::RowMajor; | ||
| 509 | + using ElementS = float; | ||
| 510 | + using LayoutS = layout::RowMajor; | ||
| 511 | + using ElementP = Dtype; | ||
| 512 | + using LayoutP = layout::RowMajor; | ||
| 513 | + using ElementO = Dtype; | ||
| 514 | + using LayoutO = layout::RowMajor; | ||
| 515 | + using ElementMask = Dtype; | ||
| 516 | + using LayoutMask = layout::RowMajor; | ||
| 517 | + using ElementOTmp = float; | ||
| 518 | + using LayoutOTmp = layout::RowMajor; | ||
| 519 | + using ElementUpdate = float; | ||
| 520 | + using LayoutUpdate = layout::RowMajor; | ||
| 521 | + | ||
| 522 | + // L1TileShape::K must be embdding | ||
| 523 | + using L1TileShape = GemmShape<128, 128, 576>; | ||
| 524 | + using L0TileShape = L1TileShape; | ||
| 525 | + | ||
| 526 | + // GEMM Block模块,实现Flash MLA的Q * K^T | ||
| 527 | + using DispatchPolicyQK = Gemm::MmadAtlasA2MLAQKTp1Spec; | ||
| 528 | + using QType = Gemm::GemmType<ElementQ, LayoutQ>; | ||
| 529 | + using KType = Gemm::GemmType<ElementK, LayoutK>; | ||
| 530 | + using SType = Gemm::GemmType<ElementS, LayoutS>; | ||
| 531 | + using BlockMmadQK = Gemm::Block::BlockMmad<DispatchPolicyQK, L1TileShape, L0TileShape, QType, KType, SType>; | ||
| 532 | + | ||
| 533 | + // Epilogue Block模块,实现Flash MLA中当前S基块的softmax | ||
| 534 | + using PType = Gemm::GemmType<ElementP, LayoutP>; | ||
| 535 | + using MaskType = Gemm::GemmType<ElementMask, LayoutMask>; | ||
| 536 | + using OTmpType = Gemm::GemmType<ElementOTmp, LayoutOTmp>; | ||
| 537 | + using EpilogueAMLASoftmax = | ||
| 538 | + Epilogue::Block::BlockEpilogue<Epilogue::EpilogueAtlasA2AMLATP1Softmax, PType, SType, OTmpType, MaskType>; | ||
| 539 | + | ||
| 540 | + // GEMM Block模块,实现Flash MLA的P * V | ||
| 541 | + using VType = Gemm::GemmType<ElementV, LayoutV>; | ||
| 542 | + using DispatchPolicyAMLAPV = Gemm::MmadAtlasA2AMLAPVTp1Spec; | ||
| 543 | + using BlockMmadAMLAPV = Gemm::Block::BlockMmad<DispatchPolicyAMLAPV, L1TileShape, L0TileShape, PType, VType, OTmpType>; | ||
| 544 | + | ||
| 545 | + // Epilogue Block模块,实现Flash MLA中当前O基块的更新 | ||
| 546 | + using OType = Gemm::GemmType<ElementO, LayoutO>; | ||
| 547 | + using OUpdateType = Gemm::GemmType<ElementUpdate, LayoutUpdate>; | ||
| 548 | + using EpilogueAMLARescaleO = | ||
| 549 | + Epilogue::Block::BlockEpilogue<Epilogue::EpilogueAtlasA2AMLATP1RescaleO, OType, OUpdateType, OTmpType>; | ||
| 550 | + | ||
| 551 | + // Epilogue Block模块,实现Flash MLA中flash decoding | ||
| 552 | + using lType = Gemm::GemmType<ElementUpdate, LayoutUpdate>; | ||
| 553 | + constexpr uint32_t ComputeEleNum = 6144; | ||
| 554 | + using EpilogueMLAFDRescaleO = | ||
| 555 | + Epilogue::Block::BlockEpilogue<Epilogue::EpilogueAtlasA2MLAFDRescaleO<ComputeEleNum>, OType, lType>; | ||
| 556 | + | ||
| 557 | + // Kernel level | ||
| 558 | + using MLAKernel = AMLAKernelTp1Spec<BlockMmadQK, BlockMmadAMLAPV, EpilogueAMLASoftmax, | ||
| 559 | + EpilogueAMLARescaleO, EpilogueMLAFDRescaleO>; | ||
| 560 | + typename MLAKernel::Params params{q, qRope, k, kRope, blockTables, o, s, p, oTmp, oUpdate, oCoreTmp, l, tiling}; | ||
| 561 | + | ||
| 562 | + // call kernel | ||
| 563 | + MLAKernel mla; | ||
| 564 | + mla(params); | ||
| 565 | +} | ||
| @@ -49,8 +49,14 @@ class TestPagedMLAttention(): | |||
| 49 | dtype: any | 49 | dtype: any |
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | - def check_attr(cls, batch: int, q_seqlen: int, kv_seqlen: int, num_blocks: int, block_size: int): | 52 | + def check_attr(cls, batch: int, q_seqlen_list: list, k_seqlen_list: list, num_blocks: int, block_size: int): |
| 53 | - if batch * kv_seqlen > num_blocks * block_size: | 53 | + # 检查列表长度是否与 batch size 匹配 |
| 54 | + if len(q_seqlen_list) != batch or len(k_seqlen_list) != batch: | ||
| 55 | + logging("[ERROR] The length of q_seqlen_list and k_seqlen_list must be equal to batch size.") | ||
| 56 | + sys.exit() | ||
| 57 | + | ||
| 58 | + # 检查缓存大小是否足够 | ||
| 59 | + if sum(k_seqlen_list) > num_blocks * block_size: | ||
| 54 | logging("[ERROR] the number of K and V tokens is too big to fit in the paged cache.") | 60 | logging("[ERROR] the number of K and V tokens is too big to fit in the paged cache.") |
| 55 | sys.exit() | 61 | sys.exit() |
| 56 | 62 | ||
| @@ -58,9 +64,18 @@ class TestPagedMLAttention(): | |||
| 58 | logging("[ERROR] blockSize != 128 is not supported.") | 64 | logging("[ERROR] blockSize != 128 is not supported.") |
| 59 | sys.exit() | 65 | sys.exit() |
| 60 | 66 | ||
| 61 | - if q_seqlen > 4: | 67 | + # 检查每个 q_seqlen 是否在有效范围内 [1, 4] |
| 62 | - logging("[ERROR] q_seqlen > 4 is not supported.") | 68 | + for q_seqlen in q_seqlen_list: |
| 63 | - sys.exit() | 69 | + if q_seqlen > 4 or q_seqlen < 1: |
| 70 | + logging(f"[ERROR] q_seqlen value {q_seqlen} is not in the valid range of [1, 4].") | ||
| 71 | + sys.exit() | ||
| 72 | + | ||
| 73 | + # 检查每个 kv_seqlen 是否在有效范围内 [128, 16384] | ||
| 74 | + for kv_seqlen in k_seqlen_list: | ||
| 75 | + if kv_seqlen > 16384 or kv_seqlen < 128: | ||
| 76 | + logging(f"[ERROR] kv_seqlen value {kv_seqlen} is not in the valid range of [128, 16384].") | ||
| 77 | + sys.exit() | ||
| 78 | + | ||
| 64 | 79 | ||
| 65 | 80 | ||
| 66 | def group_matmul(cls, head, kv_head, left, right): | 81 | def group_matmul(cls, head, kv_head, left, right): |
| @@ -101,7 +116,7 @@ class TestPagedMLAttention(): | |||
| 101 | sim_high = sim_high + ( | 116 | sim_high = sim_high + ( |
| 102 | mask[:sim_high.shape[-2], :sim_high.shape[-1]] * self.post_mask_factor | 117 | mask[:sim_high.shape[-2], :sim_high.shape[-1]] * self.post_mask_factor |
| 103 | ).astype(np.float32) | 118 | ).astype(np.float32) |
| 104 | - | 119 | + |
| 105 | # softmax | 120 | # softmax |
| 106 | p_high = self.softmax_numpy(sim_high) | 121 | p_high = self.softmax_numpy(sim_high) |
| 107 | p = p_high.astype(query.dtype) | 122 | p = p_high.astype(query.dtype) |
| @@ -188,7 +203,7 @@ class TestPagedMLAttention(): | |||
| 188 | 203 | ||
| 189 | pre_mask_factor = -10000.0 | 204 | pre_mask_factor = -10000.0 |
| 190 | if gen_data_params.mask_type == 1: | 205 | if gen_data_params.mask_type == 1: |
| 191 | - mask = np.zeros(shape=(num_tokens, max_k_seqlen)).astype(np.float16) | 206 | + mask = np.zeros(shape=(num_tokens, max_k_seqlen)).astype(gen_data_params.dtype) |
| 192 | pre_qseqlen = 0 | 207 | pre_qseqlen = 0 |
| 193 | for i in range(batch_size): | 208 | for i in range(batch_size): |
| 194 | qseqlen = gen_data_params.q_seqlen_list[i] | 209 | qseqlen = gen_data_params.q_seqlen_list[i] |
| @@ -226,20 +241,35 @@ class TestPagedMLAttention(): | |||
| 226 | os.path.join(WORKSPACE, "data", "kv_seqlen.bin")) | 241 | os.path.join(WORKSPACE, "data", "kv_seqlen.bin")) |
| 227 | if mask: | 242 | if mask: |
| 228 | mask.tofile(os.path.join(WORKSPACE, "data", "mask.bin")) | 243 | mask.tofile(os.path.join(WORKSPACE, "data", "mask.bin")) |
| 229 | - ref_output.astype(np.float32).tofile(os.path.join(WORKSPACE, "data", "golden.bin")) | 244 | + ref_output.astype(gen_data_params.dtype).tofile(os.path.join(WORKSPACE, "data", "cpu_low.bin")) |
| 245 | + true_out.astype(np.float32).tofile(os.path.join(WORKSPACE, "data", "golden.bin")) | ||
| 230 | 246 | ||
| 231 | 247 | ||
| 232 | if __name__ == "__main__": | 248 | if __name__ == "__main__": |
| 233 | os.makedirs(os.path.join(WORKSPACE, "data"), exist_ok=True) | 249 | os.makedirs(os.path.join(WORKSPACE, "data"), exist_ok=True) |
| 234 | 250 | ||
| 251 | + | ||
| 252 | + # 修改命令行参数解析逻辑,以接受列表形式的输入 | ||
| 253 | + if len(sys.argv) != 8: | ||
| 254 | + print("Usage: python gen_data.py <batchSize> \"<qSeqlen_list>\" \"<kvSeqlen_list>\" <qheadNum> <numBlock> <blockSize> <dtype>") | ||
| 255 | + print("Example: python gen_data.py 4 \"1,2,3,4\" \"128,256,512,1024\" 16 16 128 half") | ||
| 256 | + sys.exit(1) | ||
| 257 | + | ||
| 235 | batch = int(sys.argv[1]) | 258 | batch = int(sys.argv[1]) |
| 236 | - q_seqlen = int(sys.argv[2]) | 259 | + |
| 237 | - kv_seqlen = int(sys.argv[3]) | 260 | + # 将逗号分隔的字符串解析为整数列表 |
| 261 | + q_seqlen_list_str = sys.argv[2] | ||
| 262 | + kv_seqlen_list_str = sys.argv[3] | ||
| 263 | + q_seqlen_list = [int(x.strip()) for x in q_seqlen_list_str.split(',')] | ||
| 264 | + kv_seqlen_list = [int(x.strip()) for x in kv_seqlen_list_str.split(',')] | ||
| 265 | + | ||
| 238 | num_head = int(sys.argv[4]) | 266 | num_head = int(sys.argv[4]) |
| 239 | num_blocks = int(sys.argv[5]) | 267 | num_blocks = int(sys.argv[5]) |
| 240 | block_size = int(sys.argv[6]) | 268 | block_size = int(sys.argv[6]) |
| 241 | str_dtype = str(sys.argv[7]) | 269 | str_dtype = str(sys.argv[7]) |
| 242 | - max_kv_seqlen = kv_seqlen | 270 | + max_kv_seqlen = max(kv_seqlen_list) if kv_seqlen_list else 0 |
| 271 | + | ||
| 272 | + | ||
| 243 | mask_type = 0 | 273 | mask_type = 0 |
| 244 | kv_heads = 1 | 274 | kv_heads = 1 |
| 245 | embedding_size = 512 | 275 | embedding_size = 512 |
| @@ -251,13 +281,13 @@ if __name__ == "__main__": | |||
| 251 | else: | 281 | else: |
| 252 | logging("[ERROR] dtype must be half or bf16") | 282 | logging("[ERROR] dtype must be half or bf16") |
| 253 | sys.exit() | 283 | sys.exit() |
| 254 | - q_seqlen_list = [q_seqlen] * batch | 284 | + |
| 255 | - kv_seqlen_list = [kv_seqlen] * batch | ||
| 256 | - | ||
| 257 | testObj = TestPagedMLAttention() | 285 | testObj = TestPagedMLAttention() |
| 258 | - testObj.check_attr(batch, q_seqlen, kv_seqlen, num_blocks, block_size) | 286 | + |
| 287 | + testObj.check_attr(batch, q_seqlen_list, kv_seqlen_list, num_blocks, block_size) | ||
| 259 | gen_data_params = testObj.GenDataParams(q_seqlen_list, kv_seqlen_list, num_head, | 288 | gen_data_params = testObj.GenDataParams(q_seqlen_list, kv_seqlen_list, num_head, |
| 260 | kv_heads, embedding_size, embedding_size_rope, | 289 | kv_heads, embedding_size, embedding_size_rope, |
| 261 | num_blocks, block_size, mask_type, dtype) | 290 | num_blocks, block_size, mask_type, dtype) |
| 291 | + | ||
| 262 | testObj.calc_data(gen_data_params) | 292 | testObj.calc_data(gen_data_params) |
| 263 | 293 | ||
| @@ -8,14 +8,15 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | + | ||
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | - | ||
| 15 | - | ||
| 16 | constexpr uint32_t QK_READY_ID = 1; | 15 | constexpr uint32_t QK_READY_ID = 1; |
| 17 | constexpr uint32_t SOFTMAX_READY_ID = 2; | 16 | constexpr uint32_t SOFTMAX_READY_ID = 2; |
| 18 | constexpr uint32_t PV_READY_ID = 3; | 17 | constexpr uint32_t PV_READY_ID = 3; |
| 18 | +constexpr uint32_t PRE_AUTOADD_READY_ID = 0; | ||
| 19 | +constexpr uint32_t SM_AUTOADD_READY_ID = 7; | ||
| 19 | constexpr uint32_t BLOCK_SIZE = 16; | 20 | constexpr uint32_t BLOCK_SIZE = 16; |
| 20 | constexpr uint32_t TMP_SIZE = 65536; | 21 | constexpr uint32_t TMP_SIZE = 65536; |
| 21 | constexpr uint32_t TMP_SIZE_DECODER = 32768; | 22 | constexpr uint32_t TMP_SIZE_DECODER = 32768; |
| @@ -39,6 +40,8 @@ constexpr int32_t TILING_KVCORENUM = 16; | |||
| 39 | constexpr int32_t TILING_TOTAL_QTOKENS = 18; | 40 | constexpr int32_t TILING_TOTAL_QTOKENS = 18; |
| 40 | constexpr int32_t TILING_FORMERTASKNUM = 19; | 41 | constexpr int32_t TILING_FORMERTASKNUM = 19; |
| 41 | constexpr int32_t TILING_TAILTASKNUM = 20; | 42 | constexpr int32_t TILING_TAILTASKNUM = 20; |
| 43 | +constexpr int32_t TILING_PROCESSNUM = 21; | ||
| 44 | +constexpr int32_t CUTASK_START_OFFSET = 25; | ||
| 42 | constexpr int32_t TILING_BLOCKSIZE_CALC = 25; | 45 | constexpr int32_t TILING_BLOCKSIZE_CALC = 25; |
| 43 | constexpr int32_t TILING_HEADDIM_K_SPLIT = 38; | 46 | constexpr int32_t TILING_HEADDIM_K_SPLIT = 38; |
| 44 | constexpr int32_t TILING_HEADDIM_V_SPLIT = 39; | 47 | constexpr int32_t TILING_HEADDIM_V_SPLIT = 39; |
| @@ -16,25 +16,41 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 20 | + | ||
| 19 | // Helper methods to check for errors | 21 | // Helper methods to check for errors |
| 20 | 22 | ||
| 21 | 23 | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 26 | + | ||
| 24 | 27 | ||
| 25 | 28 | ||
| 26 | using namespace std; | 29 | using namespace std; |
| 27 | 30 | ||
| 31 | +// Helper function to split comma-separated string into vector of uint32_t | ||
| 32 | +vector<uint32_t> splitSeqList(const string &seqStr) { | ||
| 33 | + vector<uint32_t> seqList; | ||
| 34 | + stringstream ss(seqStr); | ||
| 35 | + string item; | ||
| 36 | + while (getline(ss, item, ',')) { | ||
| 37 | + seqList.push_back(static_cast<uint32_t>(stoul(item))); | ||
| 38 | + } | ||
| 39 | + return seqList; | ||
| 40 | +} | ||
| 41 | + | ||
| 28 | // This code section describes the parameters to execute the run function. | 42 | // This code section describes the parameters to execute the run function. |
| 29 | struct Options { | 43 | struct Options { |
| 30 | - static constexpr auto HELPER = "Usage: mla batch qSeqlen kvSeqlen numHeads numBlocks blockSize [--dtype DTYPE " | 44 | + static constexpr auto HELPER = |
| 31 | - "--datapath DATA_PATH --device DEVICE_ID]\n"; | 45 | + "Usage: mla batch \"qSeqlenList\" \"kvSeqlenList\" numHeads numBlocks blockSize [--dtype DTYPE " |
| 46 | + "--datapath DATA_PATH --device DEVICE_ID]\n" | ||
| 47 | + "Example: ./19_mla 4 \"1,2,3,4\" \"128,256,512,1024\" 16 16 128\n"; | ||
| 32 | static constexpr auto MIN_ARGS = 7; | 48 | static constexpr auto MIN_ARGS = 7; |
| 33 | 49 | ||
| 34 | // Define default value. | 50 | // Define default value. |
| 35 | uint32_t batch{0}; | 51 | uint32_t batch{0}; |
| 36 | - uint32_t qSeqlen{0}; | 52 | + vector<uint32_t> qSeqlenList; |
| 37 | - uint32_t kvSeqlen{0}; | 53 | + vector<uint32_t> kvSeqlenList; |
| 38 | uint32_t numHeads{0}; | 54 | uint32_t numHeads{0}; |
| 39 | uint32_t numBlocks{0}; | 55 | uint32_t numBlocks{0}; |
| 40 | uint32_t blockSize{0}; | 56 | uint32_t blockSize{0}; |
| @@ -61,8 +77,15 @@ struct Options { | |||
| 61 | // Allocate arguments to parameters. | 77 | // Allocate arguments to parameters. |
| 62 | uint32_t argIndex = 1; | 78 | uint32_t argIndex = 1; |
| 63 | batch = atoi(argv[argIndex++]); | 79 | batch = atoi(argv[argIndex++]); |
| 64 | - qSeqlen = atoi(argv[argIndex++]); | 80 | + string qSeqStr = argv[argIndex++]; |
| 65 | - kvSeqlen = atoi(argv[argIndex++]); | 81 | + string kvSeqStr = argv[argIndex++]; |
| 82 | + qSeqlenList = splitSeqList(qSeqStr); | ||
| 83 | + kvSeqlenList = splitSeqList(kvSeqStr); | ||
| 84 | + if (qSeqlenList.size() != batch || kvSeqlenList.size() != batch) { | ||
| 85 | + printf("Error: The number of elements in qSeqlenList and kvSeqlenList must match the batch size.\n"); | ||
| 86 | + printf(HELPER); | ||
| 87 | + return -1; | ||
| 88 | + } | ||
| 66 | numHeads = atoi(argv[argIndex++]); | 89 | numHeads = atoi(argv[argIndex++]); |
| 67 | numBlocks = atoi(argv[argIndex++]); | 90 | numBlocks = atoi(argv[argIndex++]); |
| 68 | blockSize = atoi(argv[argIndex++]); | 91 | blockSize = atoi(argv[argIndex++]); |
| @@ -109,8 +132,6 @@ static void Run(const Options &options) | |||
| 109 | 132 | ||
| 110 | // Parameters initialization. | 133 | // Parameters initialization. |
| 111 | int32_t batch = options.batch; | 134 | int32_t batch = options.batch; |
| 112 | - int32_t qSeqlen = options.qSeqlen; | ||
| 113 | - int32_t kvSeqlen = options.kvSeqlen; | ||
| 114 | int32_t numHeads = options.numHeads; | 135 | int32_t numHeads = options.numHeads; |
| 115 | int32_t kvHeads = options.kvHeads; | 136 | int32_t kvHeads = options.kvHeads; |
| 116 | int32_t embeddingSize = options.embeddingSize; | 137 | int32_t embeddingSize = options.embeddingSize; |
| @@ -120,20 +141,27 @@ static void Run(const Options &options) | |||
| 120 | int32_t maskType = options.maskType; | 141 | int32_t maskType = options.maskType; |
| 121 | string dataType = options.dataType; | 142 | string dataType = options.dataType; |
| 122 | string dataPath = options.dataPath; | 143 | string dataPath = options.dataPath; |
| 123 | - int32_t maxKvSeqlen = kvSeqlen; | 144 | + int32_t maxKvSeqlen = 0; |
| 145 | + if (!options.kvSeqlenList.empty()) { | ||
| 146 | + maxKvSeqlen = options.kvSeqlenList[0]; | ||
| 147 | + for (size_t i = 1; i < options.kvSeqlenList.size(); ++i) { | ||
| 148 | + if (options.kvSeqlenList[i] > maxKvSeqlen) { | ||
| 149 | + maxKvSeqlen = options.kvSeqlenList[i]; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + } | ||
| 124 | 153 | ||
| 125 | if ((dataType != "half") && (dataType != "bf16")) { | 154 | if ((dataType != "half") && (dataType != "bf16")) { |
| 126 | cerr << "[ERROR] dtype must be 'half' or 'bf16'." << endl; | 155 | cerr << "[ERROR] dtype must be 'half' or 'bf16'." << endl; |
| 127 | return; | 156 | return; |
| 128 | } | 157 | } |
| 129 | 158 | ||
| 130 | - uint32_t dTypeKey = (dataType == "half") ? 0 : 1; | 159 | + int32_t dTypeKey = (dataType == "half") ? 0 : 1; |
| 131 | - uint32_t specStraKey = (numHeads == MLATiling::NUM128) ? 1 : 0; | 160 | + int32_t specStraKey = (numHeads == MLATiling::NUM128) ? 1 : 0; |
| 132 | 161 | ||
| 133 | // 3 bits for tilingKey(specStraKey : 1, dTypeKey : 2) | 162 | // 3 bits for tilingKey(specStraKey : 1, dTypeKey : 2) |
| 134 | uint32_t dTypeKeyBitLen = 2; | 163 | uint32_t dTypeKeyBitLen = 2; |
| 135 | uint32_t tilingKey = (specStraKey << dTypeKeyBitLen) + dTypeKey; | 164 | uint32_t tilingKey = (specStraKey << dTypeKeyBitLen) + dTypeKey; |
| 136 | - std::cout << "tilingKey : " << tilingKey << std::endl; | ||
| 137 | 165 | ||
| 138 | // read qNtokens num | 166 | // read qNtokens num |
| 139 | void *qNtokens = nullptr; | 167 | void *qNtokens = nullptr; |
| @@ -141,6 +169,11 @@ static void Run(const Options &options) | |||
| 141 | ReadFile(dataPath + "/q_ntokens.bin", qNtokens, 1 * sizeof(int32_t)); | 169 | ReadFile(dataPath + "/q_ntokens.bin", qNtokens, 1 * sizeof(int32_t)); |
| 142 | int32_t numTokens = static_cast<int32_t *>(qNtokens)[0]; | 170 | int32_t numTokens = static_cast<int32_t *>(qNtokens)[0]; |
| 143 | 171 | ||
| 172 | + if ((numHeads == MLATiling::NUM128) && (numTokens % aicCoreNum <= 10) && (batch <= 40)) { | ||
| 173 | + tilingKey = (dTypeKey == 0) ? 7 : 8; | ||
| 174 | + } | ||
| 175 | + std::cout << "tilingKey : " << tilingKey << std::endl; | ||
| 176 | + | ||
| 144 | // read qSeq | 177 | // read qSeq |
| 145 | void *qSeq = nullptr; | 178 | void *qSeq = nullptr; |
| 146 | ACL_CHECK(aclrtMallocHost(&qSeq, batch * sizeof(int32_t))); | 179 | ACL_CHECK(aclrtMallocHost(&qSeq, batch * sizeof(int32_t))); |
| @@ -253,9 +286,9 @@ static void Run(const Options &options) | |||
| 253 | 286 | ||
| 254 | ACL_CHECK(aclrtMemcpy(tilingDevice, tilingSize, tilingHost, tilingSize, ACL_MEMCPY_HOST_TO_DEVICE)); | 287 | ACL_CHECK(aclrtMemcpy(tilingDevice, tilingSize, tilingHost, tilingSize, ACL_MEMCPY_HOST_TO_DEVICE)); |
| 255 | 288 | ||
| 256 | - uint32_t kvSplitCoreNum = *((uint32_t *)tilingHost + MLATiling::TILING_KVCORENUM); | 289 | + uint32_t maxKvSplitCoreNum = *((uint32_t *)tilingHost + MLATiling::TILING_KVCORENUM); |
| 257 | - uint64_t oFdSize = embeddingSize * numHeads * numTokens * kvSplitCoreNum * sizeof(float); | 290 | + uint64_t oFdSize = embeddingSize * numHeads * numTokens * maxKvSplitCoreNum * sizeof(float); |
| 258 | - uint64_t lSize = numTokens * numHeads * kvSplitCoreNum * sizeof(float); | 291 | + uint64_t lSize = numTokens * numHeads * maxKvSplitCoreNum * sizeof(float); |
| 259 | 292 | ||
| 260 | uint8_t *oCoreTmpDevice; | 293 | uint8_t *oCoreTmpDevice; |
| 261 | ACL_CHECK(aclrtMalloc((void **)(&oCoreTmpDevice), oFdSize, ACL_MEM_MALLOC_HUGE_FIRST)); | 294 | ACL_CHECK(aclrtMalloc((void **)(&oCoreTmpDevice), oFdSize, ACL_MEM_MALLOC_HUGE_FIRST)); |
| @@ -268,26 +301,39 @@ static void Run(const Options &options) | |||
| 268 | ACL_CHECK(aclrtGetHardwareSyncAddr(reinterpret_cast<void**>(&hardwareSyncAddr))); | 301 | ACL_CHECK(aclrtGetHardwareSyncAddr(reinterpret_cast<void**>(&hardwareSyncAddr))); |
| 269 | 302 | ||
| 270 | // use Tp1Spec kernel to get better performance when numHeads = 128 | 303 | // use Tp1Spec kernel to get better performance when numHeads = 128 |
| 271 | - if (tilingKey == 0) { | 304 | + switch (tilingKey) { |
| 272 | - MLAFp16<<<blockDim, nullptr, stream>>>( | 305 | + case 0: |
| 273 | - hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, blockTableDevice, oDevice, sDevice, pDevice, | 306 | + MLA<half><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, |
| 274 | - oTmpDevice, globaloDevice, oCoreTmpDevice, lDevice, tilingDevice | 307 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, |
| 275 | - ); | 308 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); |
| 276 | - } else if (tilingKey == 1) { | 309 | + break; |
| 277 | - MLABf16<<<blockDim, nullptr, stream>>>( | 310 | + case 1: |
| 278 | - hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, blockTableDevice, oDevice, sDevice, pDevice, | 311 | + MLA<bfloat16_t><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, |
| 279 | - oTmpDevice, globaloDevice, oCoreTmpDevice, lDevice, tilingDevice | 312 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, |
| 280 | - ); | 313 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); |
| 281 | - } else if (tilingKey == 4) { | 314 | + break; |
| 282 | - MLATp1SpecFp16<<<blockDim, nullptr, stream>>>( | 315 | + case 4: |
| 283 | - hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, blockTableDevice, oDevice, sDevice, pDevice, | 316 | + AMLATp1Spec<half><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, |
| 284 | - oTmpDevice, globaloDevice, oCoreTmpDevice, lDevice, tilingDevice | 317 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, |
| 285 | - ); | 318 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); |
| 286 | - } else if (tilingKey == 5) { | 319 | + break; |
| 287 | - MLATp1SpecBf16<<<blockDim, nullptr, stream>>>( | 320 | + case 5: |
| 288 | - hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, blockTableDevice, oDevice, sDevice, pDevice, | 321 | + AMLATp1Spec<bfloat16_t><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, |
| 289 | - oTmpDevice, globaloDevice, oCoreTmpDevice, lDevice, tilingDevice | 322 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, |
| 290 | - ); | 323 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); |
| 324 | + break; | ||
| 325 | + case 7: | ||
| 326 | + MLATp1Spec<half><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, | ||
| 327 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, | ||
| 328 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); | ||
| 329 | + break; | ||
| 330 | + case 8: | ||
| 331 | + MLATp1Spec<bfloat16_t><<<blockDim, nullptr, stream>>>(hardwareSyncAddr, qDevice, qRopeDevice, kDevice, kRopeDevice, | ||
| 332 | + blockTableDevice, oDevice, sDevice, pDevice, oTmpDevice, | ||
| 333 | + globaloDevice, oCoreTmpDevice, lDevice, tilingDevice); | ||
| 334 | + break; | ||
| 335 | + default: | ||
| 336 | + break; | ||
| 291 | } | 337 | } |
| 292 | ACL_CHECK(aclrtSynchronizeStream(stream)); | 338 | ACL_CHECK(aclrtSynchronizeStream(stream)); |
| 293 | // Copy the result from device to host | 339 | // Copy the result from device to host |
| @@ -304,13 +350,28 @@ static void Run(const Options &options) | |||
| 304 | const size_t goldenSize = qoSize * 2; | 350 | const size_t goldenSize = qoSize * 2; |
| 305 | ReadFile(dataPath + "/golden.bin", goldenHost.data(), goldenSize); | 351 | ReadFile(dataPath + "/golden.bin", goldenHost.data(), goldenSize); |
| 306 | 352 | ||
| 307 | - // Compare the result | 353 | + // Compute the cpulow result |
| 308 | - vector<uint64_t> errorIndices = (dataType == "half") ? golden::CompareData(oHostHalf, goldenHost, kvSeqlen) | 354 | + // cpu_low.bin is written in fp16 (same format as result.bin), NOT fp32 like golden.bin. |
| 309 | - : golden::CompareData(oHostBf16, goldenHost, kvSeqlen); | 355 | + // Read it as fp16 first, then widen to float for comparison. |
| 310 | - if (errorIndices.empty()) { | 356 | + vector<float> cpulowHost(qoSize / sizeof(fp16_t)); |
| 357 | + vector<fp16_t> cpulowFp16Tmp(qoSize / sizeof(fp16_t)); | ||
| 358 | + const size_t cpulowSize = qoSize; // fp16 binary: qoSize bytes | ||
| 359 | + ReadFile(dataPath + "/cpu_low.bin", cpulowFp16Tmp.data(), cpulowSize); | ||
| 360 | + for (size_t i = 0; i < cpulowFp16Tmp.size(); ++i) { | ||
| 361 | + cpulowHost[i] = static_cast<float>(cpulowFp16Tmp[i]); | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + // Compute error metrics | ||
| 365 | + auto errorMetrics = (dataType == "half") | ||
| 366 | + ? golden::ComputeErrorMetrics(oHostHalf, cpulowHost, goldenHost, 10.0, 2.0, 2.0) | ||
| 367 | + : golden::ComputeErrorMetrics(oHostBf16, cpulowHost, goldenHost, 10.0, 2.0, 2.0); | ||
| 368 | + if (errorMetrics.passed) { | ||
| 311 | cout << "Compare success." << endl; | 369 | cout << "Compare success." << endl; |
| 312 | } else { | 370 | } else { |
| 313 | - cerr << "Compare failed. Error count: " << errorIndices.size() << endl; | 371 | + cerr << "Error ratios exceed thresholds:" << endl; |
| 372 | + cerr << "MARE ratio: " << errorMetrics.mareRatio << " (threshold: 10)" << endl; | ||
| 373 | + cerr << "MERE ratio: " << errorMetrics.mereRatio << " (threshold: 2)" << endl; | ||
| 374 | + cerr << "RMSE ratio: " << errorMetrics.rmseRatio << " (threshold: 2)" << endl; | ||
| 314 | } | 375 | } |
| 315 | 376 | ||
| 316 | // Free host memory allocations. | 377 | // Free host memory allocations. |
| @@ -12,13 +12,13 @@ CATLASS MLA是基于CATLASS Gemm API实现的亲和昇腾AtlasA2硬件的Flash-M | |||
| 12 | Tiling计算的逻辑位于[mla.cpp](./mla.cpp)文件中,在调用算子前,需要准备好tiling计算所需的各项参数,赋值给MLAInfo结构体,并调用`GetMLATilingParam`函数。[mla.cpp](./mla.cpp)中提供了一个示例 | 12 | Tiling计算的逻辑位于[mla.cpp](./mla.cpp)文件中,在调用算子前,需要准备好tiling计算所需的各项参数,赋值给MLAInfo结构体,并调用`GetMLATilingParam`函数。[mla.cpp](./mla.cpp)中提供了一个示例 |
| 13 | 13 | ||
| 14 | ```c++ | 14 | ```c++ |
| 15 | -// 准备Tiling计算所需的中间结构体以及Host侧空间 | 15 | +// 准备Tiling计算所需的中间结构体以及HOST侧空间 |
| 16 | MLATiling::MLAInfo mlaInfo; | 16 | MLATiling::MLAInfo mlaInfo; |
| 17 | ... | 17 | ... |
| 18 | MLATiling::GetMLATilingParam(mlaInfo, blockDim, (uint32_t *)tilingHost); | 18 | MLATiling::GetMLATilingParam(mlaInfo, blockDim, (uint32_t *)tilingHost); |
| 19 | ``` | 19 | ``` |
| 20 | 20 | ||
| 21 | -`GetMLATilingParam`函数中,调用了两个函数`GetMLATilingCommon`与`GetMLATilingSpec`,分别对应了通用场景下和特化场景下的分核逻辑 | 21 | +`GetMLATilingParam`函数中,调用了两个函数`GetMLATilingCommon`与`GetMLATilingSpec`,分别对应了通用场景下/特化场景下的分核逻辑 |
| 22 | 22 | ||
| 23 | ## Kernel | 23 | ## Kernel |
| 24 | 24 | ||
| @@ -42,7 +42,7 @@ MLATiling::GetMLATilingParam(mlaInfo, blockDim, (uint32_t *)tilingHost); | |||
| 42 | 在本算子中,使用了Block和Tile层级组件来组装Kernel,具体步骤为: | 42 | 在本算子中,使用了Block和Tile层级组件来组装Kernel,具体步骤为: |
| 43 | 43 | ||
| 44 | 1. 组装attention计算中的两个BlockMmad(QK,PV)以及三个BlockEpilogue(softmax, rescaleO, flashDecoding)。 | 44 | 1. 组装attention计算中的两个BlockMmad(QK,PV)以及三个BlockEpilogue(softmax, rescaleO, flashDecoding)。 |
| 45 | -2. 将Block组合在一起构建成`MLAKernel`,并在Kernel类中完成对各个Block的循环调用。 | 45 | +2. 将Block组合在一起构建成`MLAKernel`,并在Kernel类中完成对各个Block的循环调用。 |
| 46 | 46 | ||
| 47 | 这一过程也体现在Kernel入口的代码中(以[mla_kernel.cpp](./mla_kernel.cpp)为例): | 47 | 这一过程也体现在Kernel入口的代码中(以[mla_kernel.cpp](./mla_kernel.cpp)为例): |
| 48 | 48 | ||
| @@ -73,6 +73,7 @@ using EpilogueMLARescaleO = | |||
| 73 | Epilogue::Block::BlockEpilogue<Epilogue::EpilogueAtlasA2MLARescaleO, OType, OUpdateType, OTmpType>; | 73 | Epilogue::Block::BlockEpilogue<Epilogue::EpilogueAtlasA2MLARescaleO, OType, OUpdateType, OTmpType>; |
| 74 | 74 | ||
| 75 | // Epilogue Block模块, 实现Flash MLA中flash decoding | 75 | // Epilogue Block模块, 实现Flash MLA中flash decoding |
| 76 | +using OType = Gemm::GemmType<ElementO, LayoutO>; | ||
| 76 | using lType = Gemm::GemmType<ElementUpdate, LayoutUpdate>; | 77 | using lType = Gemm::GemmType<ElementUpdate, LayoutUpdate>; |
| 77 | constexpr uint32_t ComputeEleNum = 6144; | 78 | constexpr uint32_t ComputeEleNum = 6144; |
| 78 | using EpilogueMLAFDRescaleO = | 79 | using EpilogueMLAFDRescaleO = |
| @@ -21,7 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | - | ||
| 25 | using namespace std; | 24 | using namespace std; |
| 26 | namespace MLATiling { | 25 | namespace MLATiling { |
| 27 | using AddrOffsets = struct AddressOffsetInfo { | 26 | using AddrOffsets = struct AddressOffsetInfo { |
| @@ -32,14 +31,17 @@ using AddrOffsets = struct AddressOffsetInfo { | |||
| 32 | uint64_t addrLSeqOffset = 0; | 31 | uint64_t addrLSeqOffset = 0; |
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | -inline uint32_t GetHigh32Bit(uint64_t v) { | 34 | +struct AddrOffsetPerBatch { |
| 36 | - return static_cast<uint32_t>(v >> NUM32); | 35 | + uint64_t qSeqOffset = 0; |
| 37 | -} | 36 | + uint64_t qSeqRopeOffset = 0; |
| 38 | -inline uint32_t GetLow32Bit(uint64_t v) { | 37 | + uint64_t maskBatchOffset = 0; |
| 39 | - return static_cast<uint32_t>(v); | 38 | +}; |
| 40 | -} | ||
| 41 | 39 | ||
| 42 | -void GetAddrOffsetMLA(uint32_t *tilingHost, const AddrOffsets addrOffsets, const int32_t tilingOffset) { | 40 | +inline uint32_t GetHigh32Bit(uint64_t v) { return static_cast<uint32_t>(v >> NUM32); } |
| 41 | +inline uint32_t GetLow32Bit(uint64_t v) { return static_cast<uint32_t>(v); } | ||
| 42 | + | ||
| 43 | +void GetAddrOffsetMLA(uint32_t *tilingHost, const AddrOffsets &addrOffsets, const int32_t tilingOffset) | ||
| 44 | +{ | ||
| 43 | // Calculate address offset | 45 | // Calculate address offset |
| 44 | tilingHost[tilingOffset + NUM4] = GetHigh32Bit(addrOffsets.addrQSeqOffset); | 46 | tilingHost[tilingOffset + NUM4] = GetHigh32Bit(addrOffsets.addrQSeqOffset); |
| 45 | tilingHost[tilingOffset + NUM5] = GetLow32Bit(addrOffsets.addrQSeqOffset); | 47 | tilingHost[tilingOffset + NUM5] = GetLow32Bit(addrOffsets.addrQSeqOffset); |
| @@ -49,46 +51,58 @@ void GetAddrOffsetMLA(uint32_t *tilingHost, const AddrOffsets addrOffsets, const | |||
| 49 | tilingHost[tilingOffset + NUM9] = GetLow32Bit(addrOffsets.addrMaskBatchOffset); | 51 | tilingHost[tilingOffset + NUM9] = GetLow32Bit(addrOffsets.addrMaskBatchOffset); |
| 50 | } | 52 | } |
| 51 | 53 | ||
| 52 | -void GetMLATilingCommon(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost) { | 54 | +void GetMLATilingCommon(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost, const std::vector<uint32_t>& sortedIndices, |
| 53 | - // Calculate the batch-related tiling parameters | 55 | + const std::vector<AddrOffsetPerBatch>& addrOffsetsPerBatch) |
| 56 | +{ | ||
| 54 | int32_t maxKVSeqlen = 0; | 57 | int32_t maxKVSeqlen = 0; |
| 55 | int32_t maxQSeqlen = 0; | 58 | int32_t maxQSeqlen = 0; |
| 56 | - AddrOffsets addrOffsets{}; | ||
| 57 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | 59 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { |
| 58 | - int32_t qSeqLen = *(mlaInfo.qSeqLen + seqIdx); | 60 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; |
| 59 | - qSeqLen = (*(mlaInfo.kvSeqLen + seqIdx) == 0) ? 0 : qSeqLen; | 61 | + int32_t qSeqLen = *(mlaInfo.qSeqLen + sortSeqIdx); |
| 62 | + int32_t kvSeqlen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 63 | + | ||
| 64 | + qSeqLen = (kvSeqlen == 0) ? 0 : qSeqLen; | ||
| 60 | maxQSeqlen = std::max(maxQSeqlen, qSeqLen); | 65 | maxQSeqlen = std::max(maxQSeqlen, qSeqLen); |
| 61 | - int32_t kvSeqlen = *(mlaInfo.kvSeqLen + seqIdx); | ||
| 62 | maxKVSeqlen = std::max(maxKVSeqlen, kvSeqlen); | 66 | maxKVSeqlen = std::max(maxKVSeqlen, kvSeqlen); |
| 67 | + | ||
| 63 | int32_t tilingOffset = TILING_HEAD_SIZE + TILING_PARA_SIZE * seqIdx; | 68 | int32_t tilingOffset = TILING_HEAD_SIZE + TILING_PARA_SIZE * seqIdx; |
| 64 | tilingHost[tilingOffset] = static_cast<uint32_t>(qSeqLen); | 69 | tilingHost[tilingOffset] = static_cast<uint32_t>(qSeqLen); |
| 65 | tilingHost[tilingOffset + NUM1] = static_cast<uint32_t>(kvSeqlen); | 70 | tilingHost[tilingOffset + NUM1] = static_cast<uint32_t>(kvSeqlen); |
| 71 | + tilingHost[tilingOffset + NUM2] = static_cast<uint32_t>(sortSeqIdx); | ||
| 66 | tilingHost[tilingOffset + NUM3] = static_cast<uint32_t>(mlaInfo.blockSize); | 72 | tilingHost[tilingOffset + NUM3] = static_cast<uint32_t>(mlaInfo.blockSize); |
| 73 | + | ||
| 74 | + const auto &batchOffsets = addrOffsetsPerBatch[sortSeqIdx]; | ||
| 75 | + AddrOffsets addrOffsets{}; | ||
| 76 | + addrOffsets.addrQSeqOffset = batchOffsets.qSeqOffset; | ||
| 77 | + addrOffsets.addrQSeqRopeOffset = batchOffsets.qSeqRopeOffset; | ||
| 78 | + addrOffsets.addrMaskBatchOffset = batchOffsets.maskBatchOffset; | ||
| 67 | GetAddrOffsetMLA(tilingHost, addrOffsets, tilingOffset); | 79 | GetAddrOffsetMLA(tilingHost, addrOffsets, tilingOffset); |
| 68 | - uint64_t addressOffset = static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSize * qSeqLen); | ||
| 69 | - uint64_t addressMaskOffset = static_cast<uint64_t>(mlaInfo.maxKvSeqlen * qSeqLen); | ||
| 70 | - uint64_t addressOffsetRope = static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSizeRope * qSeqLen); | ||
| 71 | - addrOffsets.addrQSeqOffset += addressOffset; | ||
| 72 | - addrOffsets.addrQSeqRopeOffset += addressOffsetRope; | ||
| 73 | - addrOffsets.addrMaskBatchOffset += addressMaskOffset; | ||
| 74 | } | 80 | } |
| 81 | + | ||
| 75 | tilingHost[TILING_MAX_KVSEQLEN] = maxKVSeqlen; | 82 | tilingHost[TILING_MAX_KVSEQLEN] = maxKVSeqlen; |
| 76 | tilingHost[TILING_MAX_QSEQLEN] = maxQSeqlen; | 83 | tilingHost[TILING_MAX_QSEQLEN] = maxQSeqlen; |
| 77 | } | 84 | } |
| 78 | 85 | ||
| 79 | -void GetMLATilingSpec(const MLAInfo &mmInfo, uint32_t &blockDim, uint32_t *tilingHost) { | 86 | +void GetMLATilingSpec(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost, const std::vector<uint32_t>& sortedIndices, |
| 80 | - // Tp1 senario specialization | 87 | + const std::vector<std::vector<uint32_t>>& realPreTaskNums) |
| 88 | +{ | ||
| 89 | + // TP1 scenario specialization. | ||
| 81 | // Treat every Q token with 128 heads as one process, regardless of the mtp depth | 90 | // Treat every Q token with 128 heads as one process, regardless of the mtp depth |
| 82 | int32_t prevTaskNum = 0; | 91 | int32_t prevTaskNum = 0; |
| 83 | int32_t maxKVSeqlen = 0; | 92 | int32_t maxKVSeqlen = 0; |
| 84 | - for (int32_t seqIdx = 0; seqIdx < mmInfo.batch; seqIdx++) { | 93 | + |
| 85 | - int32_t qSeqLen = mmInfo.qSeqLen == nullptr ? 1 : *(mmInfo.qSeqLen + seqIdx); | 94 | + for (int32_t i = 0; i < mlaInfo.batch; i++) { |
| 86 | - int32_t kvSeqlen = *(mmInfo.kvSeqLen + seqIdx); | 95 | + uint32_t sortSeqIdx = sortedIndices[i]; |
| 87 | - maxKVSeqlen = std::max(maxKVSeqlen, kvSeqlen); | 96 | + int32_t qSeqLen = *(mlaInfo.qSeqLen + sortSeqIdx); |
| 97 | + int32_t kvSeqlen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 98 | + const std::vector<uint32_t>& currentRealPreTaskNum = realPreTaskNums[sortSeqIdx]; | ||
| 99 | + | ||
| 100 | + maxKVSeqlen = (maxKVSeqlen > kvSeqlen) ? maxKVSeqlen : kvSeqlen; | ||
| 101 | + | ||
| 88 | for (int32_t qSeq = 0; qSeq < qSeqLen; qSeq++) { | 102 | for (int32_t qSeq = 0; qSeq < qSeqLen; qSeq++) { |
| 89 | int32_t tilingOffset = TILING_HEAD_SIZE + PARA_TILING_ELENUM_SPEC * prevTaskNum; | 103 | int32_t tilingOffset = TILING_HEAD_SIZE + PARA_TILING_ELENUM_SPEC * prevTaskNum; |
| 90 | - tilingHost[tilingOffset] = seqIdx; | 104 | + tilingHost[tilingOffset] = sortSeqIdx; |
| 91 | - tilingHost[tilingOffset + NUM1] = prevTaskNum; | 105 | + tilingHost[tilingOffset + NUM1] = currentRealPreTaskNum[qSeq]; |
| 92 | tilingHost[tilingOffset + NUM2] = kvSeqlen; | 106 | tilingHost[tilingOffset + NUM2] = kvSeqlen; |
| 93 | prevTaskNum++; | 107 | prevTaskNum++; |
| 94 | } | 108 | } |
| @@ -96,9 +110,10 @@ void GetMLATilingSpec(const MLAInfo &mmInfo, uint32_t &blockDim, uint32_t *tilin | |||
| 96 | tilingHost[TILING_MAX_KVSEQLEN] = maxKVSeqlen; | 110 | tilingHost[TILING_MAX_KVSEQLEN] = maxKVSeqlen; |
| 97 | } | 111 | } |
| 98 | 112 | ||
| 99 | -int32_t GetQNBlockTile(const MLAInfo &mlaInfo, int32_t qSeqLen, uint32_t specStrategyFlag) { | 113 | +int32_t GetQNBlockTile(const MLAInfo &mlaInfo, int32_t qSeqLen, uint32_t specStrategyFlag) |
| 114 | +{ | ||
| 100 | int32_t tokenNum = qSeqLen; | 115 | int32_t tokenNum = qSeqLen; |
| 101 | - if (specStrategyFlag > 0) { | 116 | + if (specStrategyFlag) { |
| 102 | tokenNum = NUM1; | 117 | tokenNum = NUM1; |
| 103 | } | 118 | } |
| 104 | int32_t tileListIdx = static_cast<int32_t>(std::ceil(std::log2(tokenNum))); | 119 | int32_t tileListIdx = static_cast<int32_t>(std::ceil(std::log2(tokenNum))); |
| @@ -109,17 +124,13 @@ int32_t GetQNBlockTile(const MLAInfo &mlaInfo, int32_t qSeqLen, uint32_t specStr | |||
| 109 | return qNBlockTile; | 124 | return qNBlockTile; |
| 110 | } | 125 | } |
| 111 | 126 | ||
| 112 | -void GetTilingHead( | 127 | +void GetTilingHead(const MLAInfo &mlaInfo, uint32_t *tilingHost, const uint32_t *torPtr, int32_t maxQseqlen, |
| 113 | - const MLAInfo &mlaInfo, | 128 | + uint32_t specStrategyFlag) |
| 114 | - uint32_t *tilingHost, | 129 | +{ |
| 115 | - const uint32_t *torPtr, | ||
| 116 | - int32_t maxQseqlen, | ||
| 117 | - uint32_t specStrategyFlag | ||
| 118 | -) { | ||
| 119 | // Calculating tiling parameters | 130 | // Calculating tiling parameters |
| 120 | tilingHost[TILING_BATCH] = static_cast<uint32_t>(mlaInfo.batch); | 131 | tilingHost[TILING_BATCH] = static_cast<uint32_t>(mlaInfo.batch); |
| 121 | tilingHost[TILING_HEADSIZE] = static_cast<uint32_t>(TILING_HEAD_SIZE); | 132 | tilingHost[TILING_HEADSIZE] = static_cast<uint32_t>(TILING_HEAD_SIZE); |
| 122 | - if (specStrategyFlag > 0) { | 133 | + if (specStrategyFlag) { |
| 123 | tilingHost[TILING_PARASIZE] = static_cast<uint32_t>(PARA_TILING_ELENUM_SPEC); | 134 | tilingHost[TILING_PARASIZE] = static_cast<uint32_t>(PARA_TILING_ELENUM_SPEC); |
| 124 | } else { | 135 | } else { |
| 125 | tilingHost[TILING_PARASIZE] = static_cast<uint32_t>(TILING_PARA_SIZE); | 136 | tilingHost[TILING_PARASIZE] = static_cast<uint32_t>(TILING_PARA_SIZE); |
| @@ -141,115 +152,303 @@ void GetTilingHead( | |||
| 141 | tilingHost[TILING_TOTAL_QTOKENS] = static_cast<uint32_t>(mlaInfo.numTokens); | 152 | tilingHost[TILING_TOTAL_QTOKENS] = static_cast<uint32_t>(mlaInfo.numTokens); |
| 142 | } | 153 | } |
| 143 | 154 | ||
| 144 | -uint32_t GetKVSplitParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost) { | 155 | +uint32_t GetKVSplitParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost, const std::vector<uint32_t>& sortedIndices) |
| 145 | - // Calculate the tiling parameters related to flash decoding | 156 | +{ |
| 146 | - bool isKVSplit = (tilingHost[TILING_MAX_KVSEQLEN] >= blockDim * KV_SEQLEN_SLICE * NUM2) | 157 | + // Only split KV when the longest sequence is long enough to be worth distributing across |
| 147 | - && (tilingHost[TILING_BATCH] <= blockDim * SPLITKV_RATION && tilingHost[TILING_MAX_QSEQLEN] == 1); | 158 | + // cores (>= blockDim * KV_SEQLEN_SLICE * 2). For short sequences, splitting adds extra |
| 148 | - if (tilingHost[TILING_NUMHEADS] == NUM128 || !isKVSplit) { | 159 | + // flash-decoding accumulation that degrades the max/mean relative error (MARE/MERE) on |
| 160 | + // near-zero output elements without any performance benefit. This matches the reference | ||
| 161 | + // implementation's split decision (blockDim = AIC core count = 20 here). | ||
| 162 | + bool isKVSplit = (tilingHost[TILING_MAX_KVSEQLEN] >= blockDim * KV_SEQLEN_SLICE * NUM2) && | ||
| 163 | + (tilingHost[TILING_BATCH] <= blockDim * SPLITKV_RATION && tilingHost[TILING_MAX_QSEQLEN] == 1); | ||
| 164 | + | ||
| 165 | + if (!isKVSplit) { | ||
| 149 | tilingHost[TILING_KVCORENUM] = 1; | 166 | tilingHost[TILING_KVCORENUM] = 1; |
| 150 | - tilingHost[TILING_KVSPLIT] = tilingHost[TILING_MAX_KVSEQLEN]; | 167 | + tilingHost[TILING_PROCESSNUM] = 0; |
| 151 | - std::cout << "TILING_KVSPLIT = " << tilingHost[TILING_KVSPLIT] << std::endl; | 168 | + for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { |
| 152 | - std::cout << "TILING_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | 169 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; |
| 170 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 171 | + int32_t tilingOffset = seqIdx * TILING_PARA_SIZE + TILING_HEAD_SIZE; | ||
| 172 | + tilingHost[tilingOffset + NUM15] = kvSeqLen; | ||
| 173 | + tilingHost[tilingOffset + NUM16] = 1; | ||
| 174 | + } | ||
| 153 | return tilingHost[TILING_BATCH]; | 175 | return tilingHost[TILING_BATCH]; |
| 154 | } | 176 | } |
| 155 | 177 | ||
| 156 | - uint32_t decoderBatch = tilingHost[TILING_BATCH]; | 178 | + // T+1-style balanced KV split: distribute available cores among the (q==1) decode tasks |
| 157 | - uint32_t process = std::lcm(decoderBatch, blockDim); | 179 | + // by repeatedly splitting the currently heaviest task, with a minimum tokens-per-split floor. |
| 158 | - uint32_t kvSplitCoreNum = process / decoderBatch; | 180 | + // Each batch is one task here (split path requires maxQseqlen == 1). |
| 181 | + const uint32_t MIN_TOKENS_PER_SPLIT = static_cast<uint32_t>(mlaInfo.blockSize * NUM4); | ||
| 182 | + // Cap the per-task split count to a proven-safe value (the original common path always | ||
| 183 | + // used 8). This keeps each task's kvSplitCoreNum within the range the flash-decoding | ||
| 184 | + // reduction handles correctly, and together with totalAllocated <= blockDim guarantees | ||
| 185 | + // sum(kvSplitCoreNum) <= blockDim (i.e. at most one task per core). | ||
| 186 | + const uint32_t MAX_SPLIT_PER_TASK = 8; | ||
| 187 | + uint32_t taskCount = static_cast<uint32_t>(mlaInfo.batch); | ||
| 159 | 188 | ||
| 160 | - uint32_t kvSeqlenMaxAlign = RoundUp(tilingHost[TILING_MAX_KVSEQLEN], static_cast<uint32_t>(mlaInfo.blockSize)); | 189 | + std::vector<uint32_t> alignedKvLens(taskCount); |
| 161 | - uint32_t kvSeqBlockNum = kvSeqlenMaxAlign / mlaInfo.blockSize; | 190 | + for (uint32_t seqIdx = 0; seqIdx < taskCount; seqIdx++) { |
| 162 | - uint32_t kvBlockPerCore = CeilDiv(kvSeqBlockNum, kvSplitCoreNum); | 191 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; |
| 163 | - uint32_t kvSplitPerCore = kvBlockPerCore * mlaInfo.blockSize; | 192 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); |
| 164 | - kvSplitCoreNum = CeilDiv(tilingHost[TILING_MAX_KVSEQLEN], kvSplitPerCore); | 193 | + alignedKvLens[seqIdx] = RoundUp(kvSeqLen, static_cast<uint32_t>(mlaInfo.blockSize)); |
| 194 | + } | ||
| 165 | 195 | ||
| 166 | - tilingHost[TILING_KVSPLIT] = kvSplitPerCore; | 196 | + std::vector<uint32_t> batchSplitNum(taskCount, 1); |
| 167 | - tilingHost[TILING_KVCORENUM] = kvSplitCoreNum; | 197 | + uint32_t totalAllocated = taskCount; |
| 168 | - std::cout << "TILING_KVSPLIT = " << tilingHost[TILING_KVSPLIT] << std::endl; | 198 | + while (totalAllocated < blockDim) { |
| 169 | - std::cout << "TILING_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | 199 | + int32_t maxLoadIdx = -1; |
| 200 | + uint32_t maxLoad = 0; | ||
| 201 | + for (uint32_t i = 0; i < taskCount; i++) { | ||
| 202 | + uint32_t currentLoad = alignedKvLens[i] / batchSplitNum[i]; | ||
| 203 | + uint32_t nextLoad = alignedKvLens[i] / (batchSplitNum[i] + 1); | ||
| 204 | + if (batchSplitNum[i] < MAX_SPLIT_PER_TASK && | ||
| 205 | + nextLoad >= MIN_TOKENS_PER_SPLIT && currentLoad > maxLoad) { | ||
| 206 | + maxLoad = currentLoad; | ||
| 207 | + maxLoadIdx = static_cast<int32_t>(i); | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + if (maxLoadIdx == -1) { | ||
| 211 | + break; | ||
| 212 | + } | ||
| 213 | + batchSplitNum[maxLoadIdx]++; | ||
| 214 | + totalAllocated++; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + uint32_t MAX_KV_SPLIT_NUM = 1; | ||
| 218 | + for (uint32_t num : batchSplitNum) { | ||
| 219 | + if (num > MAX_KV_SPLIT_NUM) { | ||
| 220 | + MAX_KV_SPLIT_NUM = num; | ||
| 221 | + } | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + // Build the cumulative-task prefix sum so the kernel can map process -> (task, kvIdx) tightly. | ||
| 225 | + uint32_t cuTaskVal = 0; | ||
| 226 | + int32_t cuTaskIdx = 0; | ||
| 227 | + tilingHost[CUTASK_START_OFFSET + cuTaskIdx++] = cuTaskVal; | ||
| 228 | + for (uint32_t seqIdx = 0; seqIdx < taskCount; seqIdx++) { | ||
| 229 | + int32_t tilingOffset = seqIdx * TILING_PARA_SIZE + TILING_HEAD_SIZE; | ||
| 230 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; | ||
| 231 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 232 | + | ||
| 233 | + uint32_t kvSplitPerCore; | ||
| 234 | + uint32_t kvSplitCoreNum; | ||
| 235 | + if (kvSeqLen == 0) { | ||
| 236 | + kvSplitPerCore = static_cast<uint32_t>(mlaInfo.blockSize); | ||
| 237 | + kvSplitCoreNum = 1; | ||
| 238 | + } else { | ||
| 239 | + uint32_t allocSplit = batchSplitNum[seqIdx]; | ||
| 240 | + uint32_t kvSeqAlign = RoundUp(kvSeqLen, static_cast<uint32_t>(mlaInfo.blockSize)); | ||
| 241 | + uint32_t kvSeqBlockNum = kvSeqAlign / mlaInfo.blockSize; | ||
| 242 | + uint32_t kvBlockPerCore = CeilDiv(kvSeqBlockNum, allocSplit); | ||
| 243 | + kvSplitPerCore = kvBlockPerCore * mlaInfo.blockSize; | ||
| 244 | + kvSplitCoreNum = CeilDiv(kvSeqLen, kvSplitPerCore); | ||
| 245 | + } | ||
| 246 | + tilingHost[tilingOffset + NUM15] = kvSplitPerCore; | ||
| 247 | + tilingHost[tilingOffset + NUM16] = kvSplitCoreNum; | ||
| 248 | + cuTaskVal += kvSplitCoreNum; | ||
| 249 | + tilingHost[CUTASK_START_OFFSET + cuTaskIdx++] = cuTaskVal; | ||
| 250 | + } | ||
| 251 | + tilingHost[TILING_PROCESSNUM] = cuTaskVal; | ||
| 252 | + tilingHost[TILING_KVCORENUM] = MAX_KV_SPLIT_NUM; | ||
| 253 | + std::cout << "TILING_MAX_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | ||
| 254 | + std::cout << "TILING_PROCESSNUM = " << tilingHost[TILING_PROCESSNUM] << std::endl; | ||
| 170 | 255 | ||
| 171 | // Set lOffsetInfo and OfdOffsetInfo | 256 | // Set lOffsetInfo and OfdOffsetInfo |
| 172 | AddrOffsets addrOffsets; | 257 | AddrOffsets addrOffsets; |
| 173 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | 258 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { |
| 174 | - int32_t qSeqlen = 1; | 259 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; |
| 175 | - qSeqlen = (*(mlaInfo.kvSeqLen + seqIdx) == 0) ? 0 : qSeqlen; | 260 | + uint32_t qSeqlen = *(mlaInfo.qSeqLen + sortSeqIdx); |
| 261 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 262 | + qSeqlen = (kvSeqLen == 0) ? 0 : qSeqlen; | ||
| 176 | int32_t tilingOffset = seqIdx * TILING_PARA_SIZE + TILING_HEAD_SIZE; | 263 | int32_t tilingOffset = seqIdx * TILING_PARA_SIZE + TILING_HEAD_SIZE; |
| 177 | tilingHost[tilingOffset + NUM11] = GetHigh32Bit(addrOffsets.addrLSeqOffset); | 264 | tilingHost[tilingOffset + NUM11] = GetHigh32Bit(addrOffsets.addrLSeqOffset); |
| 178 | tilingHost[tilingOffset + NUM12] = GetLow32Bit(addrOffsets.addrLSeqOffset); | 265 | tilingHost[tilingOffset + NUM12] = GetLow32Bit(addrOffsets.addrLSeqOffset); |
| 179 | tilingHost[tilingOffset + NUM13] = GetHigh32Bit(addrOffsets.addrOFdSeqOffset); | 266 | tilingHost[tilingOffset + NUM13] = GetHigh32Bit(addrOffsets.addrOFdSeqOffset); |
| 180 | tilingHost[tilingOffset + NUM14] = GetLow32Bit(addrOffsets.addrOFdSeqOffset); | 267 | tilingHost[tilingOffset + NUM14] = GetLow32Bit(addrOffsets.addrOFdSeqOffset); |
| 181 | - addrOffsets.addrLSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * qSeqlen * kvSplitCoreNum); | 268 | + addrOffsets.addrLSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * qSeqlen * MAX_KV_SPLIT_NUM); |
| 182 | addrOffsets.addrOFdSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * qSeqlen * mlaInfo.embeddingSize); | 269 | addrOffsets.addrOFdSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * qSeqlen * mlaInfo.embeddingSize); |
| 183 | } | 270 | } |
| 184 | 271 | ||
| 185 | - return decoderBatch * kvSplitCoreNum; | 272 | + return cuTaskVal; |
| 186 | } | 273 | } |
| 187 | 274 | ||
| 188 | -uint32_t GetKVSplitParamSpec(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost) { | 275 | +uint32_t GetKVSplitParamSpec(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost, const std::vector<uint32_t>& sortedIndices) |
| 189 | - // Tp1 senario specialization | 276 | +{ |
| 277 | + // TP1 scenario specialization. | ||
| 190 | // Calculate the tiling parameters related to flash decoding | 278 | // Calculate the tiling parameters related to flash decoding |
| 191 | uint32_t totalTaskNumSpec = tilingHost[TILING_TOTAL_QTOKENS]; | 279 | uint32_t totalTaskNumSpec = tilingHost[TILING_TOTAL_QTOKENS]; |
| 192 | - | ||
| 193 | uint32_t formerTaskNum = totalTaskNumSpec; | 280 | uint32_t formerTaskNum = totalTaskNumSpec; |
| 194 | uint32_t tailTaskNum = 0; | 281 | uint32_t tailTaskNum = 0; |
| 195 | - | 282 | + if (mlaInfo.numTokens % NUM20 <= NUM10 && mlaInfo.batch <= 40) { |
| 196 | - uint32_t processLoop = totalTaskNumSpec / blockDim; | 283 | + uint32_t processLoop = totalTaskNumSpec / blockDim; |
| 197 | - formerTaskNum = processLoop * blockDim; | 284 | + formerTaskNum = processLoop * blockDim; |
| 198 | - tailTaskNum = totalTaskNumSpec - formerTaskNum; | 285 | + tailTaskNum = totalTaskNumSpec - formerTaskNum; |
| 199 | - | ||
| 200 | - if (tailTaskNum >= blockDim * SPLITKV_RATION) { | ||
| 201 | - formerTaskNum = totalTaskNumSpec; | ||
| 202 | - tailTaskNum = 0; | ||
| 203 | } | 286 | } |
| 204 | 287 | ||
| 205 | tilingHost[TILING_FORMERTASKNUM] = formerTaskNum; | 288 | tilingHost[TILING_FORMERTASKNUM] = formerTaskNum; |
| 206 | tilingHost[TILING_TAILTASKNUM] = tailTaskNum; | 289 | tilingHost[TILING_TAILTASKNUM] = tailTaskNum; |
| 207 | std::cout << "TILING_FORMERTASKNUM = " << tilingHost[TILING_FORMERTASKNUM] << std::endl; | 290 | std::cout << "TILING_FORMERTASKNUM = " << tilingHost[TILING_FORMERTASKNUM] << std::endl; |
| 208 | std::cout << "TILING_TAILTASKNUM = " << tilingHost[TILING_TAILTASKNUM] << std::endl; | 291 | std::cout << "TILING_TAILTASKNUM = " << tilingHost[TILING_TAILTASKNUM] << std::endl; |
| 209 | - | ||
| 210 | if (tailTaskNum == 0) { | 292 | if (tailTaskNum == 0) { |
| 211 | tilingHost[TILING_KVCORENUM] = 1; | 293 | tilingHost[TILING_KVCORENUM] = 1; |
| 212 | tilingHost[TILING_KVSPLIT] = tilingHost[TILING_MAX_KVSEQLEN]; | 294 | tilingHost[TILING_KVSPLIT] = tilingHost[TILING_MAX_KVSEQLEN]; |
| 295 | + tilingHost[TILING_PROCESSNUM] = 0; | ||
| 213 | std::cout << "TILING_KVSPLIT = " << tilingHost[TILING_KVSPLIT] << std::endl; | 296 | std::cout << "TILING_KVSPLIT = " << tilingHost[TILING_KVSPLIT] << std::endl; |
| 214 | std::cout << "TILING_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | 297 | std::cout << "TILING_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; |
| 215 | return blockDim; | 298 | return blockDim; |
| 216 | } | 299 | } |
| 217 | 300 | ||
| 218 | - uint32_t process = std::lcm(tailTaskNum, blockDim); | 301 | + const uint32_t MIN_TOKENS_PER_SPLIT = static_cast<uint32_t>(mlaInfo.blockSize * NUM4); |
| 219 | - uint32_t kvSplitCoreNum = process / tailTaskNum; | ||
| 220 | 302 | ||
| 221 | - uint32_t kvSeqlenMaxAlign = RoundUp(tilingHost[TILING_MAX_KVSEQLEN], static_cast<uint32_t>(mlaInfo.blockSize)); | 303 | + std::vector<uint32_t> alignedKvLens; |
| 222 | - uint32_t kvSeqBlockNum = kvSeqlenMaxAlign / mlaInfo.blockSize; | 304 | + int32_t prevTaskNumTemp = 0; |
| 223 | - uint32_t kvBlockPerCore = CeilDiv(kvSeqBlockNum, kvSplitCoreNum); | ||
| 224 | - uint32_t kvSplitPerCore = kvBlockPerCore * mlaInfo.blockSize; | ||
| 225 | - kvSplitCoreNum = CeilDiv(tilingHost[TILING_MAX_KVSEQLEN], kvSplitPerCore); | ||
| 226 | - | ||
| 227 | - tilingHost[TILING_KVSPLIT] = kvSplitPerCore; | ||
| 228 | - tilingHost[TILING_KVCORENUM] = kvSplitCoreNum; | ||
| 229 | - std::cout << "TILING_KVSPLIT = " << tilingHost[TILING_KVSPLIT] << std::endl; | ||
| 230 | - std::cout << "TILING_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | ||
| 231 | - | ||
| 232 | - // Set lOffsetInfo and OfdOffsetInfo | ||
| 233 | - AddrOffsets addrOffsets; | ||
| 234 | - int32_t prevTaskNum = 0; | ||
| 235 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | 305 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { |
| 236 | - int32_t qSeqLen = mlaInfo.qSeqLen == nullptr ? 1 : *(mlaInfo.qSeqLen + seqIdx); | 306 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; |
| 307 | + uint32_t qSeqLen = *(mlaInfo.qSeqLen + sortSeqIdx); | ||
| 308 | + if (prevTaskNumTemp + qSeqLen < formerTaskNum) { | ||
| 309 | + prevTaskNumTemp += qSeqLen; | ||
| 310 | + continue; | ||
| 311 | + } | ||
| 312 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 313 | + alignedKvLens.push_back(RoundUp(kvSeqLen, static_cast<uint32_t>(mlaInfo.blockSize))); | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + uint32_t tailSeqCount = alignedKvLens.size(); | ||
| 317 | + std::vector<uint32_t> batchSplitNum(tailSeqCount, 1); | ||
| 318 | + uint32_t totalAllocated = tailTaskNum; | ||
| 319 | + while (totalAllocated < blockDim) { | ||
| 320 | + int32_t maxLoadIdx = -1; | ||
| 321 | + uint32_t maxLoad = 0; | ||
| 322 | + | ||
| 323 | + for (int32_t i = 0; i < tailSeqCount; i++) { | ||
| 324 | + uint32_t currentLoad = alignedKvLens[i] / batchSplitNum[i]; | ||
| 325 | + uint32_t nextLoad = alignedKvLens[i] / (batchSplitNum[i] + 1); | ||
| 326 | + if (nextLoad >= MIN_TOKENS_PER_SPLIT && currentLoad > maxLoad) { | ||
| 327 | + maxLoad = currentLoad; | ||
| 328 | + maxLoadIdx = i; | ||
| 329 | + } | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | + if (maxLoadIdx != -1) { | ||
| 333 | + batchSplitNum[maxLoadIdx]++; | ||
| 334 | + } else if (tailSeqCount > 0) { | ||
| 335 | + int32_t longestIdx = 0; | ||
| 336 | + for (int32_t i = 1; i < tailSeqCount; i++) { | ||
| 337 | + if (alignedKvLens[i] > alignedKvLens[longestIdx]) { | ||
| 338 | + longestIdx = i; | ||
| 339 | + } | ||
| 340 | + } | ||
| 341 | + batchSplitNum[longestIdx]++; | ||
| 342 | + } | ||
| 343 | + totalAllocated++; | ||
| 344 | + } | ||
| 345 | + uint32_t MAX_KV_SPLIT_NUM = 1; | ||
| 346 | + for (uint32_t num : batchSplitNum) { | ||
| 347 | + if (num > MAX_KV_SPLIT_NUM) { | ||
| 348 | + MAX_KV_SPLIT_NUM = num; | ||
| 349 | + } | ||
| 350 | + } | ||
| 351 | + uint32_t cuTaskVal = 0; | ||
| 352 | + int32_t cuTaskIdx = 0; | ||
| 353 | + tilingHost[CUTASK_START_OFFSET + cuTaskIdx++] = cuTaskVal; | ||
| 354 | + | ||
| 355 | + int32_t prevTaskNum = 0; | ||
| 356 | + int32_t tailSeqIdx = 0; | ||
| 357 | + for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | ||
| 358 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; | ||
| 359 | + uint32_t qSeqLen = *(mlaInfo.qSeqLen + sortSeqIdx); | ||
| 360 | + uint32_t kvSeqLen = *(mlaInfo.kvSeqLen + sortSeqIdx); | ||
| 361 | + | ||
| 362 | + if (prevTaskNum + qSeqLen < formerTaskNum) { | ||
| 363 | + prevTaskNum += qSeqLen; | ||
| 364 | + continue; | ||
| 365 | + } | ||
| 366 | + | ||
| 367 | + uint32_t allocSplit = 1; | ||
| 368 | + if (tailSeqIdx < tailSeqCount) { | ||
| 369 | + allocSplit = batchSplitNum[tailSeqIdx++]; | ||
| 370 | + } | ||
| 371 | + | ||
| 372 | + uint32_t kvSeqAlign = RoundUp(kvSeqLen, static_cast<uint32_t>(mlaInfo.blockSize)); | ||
| 373 | + uint32_t kvSeqBlockNum = kvSeqAlign / mlaInfo.blockSize; | ||
| 374 | + uint32_t kvBlockPerCore = CeilDiv(kvSeqBlockNum, allocSplit); | ||
| 375 | + uint32_t kvSplitPerCore = kvBlockPerCore * mlaInfo.blockSize; | ||
| 376 | + uint32_t kvSplitCoreNum = CeilDiv(kvSeqLen, kvSplitPerCore); | ||
| 377 | + | ||
| 378 | + for (int32_t qSeq = 0; qSeq < qSeqLen; qSeq++) { | ||
| 379 | + if (prevTaskNum >= formerTaskNum) { | ||
| 380 | + cuTaskVal += kvSplitCoreNum; | ||
| 381 | + tilingHost[CUTASK_START_OFFSET + cuTaskIdx++] = cuTaskVal; | ||
| 382 | + int32_t tilingOffset = TILING_HEAD_SIZE + PARA_TILING_ELENUM_SPEC * prevTaskNum; | ||
| 383 | + tilingHost[tilingOffset + NUM15] = kvSplitPerCore; | ||
| 384 | + tilingHost[tilingOffset + NUM16] = kvSplitCoreNum; | ||
| 385 | + } | ||
| 386 | + prevTaskNum++; | ||
| 387 | + } | ||
| 388 | + } | ||
| 389 | + tilingHost[TILING_PROCESSNUM] = cuTaskVal; | ||
| 390 | + tilingHost[CUTASK_START_OFFSET + cuTaskIdx++] = TILING_HEAD_SIZE; | ||
| 391 | + tilingHost[TILING_KVCORENUM] = MAX_KV_SPLIT_NUM; | ||
| 392 | + std::cout << "TILING_MAX_KVCORENUM = " << tilingHost[TILING_KVCORENUM] << std::endl; | ||
| 393 | + | ||
| 394 | + AddrOffsets addrOffsets{}; | ||
| 395 | + prevTaskNum = 0; | ||
| 396 | + | ||
| 397 | + for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | ||
| 398 | + uint32_t sortSeqIdx = sortedIndices[seqIdx]; | ||
| 399 | + uint32_t qSeqLen = *(mlaInfo.qSeqLen + sortSeqIdx); | ||
| 237 | for (int32_t qSeq = 0; qSeq < qSeqLen; qSeq++) { | 400 | for (int32_t qSeq = 0; qSeq < qSeqLen; qSeq++) { |
| 238 | int32_t tilingOffset = TILING_HEAD_SIZE + PARA_TILING_ELENUM_SPEC * prevTaskNum; | 401 | int32_t tilingOffset = TILING_HEAD_SIZE + PARA_TILING_ELENUM_SPEC * prevTaskNum; |
| 239 | tilingHost[tilingOffset + NUM11] = GetHigh32Bit(addrOffsets.addrLSeqOffset); | 402 | tilingHost[tilingOffset + NUM11] = GetHigh32Bit(addrOffsets.addrLSeqOffset); |
| 240 | tilingHost[tilingOffset + NUM12] = GetLow32Bit(addrOffsets.addrLSeqOffset); | 403 | tilingHost[tilingOffset + NUM12] = GetLow32Bit(addrOffsets.addrLSeqOffset); |
| 241 | tilingHost[tilingOffset + NUM13] = GetHigh32Bit(addrOffsets.addrOFdSeqOffset); | 404 | tilingHost[tilingOffset + NUM13] = GetHigh32Bit(addrOffsets.addrOFdSeqOffset); |
| 242 | tilingHost[tilingOffset + NUM14] = GetLow32Bit(addrOffsets.addrOFdSeqOffset); | 405 | tilingHost[tilingOffset + NUM14] = GetLow32Bit(addrOffsets.addrOFdSeqOffset); |
| 243 | - addrOffsets.addrLSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * kvSplitCoreNum); | 406 | + addrOffsets.addrLSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * MAX_KV_SPLIT_NUM); |
| 244 | addrOffsets.addrOFdSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSize); | 407 | addrOffsets.addrOFdSeqOffset += static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSize); |
| 245 | prevTaskNum++; | 408 | prevTaskNum++; |
| 246 | } | 409 | } |
| 247 | } | 410 | } |
| 248 | 411 | ||
| 249 | - return tailTaskNum * kvSplitCoreNum; | 412 | + return tailTaskNum * MAX_KV_SPLIT_NUM; |
| 250 | } | 413 | } |
| 251 | 414 | ||
| 252 | -int32_t GetMLATilingParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost) { | 415 | +void swapIndices(std::vector<uint32_t>& indices, int i, int j) { |
| 416 | + uint32_t temp = indices[i]; | ||
| 417 | + indices[i] = indices[j]; | ||
| 418 | + indices[j] = temp; | ||
| 419 | +} | ||
| 420 | + | ||
| 421 | +int partitionIndices(std::vector<uint32_t>& indices, const int32_t* kvSeqLen, const int32_t* qSeqLen, int low, int high) { | ||
| 422 | + uint32_t pivotIndex = indices[high]; | ||
| 423 | + int32_t pivotKv = kvSeqLen[pivotIndex]; | ||
| 424 | + int32_t pivotQ = qSeqLen[pivotIndex]; | ||
| 425 | + int i = (low - 1); | ||
| 426 | + | ||
| 427 | + for (int j = low; j <= high - 1; j++) { | ||
| 428 | + uint32_t currIndex = indices[j]; | ||
| 429 | + int32_t currKv = kvSeqLen[currIndex]; | ||
| 430 | + int32_t currQ = qSeqLen[currIndex]; | ||
| 431 | + | ||
| 432 | + bool needSwap = (currKv > pivotKv) || (currKv == pivotKv && currQ > pivotQ); | ||
| 433 | + if (needSwap) { | ||
| 434 | + i++; | ||
| 435 | + swapIndices(indices, i, j); | ||
| 436 | + } | ||
| 437 | + } | ||
| 438 | + swapIndices(indices, i + 1, high); | ||
| 439 | + return (i + 1); | ||
| 440 | +} | ||
| 441 | + | ||
| 442 | +void quickSortIndices(std::vector<uint32_t>& indices, const int32_t* kvSeqLen, const int32_t* qSeqLen, int low, int high) { | ||
| 443 | + if (low < high) { | ||
| 444 | + int pi = partitionIndices(indices, kvSeqLen, qSeqLen, low, high); | ||
| 445 | + quickSortIndices(indices, kvSeqLen, qSeqLen, low, pi - 1); | ||
| 446 | + quickSortIndices(indices, kvSeqLen, qSeqLen, pi + 1, high); | ||
| 447 | + } | ||
| 448 | +} | ||
| 449 | + | ||
| 450 | +int32_t GetMLATilingParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t *tilingHost) | ||
| 451 | +{ | ||
| 253 | if (tilingHost == nullptr || mlaInfo.qSeqLen == nullptr || mlaInfo.kvSeqLen == nullptr) { | 452 | if (tilingHost == nullptr || mlaInfo.qSeqLen == nullptr || mlaInfo.kvSeqLen == nullptr) { |
| 254 | cerr << "[ERROR] pointer tilingHost or seq is nullptr." << endl; | 453 | cerr << "[ERROR] pointer tilingHost or seq is nullptr." << endl; |
| 255 | return -1; | 454 | return -1; |
| @@ -258,6 +457,47 @@ int32_t GetMLATilingParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t * | |||
| 258 | cerr << "[ERROR] blockSize != 128 is not supported." << endl; | 457 | cerr << "[ERROR] blockSize != 128 is not supported." << endl; |
| 259 | return -1; | 458 | return -1; |
| 260 | } | 459 | } |
| 460 | + | ||
| 461 | + std::vector<AddrOffsetPerBatch> addrOffsetsPerBatch(mlaInfo.batch); | ||
| 462 | + uint64_t currentQSeqOffset = 0; | ||
| 463 | + uint64_t currentQSeqRopeOffset = 0; | ||
| 464 | + uint64_t currentMaskBatchOffset = 0; | ||
| 465 | + | ||
| 466 | + for (int32_t i = 0; i < mlaInfo.batch; ++i) { | ||
| 467 | + int32_t qSeqLen = *(mlaInfo.qSeqLen + i); | ||
| 468 | + | ||
| 469 | + uint64_t deltaQSeq = static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSize * qSeqLen); | ||
| 470 | + uint64_t deltaQSeqRope = static_cast<uint64_t>(mlaInfo.numHeads * mlaInfo.embeddingSizeRope * qSeqLen); | ||
| 471 | + uint64_t deltaMaskBatch = static_cast<uint64_t>(mlaInfo.maxKvSeqlen * qSeqLen); | ||
| 472 | + | ||
| 473 | + addrOffsetsPerBatch[i].qSeqOffset = currentQSeqOffset; | ||
| 474 | + addrOffsetsPerBatch[i].qSeqRopeOffset = currentQSeqRopeOffset; | ||
| 475 | + addrOffsetsPerBatch[i].maskBatchOffset = currentMaskBatchOffset; | ||
| 476 | + | ||
| 477 | + currentQSeqOffset += deltaQSeq; | ||
| 478 | + currentQSeqRopeOffset += deltaQSeqRope; | ||
| 479 | + currentMaskBatchOffset += deltaMaskBatch; | ||
| 480 | + } | ||
| 481 | + | ||
| 482 | + std::vector<uint32_t> sortedIndices(mlaInfo.batch); | ||
| 483 | + for (uint32_t i = 0; i < mlaInfo.batch; ++i) { | ||
| 484 | + sortedIndices[i] = i; | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + std::vector<std::vector<uint32_t>> realPreTaskNums(mlaInfo.batch, std::vector<uint32_t>(NUM512)); | ||
| 488 | + int32_t preTaskNum = 0; | ||
| 489 | + for (int32_t i = 0; i < mlaInfo.batch; ++i) { | ||
| 490 | + uint32_t qSeqlen = static_cast<uint32_t>(*(mlaInfo.qSeqLen + i)); | ||
| 491 | + for (int32_t token = 0; token < qSeqlen; token++) { | ||
| 492 | + realPreTaskNums[i][token] = preTaskNum; | ||
| 493 | + preTaskNum++; | ||
| 494 | + } | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + if (mlaInfo.numTokens > 0) { | ||
| 498 | + quickSortIndices(sortedIndices, mlaInfo.kvSeqLen, mlaInfo.qSeqLen, 0, mlaInfo.batch - 1); | ||
| 499 | + } | ||
| 500 | + | ||
| 261 | int32_t maxQseqlen = 0; | 501 | int32_t maxQseqlen = 0; |
| 262 | int32_t totalKvNumtokens = 0; | 502 | int32_t totalKvNumtokens = 0; |
| 263 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { | 503 | for (int32_t seqIdx = 0; seqIdx < mlaInfo.batch; seqIdx++) { |
| @@ -277,16 +517,17 @@ int32_t GetMLATilingParam(const MLAInfo &mlaInfo, uint32_t &blockDim, uint32_t * | |||
| 277 | float tor = static_cast<float>(1.0 / sqrt(1.0 * (mlaInfo.embeddingSize + mlaInfo.embeddingSizeRope))); | 517 | float tor = static_cast<float>(1.0 / sqrt(1.0 * (mlaInfo.embeddingSize + mlaInfo.embeddingSizeRope))); |
| 278 | uint32_t *torPtr = reinterpret_cast<uint32_t *>(&tor); | 518 | uint32_t *torPtr = reinterpret_cast<uint32_t *>(&tor); |
| 279 | uint32_t specStrategyFlag = (mlaInfo.numHeads == NUM128) ? 1 : 0; | 519 | uint32_t specStrategyFlag = (mlaInfo.numHeads == NUM128) ? 1 : 0; |
| 280 | - if (specStrategyFlag > 0) { | 520 | + |
| 281 | - GetMLATilingSpec(mlaInfo, blockDim, tilingHost); | 521 | + if (specStrategyFlag) { |
| 522 | + GetMLATilingSpec(mlaInfo, blockDim, tilingHost, sortedIndices, realPreTaskNums); | ||
| 282 | } else { | 523 | } else { |
| 283 | - GetMLATilingCommon(mlaInfo, blockDim, tilingHost); | 524 | + GetMLATilingCommon(mlaInfo, blockDim, tilingHost, sortedIndices, addrOffsetsPerBatch); |
| 284 | } | 525 | } |
| 285 | GetTilingHead(mlaInfo, tilingHost, torPtr, maxQseqlen, specStrategyFlag); | 526 | GetTilingHead(mlaInfo, tilingHost, torPtr, maxQseqlen, specStrategyFlag); |
| 286 | - if (specStrategyFlag > 0) { | 527 | + if (specStrategyFlag) { |
| 287 | - GetKVSplitParamSpec(mlaInfo, blockDim, tilingHost); | 528 | + GetKVSplitParamSpec(mlaInfo, blockDim, tilingHost, sortedIndices); |
| 288 | } else { | 529 | } else { |
| 289 | - GetKVSplitParam(mlaInfo, blockDim, tilingHost); | 530 | + GetKVSplitParam(mlaInfo, blockDim, tilingHost, sortedIndices); |
| 290 | } | 531 | } |
| 291 | return 0; | 532 | return 0; |
| 292 | } | 533 | } |
| @@ -37,7 +37,11 @@ const int32_t TILING_TOTAL_QTOKENS = 18; | |||
| 37 | const int32_t TILING_FORMERTASKNUM = 19; | 37 | const int32_t TILING_FORMERTASKNUM = 19; |
| 38 | const int32_t TILING_TAILTASKNUM = 20; | 38 | const int32_t TILING_TAILTASKNUM = 20; |
| 39 | 39 | ||
| 40 | -const int32_t TILING_HEAD_SIZE = 24; | 40 | +const int32_t TILING_PROCESSNUM = 21; |
| 41 | + | ||
| 42 | +const int32_t TILING_HEAD_SIZE = 400; | ||
| 43 | +const int32_t CUTASK_START_OFFSET = 25; | ||
| 44 | +const int32_t CUTASK_MAX_LENGTH = 130; | ||
| 41 | const int32_t TILING_PARA_SIZE = 17; | 45 | const int32_t TILING_PARA_SIZE = 17; |
| 42 | 46 | ||
| 43 | const int32_t PARA_TILING_ELENUM_SPEC = 17; | 47 | const int32_t PARA_TILING_ELENUM_SPEC = 17; |
| @@ -38,6 +38,8 @@ class BlockEpilogue { | |||
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | + | ||
| 42 | + | ||
| 41 | 43 | ||
| 42 | 44 | ||
| 43 | 45 | ||
| @@ -0,0 +1,267 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace Catlass::Epilogue::Block { | ||
| 22 | + | ||
| 23 | +template <class OutputType_, class UpdateType_, class InputType_> | ||
| 24 | +class BlockEpilogue<EpilogueAtlasA2AMLATP1RescaleO, OutputType_, UpdateType_, InputType_> { | ||
| 25 | +public: | ||
| 26 | + // Type aliases | ||
| 27 | + using DispatchPolicy = EpilogueAtlasA2AMLATP1RescaleO; | ||
| 28 | + using ArchTag = typename DispatchPolicy::ArchTag; | ||
| 29 | + | ||
| 30 | + using ElementOutput = typename OutputType_::Element; | ||
| 31 | + using ElementUpdate = typename UpdateType_::Element; | ||
| 32 | + using ElementInput = typename InputType_::Element; | ||
| 33 | + | ||
| 34 | + using LayoutOutput = typename OutputType_::Layout; | ||
| 35 | + using LayoutUpdate = typename UpdateType_::Layout; | ||
| 36 | + using LayoutInput = typename InputType_::Layout; | ||
| 37 | + | ||
| 38 | + static constexpr uint32_t HALF_ELENUM_PER_BLK = 16; | ||
| 39 | + static constexpr uint32_t HALF_ELENUM_PER_VECCALC = 128; | ||
| 40 | + static constexpr uint32_t FLOAT_ELENUM_PER_VECCALC = 64; | ||
| 41 | + static constexpr uint32_t HALF_ELENUM_PER_LINE = 256; | ||
| 42 | + static constexpr uint32_t FLOAT_ELENUM_PER_LINE = 128; | ||
| 43 | + static constexpr uint32_t MULTIPLIER = 2; | ||
| 44 | + static constexpr uint32_t FLOAT_BLOCK_SIZE = 8; | ||
| 45 | + static constexpr uint32_t FLOAT_VECTOR_SIZE = 64; | ||
| 46 | + static constexpr uint32_t UB_UINT8_LINE_SIZE = 512; | ||
| 47 | + static constexpr uint32_t UB_UINT8_BLOCK_SIZE_MLA = 16384; | ||
| 48 | + static constexpr uint32_t ROW_WISE_CYCLE_TILE = 8; | ||
| 49 | + static constexpr uint32_t HALF_DM_UB_SIZE = 64; | ||
| 50 | + static constexpr uint32_t HALF_LL_UB_SIZE = 256; | ||
| 51 | + static constexpr uint32_t VECTOR_SIZE = 128; | ||
| 52 | + static constexpr uint32_t NUM4 = 4; | ||
| 53 | + | ||
| 54 | + CATLASS_DEVICE | ||
| 55 | + BlockEpilogue(Arch::Resource<ArchTag> &resource, uint32_t kvSplitCoreNum_ = 1) | ||
| 56 | + { | ||
| 57 | + // Allocate UB space | ||
| 58 | + constexpr uint32_t LO_UB_TENSOR_OFFSET = 4 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 59 | + constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 2 * UB_UINT8_LINE_SIZE; | ||
| 60 | + constexpr uint32_t GL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 7 * UB_UINT8_LINE_SIZE; | ||
| 61 | + constexpr uint32_t GO_UB_TENSOR_OFFSET = 8 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 62 | + constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 63 | + constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; | ||
| 64 | + constexpr uint32_t GM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 5 * UB_UINT8_LINE_SIZE; | ||
| 65 | + | ||
| 66 | + kvSplitCoreNum = kvSplitCoreNum_; | ||
| 67 | + loUbTensor = resource.ubBuf.template GetBufferByByte<float>(LO_UB_TENSOR_OFFSET); | ||
| 68 | + dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); | ||
| 69 | + glUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); | ||
| 70 | + glUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 71 | + tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); | ||
| 72 | + goUbTensor16 = resource.ubBuf.template GetBufferByByte<ElementOutput>(GO_UB_TENSOR_OFFSET); | ||
| 73 | + goUbTensor32 = resource.ubBuf.template GetBufferByByte<float>(GO_UB_TENSOR_OFFSET); | ||
| 74 | + hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | ||
| 75 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | ||
| 76 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + CATLASS_DEVICE | ||
| 80 | + ~BlockEpilogue() {} | ||
| 81 | + | ||
| 82 | + CATLASS_DEVICE | ||
| 83 | + void SetMask(int32_t len) | ||
| 84 | + { | ||
| 85 | + uint64_t mask = 0; | ||
| 86 | + uint64_t one = 1; | ||
| 87 | + uint64_t temp = len % FLOAT_VECTOR_SIZE; | ||
| 88 | + for (int64_t i = 0; i < temp; i++) { | ||
| 89 | + mask |= one << i; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + if (len == VECTOR_SIZE) { | ||
| 93 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 94 | + } else if (len >= FLOAT_VECTOR_SIZE) { | ||
| 95 | + AscendC::SetVectorMask<int8_t>(mask, (uint64_t)-1); | ||
| 96 | + } else { | ||
| 97 | + AscendC::SetVectorMask<int8_t>(0x0, mask); | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + CATLASS_DEVICE | ||
| 102 | + void SetkvSplitCoreNum(uint32_t kvSplitCoreNum_) | ||
| 103 | + { | ||
| 104 | + kvSplitCoreNum = kvSplitCoreNum_; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + CATLASS_DEVICE | ||
| 108 | + void SubCoreCompute(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, | ||
| 109 | + AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, | ||
| 110 | + AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, | ||
| 111 | + const LayoutOutput &layoutOutput, const LayoutUpdate &layoutUpdate, uint32_t nIdx, | ||
| 112 | + uint32_t needRowLoop, uint32_t rowLoopIdx, uint32_t rescaleOPingPongFlag, | ||
| 113 | + uint32_t *glFlag, uint32_t taskPingPongFlag) | ||
| 114 | + { | ||
| 115 | + uint32_t curRowNum = layoutInput.shape(0); | ||
| 116 | + uint32_t embed = layoutInput.shape(1); | ||
| 117 | + uint32_t embedRound = layoutInput.stride(0); | ||
| 118 | + uint32_t curRowNumRound = RoundUp<HALF_ELENUM_PER_BLK>(curRowNum); | ||
| 119 | + uint64_t dmUbOffsetCurCycle = | ||
| 120 | + (uint64_t)(rescaleOPingPongFlag * HALF_DM_UB_SIZE + rowLoopIdx * ROW_WISE_CYCLE_TILE); | ||
| 121 | + | ||
| 122 | + uint32_t oUbOffset = oPingPangFlag * ROW_WISE_CYCLE_TILE * embedRound; | ||
| 123 | + | ||
| 124 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(oPingPangFlag + 4); | ||
| 125 | + // *** gl_block = expand_to_block(gl), 存放于 tv | ||
| 126 | + AscendC::DataCopy(goUbTensor32[oUbOffset], gInput, | ||
| 127 | + AscendC::DataCopyParams(1, curRowNum * embedRound / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 128 | + AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | ||
| 129 | + AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | ||
| 130 | + | ||
| 131 | + AscendC::Abs<float,false>( | ||
| 132 | + tvUbTensor, | ||
| 133 | + goUbTensor32[oUbOffset], | ||
| 134 | + (uint64_t)0, | ||
| 135 | + curRowNum * embedRound / FLOAT_VECTOR_SIZE, | ||
| 136 | + {1, 1, 8, 8} | ||
| 137 | + ); | ||
| 138 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 139 | + AscendC::LocalTensor<uint8_t> cmpMaskUb = tvUbTensor.template ReinterpretCast<uint8_t>(); | ||
| 140 | + AscendC::CompareScalar( | ||
| 141 | + cmpMaskUb, tvUbTensor, (float)1e10, AscendC::CMPMODE::LE, curRowNum * embedRound | ||
| 142 | + ); | ||
| 143 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 144 | + AscendC::Select( | ||
| 145 | + goUbTensor32[oUbOffset], cmpMaskUb, goUbTensor32[oUbOffset], (float)0.0, AscendC::SELMODE::VSEL_TENSOR_SCALAR_MODE, curRowNum * embedRound | ||
| 146 | + ); | ||
| 147 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 148 | + | ||
| 149 | + AscendC::Brcb(tvUbTensor.ReinterpretCast<uint32_t>(), | ||
| 150 | + glUbTensor[taskPingPongFlag].ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], | ||
| 151 | + curRowNumRound / FLOAT_BLOCK_SIZE, | ||
| 152 | + AscendC::BrcbRepeatParams(1, 8)); | ||
| 153 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 154 | + | ||
| 155 | + // *** go = go / gl_block | ||
| 156 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 157 | + for (uint32_t vdiv_idx = 0; vdiv_idx < embed / FLOAT_VECTOR_SIZE; ++vdiv_idx) { | ||
| 158 | + AscendC::Div<float, false>(goUbTensor32[oUbOffset + vdiv_idx * FLOAT_VECTOR_SIZE], | ||
| 159 | + goUbTensor32[oUbOffset + vdiv_idx * FLOAT_VECTOR_SIZE], | ||
| 160 | + tvUbTensor, (uint64_t)0, | ||
| 161 | + curRowNum, | ||
| 162 | + AscendC::BinaryRepeatParams(1, 1, 0, embedRound / FLOAT_BLOCK_SIZE, | ||
| 163 | + embedRound / FLOAT_BLOCK_SIZE, 1)); | ||
| 164 | + | ||
| 165 | + } | ||
| 166 | + if (embed % FLOAT_VECTOR_SIZE > 0) { | ||
| 167 | + SetMask(embed % FLOAT_VECTOR_SIZE); | ||
| 168 | + AscendC::Div<float, false>(goUbTensor32[oUbOffset + embed / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 169 | + goUbTensor32[oUbOffset + embed / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 170 | + tvUbTensor, | ||
| 171 | + (uint64_t)0, curRowNum, | ||
| 172 | + AscendC::BinaryRepeatParams(1, 1, 0, embedRound / FLOAT_BLOCK_SIZE, | ||
| 173 | + embedRound / FLOAT_BLOCK_SIZE, 1)); | ||
| 174 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 175 | + | ||
| 176 | + } | ||
| 177 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 178 | + | ||
| 179 | + // *** go = castfp32to16(go) | ||
| 180 | + if (std::is_same<ElementOutput, bfloat16_t>::value) { | ||
| 181 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 182 | + goUbTensor16[oUbOffset * 2], goUbTensor32[oUbOffset], | ||
| 183 | + AscendC::RoundMode::CAST_RINT, (uint64_t)0, | ||
| 184 | + (curRowNum * embedRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 185 | + AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 186 | + } else { | ||
| 187 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 188 | + goUbTensor16[oUbOffset * 2], goUbTensor32[oUbOffset], | ||
| 189 | + AscendC::RoundMode::CAST_NONE, (uint64_t)0, | ||
| 190 | + (curRowNum * embedRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 191 | + AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); | ||
| 195 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); | ||
| 196 | + | ||
| 197 | + // ********************* move O to GM ************************ | ||
| 198 | + AscendC::DataCopyPad(gOutput, goUbTensor16[oUbOffset * 2], | ||
| 199 | + AscendC::DataCopyExtParams(curRowNum, embed * 2, 0, 0, 0)); | ||
| 200 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(oPingPangFlag + 4); | ||
| 201 | + | ||
| 202 | + oPingPangFlag = 1 - oPingPangFlag; | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + CATLASS_DEVICE | ||
| 206 | + void operator()(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, | ||
| 207 | + AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, | ||
| 208 | + AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, | ||
| 209 | + const LayoutUpdate &layoutUpdate, const LayoutOutput &layoutOutput, GemmCoord actualBlockShape, | ||
| 210 | + uint32_t nIdx, uint32_t rescaleOPingPongFlag, uint32_t *glFlag, uint32_t taskPingPongFlag) | ||
| 211 | + { | ||
| 212 | + uint32_t embed = layoutInput.shape(1); | ||
| 213 | + uint32_t rowActual = actualBlockShape.m(); | ||
| 214 | + uint32_t columnActual = actualBlockShape.n(); | ||
| 215 | + | ||
| 216 | + uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | ||
| 217 | + uint32_t subBlockNum = AscendC::GetSubBlockNum(); | ||
| 218 | + | ||
| 219 | + uint32_t curRowSplitSubBlock = rowActual / subBlockNum; | ||
| 220 | + uint32_t rowActualThisSubBlock = (subBlockIdx == 0) ? curRowSplitSubBlock : (rowActual - curRowSplitSubBlock); | ||
| 221 | + uint32_t rowOffsetSubBlock = subBlockIdx * curRowSplitSubBlock; | ||
| 222 | + | ||
| 223 | + if (rowActualThisSubBlock > 0) { | ||
| 224 | + uint32_t rowLoop = (rowActualThisSubBlock + ROW_WISE_CYCLE_TILE - 1) / ROW_WISE_CYCLE_TILE; | ||
| 225 | + uint32_t needRowLoop = (rowLoop > 1) ? 1 : 0; | ||
| 226 | + for (uint32_t rowLoopIdx = 0; rowLoopIdx < rowLoop; rowLoopIdx++) { | ||
| 227 | + uint32_t rowOffsetLoop = rowLoopIdx * ROW_WISE_CYCLE_TILE; | ||
| 228 | + uint32_t rowOffsetCurCycle = rowOffsetSubBlock + rowOffsetLoop; | ||
| 229 | + uint32_t rowActualCurCycle = | ||
| 230 | + (rowLoopIdx == (rowLoop - 1)) ? rowActualThisSubBlock - rowOffsetLoop : ROW_WISE_CYCLE_TILE; | ||
| 231 | + int64_t offsetInput = layoutInput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | ||
| 232 | + auto gInputThisCurCycle = gInput[offsetInput]; | ||
| 233 | + auto layoutInputCurCycle = layoutInput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | ||
| 234 | + | ||
| 235 | + int64_t offsetUpdate = layoutUpdate.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | ||
| 236 | + auto gUpdateCurCycle = gUpdate[offsetUpdate]; | ||
| 237 | + auto layoutUpdateCurCycle = layoutUpdate.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | ||
| 238 | + | ||
| 239 | + int64_t offsetOutput = layoutOutput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | ||
| 240 | + auto gOutputCurCycle = gOutput[offsetOutput]; | ||
| 241 | + auto layoutOutputCurCycle = layoutOutput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | ||
| 242 | + | ||
| 243 | + SubCoreCompute(gInputThisCurCycle, gUpdateCurCycle, gOutputCurCycle, | ||
| 244 | + gOCoreTmp[rowOffsetLoop * embed * kvSplitCoreNum], | ||
| 245 | + gl[rowOffsetLoop * kvSplitCoreNum], layoutInputCurCycle, | ||
| 246 | + layoutOutputCurCycle, layoutUpdateCurCycle, nIdx, needRowLoop, rowLoopIdx, | ||
| 247 | + rescaleOPingPongFlag, glFlag, taskPingPongFlag); | ||
| 248 | + } | ||
| 249 | + } | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | +private: | ||
| 253 | + uint32_t kvSplitCoreNum = 1; | ||
| 254 | + uint32_t oPingPangFlag = 0; | ||
| 255 | + AscendC::LocalTensor<float> loUbTensor; | ||
| 256 | + AscendC::LocalTensor<float> dmUbTensor; | ||
| 257 | + AscendC::LocalTensor<float> glUbTensor[2]; | ||
| 258 | + AscendC::LocalTensor<float> tvUbTensor; | ||
| 259 | + AscendC::LocalTensor<ElementOutput> goUbTensor16; | ||
| 260 | + AscendC::LocalTensor<float> goUbTensor32; | ||
| 261 | + AscendC::LocalTensor<float> hmUbTensor; | ||
| 262 | + AscendC::LocalTensor<float> gmUbTensor[2]; | ||
| 263 | +}; | ||
| 264 | + | ||
| 265 | +} // namespace Catlass::Epilogue::Block | ||
| 266 | + | ||
| 267 | + | ||
| @@ -0,0 +1,838 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace Catlass::Epilogue::Block { | ||
| 23 | + | ||
| 24 | +template < | ||
| 25 | + class OutputType_, | ||
| 26 | + class InputType_, | ||
| 27 | + class UpdateType_, | ||
| 28 | + class MaskType_> | ||
| 29 | +class BlockEpilogue< | ||
| 30 | + EpilogueAtlasA2AMLATP1Softmax, | ||
| 31 | + OutputType_, | ||
| 32 | + InputType_, | ||
| 33 | + UpdateType_, | ||
| 34 | + MaskType_> | ||
| 35 | +{ | ||
| 36 | +public: | ||
| 37 | + // Type aliases | ||
| 38 | + using DispatchPolicy = EpilogueAtlasA2AMLATP1Softmax; | ||
| 39 | + using ArchTag = typename DispatchPolicy::ArchTag; | ||
| 40 | + using ElementOutput = typename OutputType_::Element; | ||
| 41 | + using ElementInput = typename InputType_::Element; | ||
| 42 | + using ElementMask = typename MaskType_::Element; | ||
| 43 | + | ||
| 44 | + using LayoutOutput = typename OutputType_::Layout; | ||
| 45 | + using LayoutInput = typename InputType_::Layout; | ||
| 46 | + using LayoutMask = typename MaskType_::Layout; | ||
| 47 | + using LayoutUpdate = typename UpdateType_::Layout; | ||
| 48 | + | ||
| 49 | + using CopyGmToUbInput = Tile::CopyGm2Ub<ArchTag, InputType_>; | ||
| 50 | + using CopyGmToUbMask = Tile::CopyGm2Ub<ArchTag, MaskType_>; | ||
| 51 | + using CopyUbToGmOutput = Tile::CopyUb2Gm<ArchTag, OutputType_>; | ||
| 52 | + | ||
| 53 | + static constexpr uint32_t FLOAT_BLOCK_SIZE = 8; | ||
| 54 | + static constexpr uint32_t FLOAT_VECTOR_SIZE = 64; | ||
| 55 | + static constexpr uint32_t HALF_VECTOR_SIZE = 128; | ||
| 56 | + static constexpr uint32_t BLOCK_SIZE = 16; | ||
| 57 | + static constexpr uint32_t UB_UINT8_LINE_SIZE = 512; | ||
| 58 | + static constexpr uint32_t UB_UINT8_BLOCK_SIZE_MLA = 16384; | ||
| 59 | + static constexpr uint32_t VECTOR_SIZE = 128; | ||
| 60 | + | ||
| 61 | + static constexpr uint32_t REDUCE_UB_SIZE = 1024; | ||
| 62 | + static constexpr uint32_t ROW_OPS_SPEC_MASK_32 = 32; | ||
| 63 | + static constexpr uint32_t ROW_OPS_SPEC_MASK_4 = 4; | ||
| 64 | + static constexpr uint32_t S_BLOCK_STACK = 4; | ||
| 65 | + static constexpr int64_t UB_FLOAT_LINE_SIZE = 64; | ||
| 66 | + static constexpr uint32_t M_SLICE = 16; | ||
| 67 | + static constexpr uint32_t QK_READY_ID = 1; | ||
| 68 | + static constexpr uint32_t SOFTMAX_READY_ID = 2; | ||
| 69 | + | ||
| 70 | + static constexpr float LN2 = 0.6931471805599453094172; | ||
| 71 | + static constexpr float RECIP_OF_LN2 = 1 / LN2; | ||
| 72 | + static constexpr float FLOAT_E_SCALAR = 8388608; | ||
| 73 | + static constexpr uint32_t PRE_AUTOADD_READY_ID = 0; | ||
| 74 | + static constexpr uint32_t SM_AUTOADD_READY_ID = 7; | ||
| 75 | + static constexpr uint32_t BRCB_SIZE = 128; | ||
| 76 | + | ||
| 77 | + CATLASS_DEVICE | ||
| 78 | + BlockEpilogue(Arch::Resource<ArchTag> &resource, half tor_, uint32_t kvSplitCoreNum_ = 1) | ||
| 79 | + { | ||
| 80 | + // Allocate UB space | ||
| 81 | + constexpr uint32_t LS_UB_TENSOR_OFFSET = 0; | ||
| 82 | + constexpr uint32_t LP_UB_TENSOR_OFFSET = 0; | ||
| 83 | + constexpr uint32_t LM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 84 | + constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; | ||
| 85 | + constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 2 * UB_UINT8_LINE_SIZE; | ||
| 86 | + constexpr uint32_t LL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 4 * UB_UINT8_LINE_SIZE; | ||
| 87 | + constexpr uint32_t GM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 5 * UB_UINT8_LINE_SIZE; | ||
| 88 | + constexpr uint32_t GL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 7 * UB_UINT8_LINE_SIZE; | ||
| 89 | + constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 90 | + | ||
| 91 | + constexpr uint32_t NBRCB_UB_TENSOR_OFFSET = 4 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 92 | + constexpr uint32_t HN_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 9 * UB_UINT8_LINE_SIZE; | ||
| 93 | + constexpr uint32_t DN_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 10 * UB_UINT8_LINE_SIZE; | ||
| 94 | + constexpr uint32_t GN_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 12 * UB_UINT8_LINE_SIZE; | ||
| 95 | + constexpr uint32_t S32_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 14 * UB_UINT8_LINE_SIZE; | ||
| 96 | + constexpr uint32_t S16Tmp_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 16 * UB_UINT8_LINE_SIZE; | ||
| 97 | + constexpr uint32_t S16_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 18 * UB_UINT8_LINE_SIZE; | ||
| 98 | + constexpr uint32_t HC_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 20 * UB_UINT8_LINE_SIZE; | ||
| 99 | + constexpr uint32_t GC_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 22 * UB_UINT8_LINE_SIZE; | ||
| 100 | + constexpr uint32_t EPS_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 24 * UB_UINT8_LINE_SIZE; | ||
| 101 | + constexpr uint32_t N_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 26 * UB_UINT8_LINE_SIZE; | ||
| 102 | + | ||
| 103 | + tor = tor_; | ||
| 104 | + kvSplitCoreNum = kvSplitCoreNum_; | ||
| 105 | + lsUbTensor = resource.ubBuf.template GetBufferByByte<float>(LS_UB_TENSOR_OFFSET); | ||
| 106 | + lpUbTensor = resource.ubBuf.template GetBufferByByte<ElementOutput>(LP_UB_TENSOR_OFFSET); | ||
| 107 | + lmUbTensor = resource.ubBuf.template GetBufferByByte<float>(LM_UB_TENSOR_OFFSET); | ||
| 108 | + hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | ||
| 109 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | ||
| 110 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 111 | + dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); | ||
| 112 | + llUbTensor = resource.ubBuf.template GetBufferByByte<float>(LL_UB_TENSOR_OFFSET); | ||
| 113 | + tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); | ||
| 114 | + glUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); | ||
| 115 | + glUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 116 | + | ||
| 117 | + hnUbTensor = resource.ubBuf.template GetBufferByByte<float>(HN_UB_TENSOR_OFFSET); | ||
| 118 | + dnUbTensor = resource.ubBuf.template GetBufferByByte<float>(DN_UB_TENSOR_OFFSET); | ||
| 119 | + gnUbTensor = resource.ubBuf.template GetBufferByByte<float>(GN_UB_TENSOR_OFFSET); | ||
| 120 | + s32UbTensor = resource.ubBuf.template GetBufferByByte<float>(S32_UB_TENSOR_OFFSET); | ||
| 121 | + s16UbTensorTmp = resource.ubBuf.template GetBufferByByte<ElementOutput>(S16Tmp_UB_TENSOR_OFFSET); | ||
| 122 | + NBrcbUbTensor = resource.ubBuf.template GetBufferByByte<int32_t>(NBRCB_UB_TENSOR_OFFSET); | ||
| 123 | + s16UbTensor = resource.ubBuf.template GetBufferByByte<float>(S16_UB_TENSOR_OFFSET); | ||
| 124 | + hcUbTensor = resource.ubBuf.template GetBufferByByte<float>(HC_UB_TENSOR_OFFSET); | ||
| 125 | + gcUbTensor = resource.ubBuf.template GetBufferByByte<float>(GC_UB_TENSOR_OFFSET); | ||
| 126 | + epsUbTensor = resource.ubBuf.template GetBufferByByte<float>(EPS_UB_TENSOR_OFFSET); | ||
| 127 | + NUbTensor = resource.ubBuf.template GetBufferByByte<int32_t>(N_UB_TENSOR_OFFSET); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + CATLASS_DEVICE | ||
| 131 | + ~BlockEpilogue() {} | ||
| 132 | + | ||
| 133 | + CATLASS_DEVICE | ||
| 134 | + void SetVecMask(int32_t len) | ||
| 135 | + { | ||
| 136 | + uint64_t mask = 0; | ||
| 137 | + uint64_t one = 1; | ||
| 138 | + uint64_t temp = len % FLOAT_VECTOR_SIZE; | ||
| 139 | + for (int64_t i = 0; i < temp; i++) { | ||
| 140 | + mask |= one << i; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + if (len == VECTOR_SIZE || len == 0) { | ||
| 144 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 145 | + } else if (len >= FLOAT_VECTOR_SIZE) { | ||
| 146 | + AscendC::SetVectorMask<int8_t>(mask, (uint64_t)-1); | ||
| 147 | + } else { | ||
| 148 | + AscendC::SetVectorMask<int8_t>(0x0, mask); | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + CATLASS_DEVICE | ||
| 153 | + void SetkvSplitCoreNum(uint32_t kvSplitCoreNum_) | ||
| 154 | + { | ||
| 155 | + kvSplitCoreNum = kvSplitCoreNum_; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + CATLASS_DEVICE | ||
| 159 | + void SetBlockReduceMask(int32_t len) | ||
| 160 | + { | ||
| 161 | + if (len > 8 || len < 1) { | ||
| 162 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 163 | + return; | ||
| 164 | + } | ||
| 165 | + uint64_t subMask = ((uint64_t)1 << len) - 1; | ||
| 166 | + uint64_t maskValue = (subMask << 48) + (subMask << 32) + (subMask << 16) + subMask + (subMask << 56) + | ||
| 167 | + (subMask << 40) + (subMask << 24) + (subMask << 8); | ||
| 168 | + AscendC::SetVectorMask<int8_t>(maskValue, maskValue); | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + CATLASS_DEVICE | ||
| 172 | + void RowsumSPECTILE512(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowsumUb, | ||
| 173 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 174 | + uint32_t numElemsAligned) | ||
| 175 | + { | ||
| 176 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb, numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE, 0, | ||
| 177 | + 1, 1, 8); | ||
| 178 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 179 | + | ||
| 180 | + AscendC::BlockReduceSum<float, false>(tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 181 | + numRowsRound * numElemsAligned / FLOAT_BLOCK_SIZE / FLOAT_VECTOR_SIZE, 0, | ||
| 182 | + 1, 1, 8); | ||
| 183 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 184 | + AscendC::BlockReduceSum<float, false>(rowsumUb, tvUbTensor[REDUCE_UB_SIZE], | ||
| 185 | + numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE / FLOAT_VECTOR_SIZE, 0, | ||
| 186 | + 1, 1, 8); | ||
| 187 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + CATLASS_DEVICE | ||
| 191 | + void RowsumSPECTILE256(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowsumUb, | ||
| 192 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 193 | + uint32_t numElemsAligned) | ||
| 194 | + { | ||
| 195 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb, numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE, 0, | ||
| 196 | + 1, 1, 8); | ||
| 197 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 198 | + SetVecMask(ROW_OPS_SPEC_MASK_32); | ||
| 199 | + AscendC::BlockReduceSum<float, false>(tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, numRowsRound, 0, 1, 1, 4); | ||
| 200 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 201 | + SetBlockReduceMask(ROW_OPS_SPEC_MASK_4); | ||
| 202 | + AscendC::BlockReduceSum<float, false>( | ||
| 203 | + rowsumUb, tvUbTensor[REDUCE_UB_SIZE], | ||
| 204 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 205 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 206 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + CATLASS_DEVICE | ||
| 210 | + void RowsumTAILTILE(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowsumUb, | ||
| 211 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 212 | + uint32_t numElemsAligned) | ||
| 213 | + { | ||
| 214 | + if (numElems >= FLOAT_VECTOR_SIZE) { | ||
| 215 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb, numRowsRound, 0, 1, 1, | ||
| 216 | + numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 217 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 218 | + AscendC::BlockReduceSum<float, false>( | ||
| 219 | + rowsumUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, | ||
| 220 | + 1, 1, 8); | ||
| 221 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 222 | + for (uint64_t rowSumIdx = 1; rowSumIdx < (uint64_t)numElems / FLOAT_VECTOR_SIZE; ++rowSumIdx) { | ||
| 223 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb[rowSumIdx * FLOAT_VECTOR_SIZE], numRowsRound, 0, | ||
| 224 | + 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 225 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 226 | + AscendC::BlockReduceSum<float, false>( | ||
| 227 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 228 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 229 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 230 | + SetVecMask(numRowsRound); | ||
| 231 | + AscendC::Add<float, false>(rowsumUb, rowsumUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 232 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 233 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 234 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 235 | + } | ||
| 236 | + } | ||
| 237 | + if (numElems % FLOAT_VECTOR_SIZE > 0) { | ||
| 238 | + SetVecMask(numElems % FLOAT_VECTOR_SIZE); | ||
| 239 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb[numElems / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 240 | + numRowsRound, 0, 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 241 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 242 | + SetBlockReduceMask((numElems % FLOAT_VECTOR_SIZE + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE); | ||
| 243 | + if (numElems < FLOAT_VECTOR_SIZE) { | ||
| 244 | + AscendC::BlockReduceSum<float, false>( | ||
| 245 | + rowsumUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 246 | + 0, 1, 1, 8); | ||
| 247 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 248 | + } else { | ||
| 249 | + AscendC::BlockReduceSum<float, false>( | ||
| 250 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 251 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 252 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 253 | + SetVecMask(numRowsRound); | ||
| 254 | + AscendC::Add<float, false>(rowsumUb, rowsumUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 255 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 256 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 257 | + } | ||
| 258 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + CATLASS_DEVICE | ||
| 263 | + void RowmaxSPECTILE512(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowmaxUb, | ||
| 264 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 265 | + uint32_t numElemsAligned) | ||
| 266 | + { | ||
| 267 | + AscendC::BlockReduceMax<float, false>(tvUbTensor, srcUb, numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE, 0, | ||
| 268 | + 1, 1, 8); | ||
| 269 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 270 | + AscendC::BlockReduceMax<float, false>(tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 271 | + numRowsRound * numElemsAligned / FLOAT_BLOCK_SIZE / FLOAT_VECTOR_SIZE, 0, | ||
| 272 | + 1, 1, 8); | ||
| 273 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 274 | + AscendC::BlockReduceMax<float, false>(rowmaxUb, tvUbTensor[REDUCE_UB_SIZE], | ||
| 275 | + numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE / FLOAT_VECTOR_SIZE, 0, | ||
| 276 | + 1, 1, 8); | ||
| 277 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + CATLASS_DEVICE | ||
| 281 | + void RowmaxSPECTILE256(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowmaxUb, | ||
| 282 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 283 | + uint32_t numElemsAligned) | ||
| 284 | + { | ||
| 285 | + AscendC::BlockReduceMax<float, false>(tvUbTensor, srcUb, numRowsRound * numElemsAligned / FLOAT_VECTOR_SIZE, 0, | ||
| 286 | + 1, 1, 8); | ||
| 287 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 288 | + SetVecMask(ROW_OPS_SPEC_MASK_32); | ||
| 289 | + AscendC::BlockReduceMax<float, false>(tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, numRowsRound, 0, 1, 1, 4); | ||
| 290 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 291 | + SetBlockReduceMask(ROW_OPS_SPEC_MASK_4); | ||
| 292 | + AscendC::BlockReduceMax<float, false>( | ||
| 293 | + rowmaxUb, tvUbTensor[REDUCE_UB_SIZE], | ||
| 294 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 295 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 296 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + CATLASS_DEVICE | ||
| 300 | + void RowmaxTAILTILE(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowmaxUb, | ||
| 301 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 302 | + uint32_t numElemsAligned) | ||
| 303 | + { | ||
| 304 | + if (numElems >= FLOAT_VECTOR_SIZE) { | ||
| 305 | + AscendC::BlockReduceMax<float, false>(tvUbTensor, srcUb, numRowsRound, 0, 1, 1, | ||
| 306 | + numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 307 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 308 | + AscendC::BlockReduceMax<float, false>( | ||
| 309 | + rowmaxUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, | ||
| 310 | + 1, 1, 8); | ||
| 311 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 312 | + for (uint64_t rowmax_idx = 1; rowmax_idx < (uint64_t)numElems / FLOAT_VECTOR_SIZE; ++rowmax_idx) { | ||
| 313 | + AscendC::BlockReduceMax<float, false>(tvUbTensor, srcUb[rowmax_idx * FLOAT_VECTOR_SIZE], numRowsRound, | ||
| 314 | + 0, 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 315 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 316 | + AscendC::BlockReduceMax<float, false>( | ||
| 317 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 318 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 319 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 320 | + SetVecMask(numRowsRound); | ||
| 321 | + AscendC::Max<float, false>(rowmaxUb, rowmaxUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 322 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 323 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 324 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + if (numElems % FLOAT_VECTOR_SIZE > 0) { | ||
| 328 | + SetVecMask(numElems % FLOAT_VECTOR_SIZE); | ||
| 329 | + AscendC::BlockReduceMax<float, false>(tvUbTensor, srcUb[numElems / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 330 | + numRowsRound, 0, 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 331 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 332 | + SetBlockReduceMask((numElems % FLOAT_VECTOR_SIZE + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE); | ||
| 333 | + if (numElems < FLOAT_VECTOR_SIZE) { | ||
| 334 | + AscendC::BlockReduceMax<float, false>( | ||
| 335 | + rowmaxUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 336 | + 0, 1, 1, 8); | ||
| 337 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 338 | + } else { | ||
| 339 | + AscendC::BlockReduceMax<float, false>( | ||
| 340 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 341 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 342 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 343 | + SetVecMask(numRowsRound); | ||
| 344 | + AscendC::Max<float, false>(rowmaxUb, rowmaxUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 345 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 346 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 347 | + } | ||
| 348 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 349 | + } | ||
| 350 | + } | ||
| 351 | + | ||
| 352 | + CATLASS_DEVICE | ||
| 353 | + void SubCoreCompute(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, | ||
| 354 | + uint32_t m, uint32_t nReal, uint32_t nStride, uint32_t pingpongFlag, uint32_t rowOffset, | ||
| 355 | + uint32_t sUbOffset, uint32_t nIdx, uint32_t isLastNTile, uint32_t *glFlag, | ||
| 356 | + uint32_t taskPingPongFlag, uint32_t gSPingPongFlag, uint32_t isLastM, uint32_t isFirstM) | ||
| 357 | + { | ||
| 358 | + uint32_t round_m = (m + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE * FLOAT_BLOCK_SIZE; | ||
| 359 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(pingpongFlag); | ||
| 360 | + // input QK | ||
| 361 | + AscendC::DataCopy(lsUbTensor[sUbOffset], gInput, AscendC::DataCopyParams(m, nStride / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 362 | + | ||
| 363 | + AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); | ||
| 364 | + AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); | ||
| 365 | + | ||
| 366 | + // *** ls = tor * ls | ||
| 367 | + AscendC::Muls<float, false>(lsUbTensor[sUbOffset], lsUbTensor[sUbOffset], tor, (uint64_t)0, | ||
| 368 | + (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 369 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 370 | + | ||
| 371 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 372 | + | ||
| 373 | + | ||
| 374 | + if (nReal == 512) { | ||
| 375 | + RowmaxSPECTILE512(lsUbTensor[sUbOffset], lmUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 376 | + } else if (nReal == 256) { | ||
| 377 | + RowmaxSPECTILE256(lsUbTensor[sUbOffset], lmUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 378 | + } else { | ||
| 379 | + RowmaxTAILTILE(lsUbTensor[sUbOffset], lmUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + | ||
| 383 | + if (nIdx == 0) { | ||
| 384 | + AscendC::DataCopy(hmUbTensor[rowOffset], lmUbTensor[rowOffset], | ||
| 385 | + AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 386 | + | ||
| 387 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 388 | + } else { | ||
| 389 | + SetVecMask(m); | ||
| 390 | + // *** hm = vmax(lm, gm) | ||
| 391 | + AscendC::Max<float, false>(hmUbTensor[rowOffset], lmUbTensor[rowOffset], gmUbTensor[taskPingPongFlag][rowOffset], (uint64_t)0, | ||
| 392 | + 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 393 | + | ||
| 394 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 395 | + // *** dm = gm - hm | ||
| 396 | + AscendC::Sub<float, false>(dmUbTensor[rowOffset], | ||
| 397 | + gmUbTensor[taskPingPongFlag][rowOffset], hmUbTensor[rowOffset], (uint64_t)0, 1, | ||
| 398 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 399 | + | ||
| 400 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 401 | + // *** dm = exp(dm) | ||
| 402 | + AscendC::Exp<float, false>(dmUbTensor[rowOffset], | ||
| 403 | + dmUbTensor[rowOffset], | ||
| 404 | + (uint64_t)0, 1, AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 408 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 409 | + // *** gm = hm | ||
| 410 | + AscendC::DataCopy(gmUbTensor[taskPingPongFlag][rowOffset], hmUbTensor[rowOffset], | ||
| 411 | + AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 412 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 413 | + | ||
| 414 | + // ni = hnUbTensor = mi / -LN2 | ||
| 415 | + SetVecMask(m); | ||
| 416 | + AscendC::Muls<float, false>( | ||
| 417 | + hnUbTensor[rowOffset], | ||
| 418 | + hmUbTensor[rowOffset], | ||
| 419 | + (-1.0f) * RECIP_OF_LN2, | ||
| 420 | + (uint64_t)0, | ||
| 421 | + 1, | ||
| 422 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 423 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 424 | + AscendC::Cast<float, float, false>( | ||
| 425 | + hnUbTensor[rowOffset], hnUbTensor[rowOffset], AscendC::RoundMode::CAST_ROUND, (uint64_t)0, | ||
| 426 | + 1, AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 427 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 428 | + | ||
| 429 | + // dnUbTensor = ni - ni-1 | ||
| 430 | + if (nIdx != 0) { | ||
| 431 | + AscendC::Sub<float, false>( | ||
| 432 | + dnUbTensor[rowOffset], | ||
| 433 | + hnUbTensor[rowOffset], | ||
| 434 | + gnUbTensor[rowOffset], | ||
| 435 | + (uint64_t)0, | ||
| 436 | + 1, | ||
| 437 | + AscendC::BinaryRepeatParams( | ||
| 438 | + 1, 1, 1, 8, 8, 8)); | ||
| 439 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 440 | + } else { | ||
| 441 | + // n1 = n0, dn = 0 | ||
| 442 | + AscendC::Duplicate<float, false>(dnUbTensor[rowOffset], 0.0f, (uint64_t)0, 1, 1, 8); | ||
| 443 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 444 | + } | ||
| 445 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 446 | + AscendC::DataCopy(gnUbTensor[rowOffset], hnUbTensor[rowOffset], AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 447 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 448 | + | ||
| 449 | + // mi / LN2 | ||
| 450 | + SetVecMask(m); | ||
| 451 | + AscendC::Muls<float, false>( | ||
| 452 | + tvUbTensor, | ||
| 453 | + hmUbTensor[rowOffset], | ||
| 454 | + RECIP_OF_LN2, | ||
| 455 | + (uint64_t)0, | ||
| 456 | + 1, | ||
| 457 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 458 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 459 | + // hnUbTensor = ni + mi / LN2 | ||
| 460 | + AscendC::Add<float, false>( | ||
| 461 | + hnUbTensor[rowOffset], | ||
| 462 | + hnUbTensor[rowOffset], | ||
| 463 | + tvUbTensor, | ||
| 464 | + (uint64_t)0, | ||
| 465 | + 1, | ||
| 466 | + AscendC::BinaryRepeatParams( | ||
| 467 | + 1, 1, 1, 8, 8, 8)); | ||
| 468 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 469 | + // ln2 * (ni + mi / ln2) | ||
| 470 | + AscendC::Muls<float, false>( | ||
| 471 | + hnUbTensor[rowOffset], | ||
| 472 | + hnUbTensor[rowOffset], | ||
| 473 | + LN2, | ||
| 474 | + (uint64_t)0, | ||
| 475 | + 1, | ||
| 476 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 477 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 478 | + // s32 = exp(ln2 * (ni + mi / ln2)) | ||
| 479 | + AscendC::Exp<float, false>( | ||
| 480 | + s32UbTensor[rowOffset], | ||
| 481 | + hnUbTensor[rowOffset], | ||
| 482 | + (uint64_t)0, | ||
| 483 | + 1, | ||
| 484 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 485 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 486 | + // s16 = s32 -> s16 | ||
| 487 | + if (std::is_same<ElementOutput, bfloat16_t>::value) { | ||
| 488 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 489 | + s16UbTensorTmp[rowOffset], s32UbTensor[rowOffset], AscendC::RoundMode::CAST_ROUND, (uint64_t)0, | ||
| 490 | + 1, AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 491 | + } else { | ||
| 492 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 493 | + s16UbTensorTmp[rowOffset], s32UbTensor[rowOffset], AscendC::RoundMode::CAST_RINT, (uint64_t)0, | ||
| 494 | + 1, AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 495 | + } | ||
| 496 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 497 | + // s16 = s16 -> s16 | ||
| 498 | + AscendC::Cast<float, ElementOutput, false>( | ||
| 499 | + s16UbTensor[rowOffset], s16UbTensorTmp[rowOffset], AscendC::RoundMode::CAST_NONE, (uint64_t)0, | ||
| 500 | + 1, AscendC::UnaryRepeatParams(1, 1, 8, 4)); | ||
| 501 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 502 | + | ||
| 503 | + // *** hm_block = expand_to_block(hm), 存放于 tv | ||
| 504 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 505 | + AscendC::Brcb(tvUbTensor.template ReinterpretCast<uint32_t>(), | ||
| 506 | + hmUbTensor[rowOffset].template ReinterpretCast<uint32_t>(), round_m / FLOAT_BLOCK_SIZE, | ||
| 507 | + AscendC::BrcbRepeatParams(1, 8)); | ||
| 508 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 509 | + | ||
| 510 | + // *** ls = ls - hm_block | ||
| 511 | + for (uint32_t subIdx = 0; subIdx < nReal / FLOAT_VECTOR_SIZE; ++subIdx) { | ||
| 512 | + AscendC::Sub<float, false>( | ||
| 513 | + lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], | ||
| 514 | + tvUbTensor, (uint64_t)0, m, | ||
| 515 | + AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | ||
| 516 | + } | ||
| 517 | + if (nReal % FLOAT_VECTOR_SIZE > 0) { | ||
| 518 | + SetVecMask(nReal % FLOAT_VECTOR_SIZE); | ||
| 519 | + AscendC::Sub<float, false>( | ||
| 520 | + lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 521 | + lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], tvUbTensor, (uint64_t)0, m, | ||
| 522 | + AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | ||
| 523 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 524 | + } | ||
| 525 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 526 | + | ||
| 527 | + // *** ls = exp(ls) | ||
| 528 | + AscendC::Exp<float, false>(lsUbTensor[sUbOffset], lsUbTensor[sUbOffset], (uint64_t)0, | ||
| 529 | + (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 530 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 531 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 532 | + | ||
| 533 | + // *** ll = rowsum(ls32) | ||
| 534 | + if (nReal == 512) { | ||
| 535 | + RowsumSPECTILE512(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 536 | + } else if (nReal == 256) { | ||
| 537 | + RowsumSPECTILE256(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 538 | + } else { | ||
| 539 | + RowsumTAILTILE(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | ||
| 540 | + } | ||
| 541 | + | ||
| 542 | + AscendC::Brcb( | ||
| 543 | + tvUbTensor.ReinterpretCast<uint32_t>(), | ||
| 544 | + s16UbTensor.ReinterpretCast<uint32_t>()[rowOffset], | ||
| 545 | + round_m / FLOAT_BLOCK_SIZE, | ||
| 546 | + AscendC::BrcbRepeatParams(1, 8)); | ||
| 547 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 548 | + | ||
| 549 | + // *** p = p * s16 | ||
| 550 | + for (uint32_t subIdx = 0; subIdx < nReal / FLOAT_VECTOR_SIZE; ++subIdx) { | ||
| 551 | + AscendC::Mul<float, false>( | ||
| 552 | + lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], | ||
| 553 | + tvUbTensor, (uint64_t)0, m, | ||
| 554 | + AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | ||
| 555 | + | ||
| 556 | + } | ||
| 557 | + if (nReal % FLOAT_VECTOR_SIZE > 0) { | ||
| 558 | + SetVecMask(nReal % FLOAT_VECTOR_SIZE); | ||
| 559 | + AscendC::Mul<float, false>( | ||
| 560 | + lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 561 | + lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], tvUbTensor, (uint64_t)0, m, | ||
| 562 | + AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | ||
| 563 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 564 | + } | ||
| 565 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 566 | + | ||
| 567 | + // *** lp = castfp32to16(ls) | ||
| 568 | + if (std::is_same<ElementOutput, bfloat16_t>::value) { | ||
| 569 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 570 | + lpUbTensor[sUbOffset * 2], lsUbTensor[sUbOffset], AscendC::RoundMode::CAST_RINT, (uint64_t)0, | ||
| 571 | + (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 572 | + } else { | ||
| 573 | + AscendC::Cast<ElementOutput, float, false>( | ||
| 574 | + lpUbTensor[sUbOffset * 2], lsUbTensor[sUbOffset], AscendC::RoundMode::CAST_NONE, (uint64_t)0, | ||
| 575 | + (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, AscendC::UnaryRepeatParams(1, 1, 4, 8)); | ||
| 576 | + } | ||
| 577 | + | ||
| 578 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); | ||
| 579 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); | ||
| 580 | + | ||
| 581 | + AscendC::DataCopy(gOutput, lpUbTensor[sUbOffset * 2], AscendC::DataCopyParams(m, nStride * 2 / 32, 0, 0)); | ||
| 582 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(pingpongFlag); | ||
| 583 | + | ||
| 584 | + if (isLastM) { | ||
| 585 | + Arch::CrossCoreSetFlag<0x2, PIPE_MTE3>(softmaxReady); | ||
| 586 | + } | ||
| 587 | + if (nIdx == 0) { | ||
| 588 | + // *** gl = ll | ||
| 589 | + AscendC::DataCopy(glUbTensor[taskPingPongFlag][rowOffset], llUbTensor[rowOffset], | ||
| 590 | + AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 591 | + | ||
| 592 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 593 | + } else { | ||
| 594 | + SetVecMask(m); | ||
| 595 | + // // *** gl = dm * gl | ||
| 596 | + AscendC::Mul<float, false>( | ||
| 597 | + glUbTensor[taskPingPongFlag][rowOffset], dmUbTensor[rowOffset], | ||
| 598 | + glUbTensor[taskPingPongFlag][rowOffset], (uint64_t)0, 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 599 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 600 | + | ||
| 601 | + // // *** gl = ll + gl | ||
| 602 | + AscendC::Add<float, false>(glUbTensor[taskPingPongFlag][rowOffset], glUbTensor[taskPingPongFlag][rowOffset], llUbTensor[rowOffset], (uint64_t)0, | ||
| 603 | + 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 604 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 605 | + | ||
| 606 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 607 | + } | ||
| 608 | + // ----------------------------------------- | ||
| 609 | + SetVecMask(m); | ||
| 610 | + if (isLastNTile) { | ||
| 611 | + AscendC::Mul<float, false>( | ||
| 612 | + glUbTensor[taskPingPongFlag][rowOffset], | ||
| 613 | + glUbTensor[taskPingPongFlag][rowOffset], | ||
| 614 | + s16UbTensor[rowOffset], | ||
| 615 | + (uint64_t)0, | ||
| 616 | + 1, | ||
| 617 | + AscendC::BinaryRepeatParams( | ||
| 618 | + 1, 1, 1, 8, 8, 8)); | ||
| 619 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 620 | + } | ||
| 621 | + | ||
| 622 | + if (nIdx > 0) { | ||
| 623 | + AscendC::Div<float, false>( | ||
| 624 | + hcUbTensor[rowOffset], | ||
| 625 | + s32UbTensor[rowOffset], | ||
| 626 | + s16UbTensor[rowOffset], | ||
| 627 | + (uint64_t)0, | ||
| 628 | + 1, | ||
| 629 | + AscendC::BinaryRepeatParams( | ||
| 630 | + 1, 1, 1, 8, 8, 8)); | ||
| 631 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 632 | + } | ||
| 633 | + // ci = s32 / s16 | ||
| 634 | + if (nIdx == 0) { | ||
| 635 | + AscendC::Duplicate<float, false>(gcUbTensor[rowOffset], 1.0, (uint64_t)0, 1, 1, 8); | ||
| 636 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 637 | + } | ||
| 638 | + | ||
| 639 | + if (nIdx > 0) { | ||
| 640 | + // eps = ci-1 / ci | ||
| 641 | + AscendC::Div<float, false>( | ||
| 642 | + epsUbTensor[rowOffset], | ||
| 643 | + gcUbTensor[rowOffset], | ||
| 644 | + hcUbTensor[rowOffset], | ||
| 645 | + (uint64_t)0, | ||
| 646 | + 1, | ||
| 647 | + AscendC::BinaryRepeatParams( | ||
| 648 | + 1, 1, 1, 8, 8, 8)); | ||
| 649 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 650 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 651 | + AscendC::DataCopy(gcUbTensor[rowOffset], hcUbTensor[rowOffset], AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | ||
| 652 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 653 | + // eps = eps - 1.0 | ||
| 654 | + SetVecMask(m); | ||
| 655 | + AscendC::Adds<float, false>( | ||
| 656 | + epsUbTensor[rowOffset], | ||
| 657 | + epsUbTensor[rowOffset], | ||
| 658 | + (float)(-1.0f), | ||
| 659 | + (uint64_t)0, | ||
| 660 | + 1, | ||
| 661 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 662 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 663 | + // eps = eps * 1.5 | ||
| 664 | + AscendC::Muls<float, false>( | ||
| 665 | + epsUbTensor[rowOffset], | ||
| 666 | + epsUbTensor[rowOffset], | ||
| 667 | + (float)(1.5f), | ||
| 668 | + (uint64_t)0, | ||
| 669 | + 1, | ||
| 670 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 671 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 672 | + // max((ni - ni-1), -30.0) | ||
| 673 | + AscendC::Maxs<float, false>( | ||
| 674 | + dnUbTensor[rowOffset], | ||
| 675 | + dnUbTensor[rowOffset], | ||
| 676 | + (float)(-30.0f), | ||
| 677 | + (uint64_t)0, | ||
| 678 | + 1, | ||
| 679 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 680 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 681 | + // eps = eps + 10^-6 | ||
| 682 | + AscendC::Adds<float, false>( | ||
| 683 | + epsUbTensor[rowOffset], | ||
| 684 | + epsUbTensor[rowOffset], | ||
| 685 | + (float)(0.000001f), | ||
| 686 | + (uint64_t)0, | ||
| 687 | + 1, | ||
| 688 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 689 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 690 | + // eps + 10^-6 + max((ni - ni-1), -30.0) | ||
| 691 | + AscendC::Add<float, false>( | ||
| 692 | + epsUbTensor[rowOffset], | ||
| 693 | + epsUbTensor[rowOffset], | ||
| 694 | + dnUbTensor[rowOffset], | ||
| 695 | + (uint64_t)0, | ||
| 696 | + 1, | ||
| 697 | + AscendC::BinaryRepeatParams( | ||
| 698 | + 1, 1, 1, 8, 8, 8)); | ||
| 699 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 700 | + // eps = eps * 2e23 | ||
| 701 | + AscendC::Muls<float, false>( | ||
| 702 | + epsUbTensor[rowOffset], | ||
| 703 | + epsUbTensor[rowOffset], | ||
| 704 | + FLOAT_E_SCALAR, | ||
| 705 | + (uint64_t)0, | ||
| 706 | + 1, | ||
| 707 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 708 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 709 | + // N | ||
| 710 | + AscendC::Cast<int32_t, float, false>( | ||
| 711 | + NUbTensor[gSPingPongFlag * UB_FLOAT_LINE_SIZE + rowOffset], epsUbTensor[rowOffset], AscendC::RoundMode::CAST_ROUND, (uint64_t)0, | ||
| 712 | + 1, AscendC::UnaryRepeatParams(1, 1, 8, 8)); | ||
| 713 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 714 | + } | ||
| 715 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 716 | + } | ||
| 717 | + CATLASS_DEVICE | ||
| 718 | + void AmlaAutoadd(AscendC::GlobalTensor<int32_t> gOTmpInt32, | ||
| 719 | + uint32_t subM, uint32_t embed, uint32_t gSPingPongFlag | ||
| 720 | + ) | ||
| 721 | + { | ||
| 722 | + // update OTmp | ||
| 723 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID5); | ||
| 724 | + for (uint32_t i = 0; i < BRCB_SIZE / FLOAT_BLOCK_SIZE; i++){ | ||
| 725 | + AscendC::Brcb( | ||
| 726 | + NBrcbUbTensor.ReinterpretCast<uint32_t>()[i * FLOAT_BLOCK_SIZE], | ||
| 727 | + NUbTensor.ReinterpretCast<uint32_t>()[gSPingPongFlag * UB_FLOAT_LINE_SIZE], | ||
| 728 | + subM / FLOAT_BLOCK_SIZE, | ||
| 729 | + AscendC::BrcbRepeatParams(BRCB_SIZE / FLOAT_BLOCK_SIZE, BRCB_SIZE)); | ||
| 730 | + } | ||
| 731 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 732 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID5); | ||
| 733 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID5); | ||
| 734 | + | ||
| 735 | + Arch::CrossCoreWaitFlag(preAutoAddReady); | ||
| 736 | + | ||
| 737 | + AscendC::SetAtomicAdd<int32_t>(); | ||
| 738 | + | ||
| 739 | + for (uint32_t i = 0; i < embed / BRCB_SIZE; i++) { | ||
| 740 | + AscendC::DataCopy( | ||
| 741 | + gOTmpInt32[i * BRCB_SIZE], | ||
| 742 | + NBrcbUbTensor, | ||
| 743 | + AscendC::DataCopyParams( | ||
| 744 | + subM, BRCB_SIZE / FLOAT_BLOCK_SIZE, 0, (embed - BRCB_SIZE) / FLOAT_BLOCK_SIZE)); | ||
| 745 | + } | ||
| 746 | + | ||
| 747 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID5); | ||
| 748 | + AscendC::SetAtomicNone(); | ||
| 749 | + } | ||
| 750 | + | ||
| 751 | + CATLASS_DEVICE | ||
| 752 | + void operator()(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, | ||
| 753 | + AscendC::GlobalTensor<int32_t> gOTmpInt32, | ||
| 754 | + const LayoutOutput &layoutOutput, const LayoutInput &layoutInput, | ||
| 755 | + const LayoutUpdate &layoutOTmp, | ||
| 756 | + GemmCoord actualBlockShape, | ||
| 757 | + uint32_t nIdx, uint32_t isLastNTile, uint32_t *glFlag, uint32_t taskPingPongFlag, uint32_t gSPingPongFlag) | ||
| 758 | + { | ||
| 759 | + uint32_t cur_head_num = actualBlockShape.m(); | ||
| 760 | + uint32_t qkN = actualBlockShape.n(); | ||
| 761 | + uint32_t embed = actualBlockShape.k(); | ||
| 762 | + uint32_t qkRoundN = layoutInput.stride(0); | ||
| 763 | + | ||
| 764 | + uint32_t pingpongFlag = 0; | ||
| 765 | + | ||
| 766 | + uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | ||
| 767 | + uint32_t subBlockNum = AscendC::GetSubBlockNum(); | ||
| 768 | + | ||
| 769 | + uint32_t subM = (subBlockIdx == 1) ? (cur_head_num - cur_head_num / 2) : cur_head_num / 2; | ||
| 770 | + | ||
| 771 | + uint32_t mEnd = (subM + M_SLICE - 1) / M_SLICE; | ||
| 772 | + | ||
| 773 | + for (uint32_t mInd = 0; mInd < mEnd; mInd++) { | ||
| 774 | + uint32_t rowOffset = mInd * M_SLICE; | ||
| 775 | + uint32_t currM = mInd == mEnd - 1 ? subM - rowOffset : M_SLICE; | ||
| 776 | + uint32_t isLastM = mInd == mEnd - 1 ? 1 : 0; | ||
| 777 | + uint32_t isFirstM = mInd == 0 ? 1 : 0; | ||
| 778 | + uint32_t sUbOffset = pingpongFlag * 8192; | ||
| 779 | + int64_t offsetOutput = rowOffset * qkRoundN; | ||
| 780 | + auto gOutputThisSubBlock = gOutput[offsetOutput]; | ||
| 781 | + int64_t offsetInput = rowOffset * qkRoundN; | ||
| 782 | + auto gInputThisSubBlock = gInput[offsetInput]; | ||
| 783 | + if (mInd == 0) { | ||
| 784 | + Arch::CrossCoreWaitFlag(qkReady); | ||
| 785 | + } | ||
| 786 | + if (currM == 0) { | ||
| 787 | + continue; | ||
| 788 | + } | ||
| 789 | + SubCoreCompute(gOutputThisSubBlock, gInputThisSubBlock, currM, qkN, qkRoundN, pingpongFlag, rowOffset, | ||
| 790 | + sUbOffset, nIdx, isLastNTile, glFlag, taskPingPongFlag, gSPingPongFlag, isLastM, isFirstM); | ||
| 791 | + pingpongFlag = 1 - pingpongFlag; | ||
| 792 | + } | ||
| 793 | + if (nIdx > 0) { | ||
| 794 | + int64_t gmOffsetOTmp = layoutOTmp.GetOffset(MatrixCoord(subM, 0)); | ||
| 795 | + auto gOTmpInt32ThisSubBlock = gOTmpInt32[gmOffsetOTmp]; | ||
| 796 | + AmlaAutoadd(gOTmpInt32, subM, embed, gSPingPongFlag); | ||
| 797 | + } | ||
| 798 | + Arch::CrossCoreSetFlag<0x2, PIPE_MTE3>(softmaxAutoAddReady); | ||
| 799 | + } | ||
| 800 | + | ||
| 801 | +private: | ||
| 802 | + float tor; | ||
| 803 | + uint32_t pingpongFlag = 0; | ||
| 804 | + uint32_t kvSplitCoreNum = 1; | ||
| 805 | + | ||
| 806 | + AscendC::LocalTensor<float> lsUbTensor; | ||
| 807 | + AscendC::LocalTensor<ElementOutput> lpUbTensor; | ||
| 808 | + AscendC::LocalTensor<float> lmUbTensor; | ||
| 809 | + AscendC::LocalTensor<float> hmUbTensor; | ||
| 810 | + AscendC::LocalTensor<float> gmUbTensor[2]; | ||
| 811 | + AscendC::LocalTensor<float> dmUbTensor; | ||
| 812 | + AscendC::LocalTensor<float> llUbTensor; | ||
| 813 | + AscendC::LocalTensor<float> tvUbTensor; | ||
| 814 | + AscendC::LocalTensor<float> glUbTensor[2]; | ||
| 815 | + | ||
| 816 | + // new add | ||
| 817 | + AscendC::LocalTensor<float> hnUbTensor; | ||
| 818 | + AscendC::LocalTensor<float> dnUbTensor; | ||
| 819 | + AscendC::LocalTensor<float> gnUbTensor; | ||
| 820 | + AscendC::LocalTensor<float> s32UbTensor; | ||
| 821 | + AscendC::LocalTensor<ElementOutput> s16UbTensorTmp; | ||
| 822 | + AscendC::LocalTensor<float> s16UbTensor; | ||
| 823 | + AscendC::LocalTensor<float> hcUbTensor; | ||
| 824 | + AscendC::LocalTensor<float> gcUbTensor; | ||
| 825 | + AscendC::LocalTensor<float> epsUbTensor; | ||
| 826 | + AscendC::LocalTensor<int32_t> NUbTensor; | ||
| 827 | + AscendC::LocalTensor<int32_t> NBrcbUbTensor; | ||
| 828 | + Arch::CrossCoreFlag preAutoAddReady{PRE_AUTOADD_READY_ID}; | ||
| 829 | + Arch::CrossCoreFlag softmaxAutoAddReady{SM_AUTOADD_READY_ID}; | ||
| 830 | + | ||
| 831 | + Arch::CrossCoreFlag qkReady{QK_READY_ID}; | ||
| 832 | + Arch::CrossCoreFlag softmaxReady{SOFTMAX_READY_ID}; | ||
| 833 | + | ||
| 834 | +}; | ||
| 835 | + | ||
| 836 | +} // namespace Catlass::Epilogue::Block | ||
| 837 | + | ||
| 838 | + | ||
| @@ -46,9 +46,9 @@ public: | |||
| 46 | static constexpr uint32_t STAGES = 2; | 46 | static constexpr uint32_t STAGES = 2; |
| 47 | 47 | ||
| 48 | CATLASS_DEVICE | 48 | CATLASS_DEVICE |
| 49 | - BlockEpilogue(Arch::Resource<ArchTag> &resource, uint32_t kvSplitCoreNum_) | 49 | + BlockEpilogue(Arch::Resource<ArchTag> &resource, uint32_t maxKvSplitCoreNum_) |
| 50 | { | 50 | { |
| 51 | - kvSplitCoreNum = kvSplitCoreNum_; | 51 | + maxKvSplitCoreNum = maxKvSplitCoreNum_; |
| 52 | 52 | ||
| 53 | uint32_t ubOffset = 0; | 53 | uint32_t ubOffset = 0; |
| 54 | oIn[0] = resource.ubBuf.template GetBufferByByte<float>(ubOffset); | 54 | oIn[0] = resource.ubBuf.template GetBufferByByte<float>(ubOffset); |
| @@ -112,7 +112,7 @@ public: | |||
| 112 | AscendC::GlobalTensor<ElementOutput> gOutput, | 112 | AscendC::GlobalTensor<ElementOutput> gOutput, |
| 113 | AscendC::GlobalTensor<ElementInput> gOCoreTmp, | 113 | AscendC::GlobalTensor<ElementInput> gOCoreTmp, |
| 114 | AscendC::GlobalTensor<ElementInput> gl, | 114 | AscendC::GlobalTensor<ElementInput> gl, |
| 115 | - uint32_t actualHeads, uint32_t headsProcess, uint32_t headSize) | 115 | + uint32_t actualHeads, uint32_t headsProcess, uint32_t headSize, uint32_t kvSplitCoreNum) |
| 116 | { | 116 | { |
| 117 | uint32_t kvSplitRound = (kvSplitCoreNum + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE * FLOAT_BLOCK_SIZE; | 117 | uint32_t kvSplitRound = (kvSplitCoreNum + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE * FLOAT_BLOCK_SIZE; |
| 118 | 118 | ||
| @@ -120,7 +120,7 @@ public: | |||
| 120 | AscendC::DataCopyPad( | 120 | AscendC::DataCopyPad( |
| 121 | lIn, gl, | 121 | lIn, gl, |
| 122 | AscendC::DataCopyExtParams( | 122 | AscendC::DataCopyExtParams( |
| 123 | - actualHeads, kvSplitCoreNum * sizeof(ElementInput), 0, | 123 | + actualHeads, kvSplitCoreNum * sizeof(ElementInput), (maxKvSplitCoreNum - kvSplitCoreNum) * sizeof(ElementInput), |
| 124 | (KV_SPLIT_MAX - kvSplitCoreNum) / FLOAT_BLOCK_SIZE, 0), | 124 | (KV_SPLIT_MAX - kvSplitCoreNum) / FLOAT_BLOCK_SIZE, 0), |
| 125 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); | 125 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); |
| 126 | 126 | ||
| @@ -205,7 +205,7 @@ public: | |||
| 205 | oIn[0], gOCoreTmp, | 205 | oIn[0], gOCoreTmp, |
| 206 | AscendC::DataCopyExtParams( | 206 | AscendC::DataCopyExtParams( |
| 207 | actualHeads, headSize * sizeof(ElementInput), | 207 | actualHeads, headSize * sizeof(ElementInput), |
| 208 | - (kvSplitCoreNum * headSize - headSize) * sizeof(ElementInput), 0, 0), | 208 | + (maxKvSplitCoreNum * headSize - headSize) * sizeof(ElementInput), 0, 0), |
| 209 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); | 209 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); |
| 210 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | 210 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); |
| 211 | 211 | ||
| @@ -223,7 +223,7 @@ public: | |||
| 223 | oIn[nextBufferId], gOCoreTmp[(i + 1) * headSize], | 223 | oIn[nextBufferId], gOCoreTmp[(i + 1) * headSize], |
| 224 | AscendC::DataCopyExtParams( | 224 | AscendC::DataCopyExtParams( |
| 225 | actualHeads, headSize * sizeof(ElementInput), | 225 | actualHeads, headSize * sizeof(ElementInput), |
| 226 | - (kvSplitCoreNum * headSize - headSize) * sizeof(ElementInput), 0, 0), | 226 | + (maxKvSplitCoreNum * headSize - headSize) * sizeof(ElementInput), 0, 0), |
| 227 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); | 227 | AscendC::DataCopyPadExtParams<ElementInput>(false, 0, 0, 0)); |
| 228 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(oInEventList[nextBufferId]); | 228 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(oInEventList[nextBufferId]); |
| 229 | } | 229 | } |
| @@ -289,7 +289,7 @@ public: | |||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | private: | 291 | private: |
| 292 | - uint32_t kvSplitCoreNum = 1; | 292 | + uint32_t maxKvSplitCoreNum = 1; |
| 293 | AscendC::LocalTensor<ElementOutput> out; | 293 | AscendC::LocalTensor<ElementOutput> out; |
| 294 | AscendC::LocalTensor<float> oIn[STAGES]; | 294 | AscendC::LocalTensor<float> oIn[STAGES]; |
| 295 | AscendC::LocalTensor<float> oTemp[STAGES]; | 295 | AscendC::LocalTensor<float> oTemp[STAGES]; |
| @@ -80,7 +80,8 @@ public: | |||
| 80 | goUbTensor32 = resource.ubBuf.template GetBufferByByte<float>(GO_UB_TENSOR_OFFSET); | 80 | goUbTensor32 = resource.ubBuf.template GetBufferByByte<float>(GO_UB_TENSOR_OFFSET); |
| 81 | goUbTensor16 = resource.ubBuf.template GetBufferByByte<ElementOutput>(GO_UB_TENSOR_OFFSET); | 81 | goUbTensor16 = resource.ubBuf.template GetBufferByByte<ElementOutput>(GO_UB_TENSOR_OFFSET); |
| 82 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | 82 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); |
| 83 | - gmUbTensor = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | 83 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); |
| 84 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | CATLASS_DEVICE | 87 | CATLASS_DEVICE |
| @@ -125,7 +126,7 @@ public: | |||
| 125 | uint32_t epiTokenNum, | 126 | uint32_t epiTokenNum, |
| 126 | uint32_t integralHeadNum, | 127 | uint32_t integralHeadNum, |
| 127 | uint32_t rescaleOPingPongFlag, | 128 | uint32_t rescaleOPingPongFlag, |
| 128 | - uint32_t &glFlag) | 129 | + uint32_t *glFlag, uint32_t taskPingPongFlag) |
| 129 | { | 130 | { |
| 130 | uint32_t curRowNum = layoutInput.shape(0); | 131 | uint32_t curRowNum = layoutInput.shape(0); |
| 131 | uint32_t embed = layoutInput.shape(1); | 132 | uint32_t embed = layoutInput.shape(1); |
| @@ -139,6 +140,8 @@ public: | |||
| 139 | uint64_t llUbOffsetCurCycle = (uint64_t)(rescaleOPingPongFlag * HALF_LL_UB_SIZE + | 140 | uint64_t llUbOffsetCurCycle = (uint64_t)(rescaleOPingPongFlag * HALF_LL_UB_SIZE + |
| 140 | rowLoopIdx * ROW_WISE_CYCLE_TILE); | 141 | rowLoopIdx * ROW_WISE_CYCLE_TILE); |
| 141 | uint32_t oUbOffset = oPingPangFlag * ROW_WISE_CYCLE_TILE * embedRound; | 142 | uint32_t oUbOffset = oPingPangFlag * ROW_WISE_CYCLE_TILE * embedRound; |
| 143 | + uint32_t qHeads = strideQO / embed; | ||
| 144 | + | ||
| 142 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(oPingPangFlag); | 145 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(oPingPangFlag); |
| 143 | if ((nIdx - 1) != 0) { | 146 | if ((nIdx - 1) != 0) { |
| 144 | AscendC::DataCopy( | 147 | AscendC::DataCopy( |
| @@ -298,7 +301,7 @@ public: | |||
| 298 | AscendC::PipeBarrier<PIPE_V>(); | 301 | AscendC::PipeBarrier<PIPE_V>(); |
| 299 | AscendC::Brcb( | 302 | AscendC::Brcb( |
| 300 | hmUbTensor.ReinterpretCast<uint32_t>(), | 303 | hmUbTensor.ReinterpretCast<uint32_t>(), |
| 301 | - gmUbTensor.ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], | 304 | + gmUbTensor[taskPingPongFlag].ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], |
| 302 | curRowNumRound / FLOAT_BLOCK_SIZE, | 305 | curRowNumRound / FLOAT_BLOCK_SIZE, |
| 303 | AscendC::BrcbRepeatParams(1, 8)); | 306 | AscendC::BrcbRepeatParams(1, 8)); |
| 304 | AscendC::PipeBarrier<PIPE_V>(); | 307 | AscendC::PipeBarrier<PIPE_V>(); |
| @@ -314,18 +317,76 @@ public: | |||
| 314 | 317 | ||
| 315 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); | 318 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); |
| 316 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); | 319 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); |
| 317 | - AscendC::DataCopyPad(gl, tvUbTensor, | ||
| 318 | - AscendC::DataCopyExtParams(curRowNum, 4, 0, (kvSplitCoreNum - 1) * 4, 0)); | ||
| 319 | 320 | ||
| 320 | - if (glFlag == 0) { | 321 | + if (tokenNumPerHead == 1) { |
| 321 | - AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | 322 | + AscendC::DataCopyPad(gl, tvUbTensor, |
| 322 | - glFlag = 1; | 323 | + AscendC::DataCopyExtParams(curRowNum, 4, 0, (kvSplitCoreNum - 1) * 4, 0)); |
| 324 | + } else { | ||
| 325 | + uint32_t innerOGmOffset = 0; | ||
| 326 | + uint32_t inner_go_ubuf_offset = 0; | ||
| 327 | + if (proTokenNum != 0) { | ||
| 328 | + AscendC::DataCopyPad(gl[innerOGmOffset + proTokenIdx * kvSplitCoreNum * qHeads], | ||
| 329 | + tvUbTensor[inner_go_ubuf_offset], | ||
| 330 | + AscendC::DataCopyExtParams(proTokenNum, | ||
| 331 | + 4, 0, (kvSplitCoreNum * qHeads - 1) * 4, 0)); | ||
| 332 | + innerOGmOffset += kvSplitCoreNum; | ||
| 333 | + inner_go_ubuf_offset += proTokenNum * FLOAT_BLOCK_SIZE; | ||
| 334 | + } | ||
| 335 | + for (uint32_t qN_idx = 0; qN_idx < integralHeadNum; qN_idx++) { | ||
| 336 | + AscendC::DataCopyPad(gl[innerOGmOffset], | ||
| 337 | + tvUbTensor[inner_go_ubuf_offset], | ||
| 338 | + AscendC::DataCopyExtParams(tokenNumPerHead, | ||
| 339 | + 4, 0, (kvSplitCoreNum * qHeads - 1) * 4, 0)); | ||
| 340 | + innerOGmOffset += kvSplitCoreNum; | ||
| 341 | + inner_go_ubuf_offset += tokenNumPerHead * FLOAT_BLOCK_SIZE; | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + if (epiTokenNum != 0) { | ||
| 345 | + AscendC::DataCopyPad(gl[innerOGmOffset], | ||
| 346 | + tvUbTensor[inner_go_ubuf_offset], | ||
| 347 | + AscendC::DataCopyExtParams(epiTokenNum, | ||
| 348 | + 4, 0, (kvSplitCoreNum * qHeads - 1) * 4, 0)); | ||
| 349 | + } | ||
| 350 | + } | ||
| 351 | + | ||
| 352 | + if (glFlag[taskPingPongFlag] == 0) { | ||
| 353 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(taskPingPongFlag + 2); | ||
| 354 | + glFlag[taskPingPongFlag] = 1; | ||
| 323 | } | 355 | } |
| 324 | uint32_t srcGap = ((embed % 16 <= 8) && (embed % 16 > 0)) ? 1 : 0; | 356 | uint32_t srcGap = ((embed % 16 <= 8) && (embed % 16 > 0)) ? 1 : 0; |
| 325 | - AscendC::DataCopyPad(gOCoreTmp, goUbTensor32[oUbOffset], | 357 | + |
| 326 | - AscendC::DataCopyExtParams(curRowNum, embed * 4, srcGap, (kvSplitCoreNum - 1) * embed * 4, 0)); | 358 | + if (tokenNumPerHead == 1) { |
| 327 | - AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | 359 | + AscendC::DataCopyPad(gOCoreTmp, goUbTensor32[oUbOffset], |
| 328 | - AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | 360 | + AscendC::DataCopyExtParams(curRowNum, embed * 4, srcGap, (kvSplitCoreNum - 1) * embed * 4, 0)); |
| 361 | + } else { | ||
| 362 | + uint32_t innerOGmOffset = 0; | ||
| 363 | + uint32_t inner_go_ubuf_offset = oUbOffset; | ||
| 364 | + if (proTokenNum != 0) { | ||
| 365 | + AscendC::DataCopyPad(gOCoreTmp[innerOGmOffset + proTokenIdx * kvSplitCoreNum * strideQO], | ||
| 366 | + goUbTensor32[inner_go_ubuf_offset], | ||
| 367 | + AscendC::DataCopyExtParams(proTokenNum, | ||
| 368 | + embed * 4, 0, (kvSplitCoreNum * strideQO - embed) * 4, 0)); | ||
| 369 | + innerOGmOffset += embed * kvSplitCoreNum; | ||
| 370 | + inner_go_ubuf_offset += proTokenNum * embed; | ||
| 371 | + } | ||
| 372 | + for (uint32_t qN_idx = 0; qN_idx < integralHeadNum; qN_idx++) { | ||
| 373 | + AscendC::DataCopyPad(gOCoreTmp[innerOGmOffset], | ||
| 374 | + goUbTensor32[inner_go_ubuf_offset], | ||
| 375 | + AscendC::DataCopyExtParams(tokenNumPerHead, | ||
| 376 | + embed * 4, 0, (kvSplitCoreNum * strideQO - embed) * 4, 0)); | ||
| 377 | + innerOGmOffset += embed * kvSplitCoreNum; | ||
| 378 | + inner_go_ubuf_offset += tokenNumPerHead * embed; | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + if (epiTokenNum != 0) { | ||
| 382 | + AscendC::DataCopyPad(gOCoreTmp[innerOGmOffset], | ||
| 383 | + goUbTensor32[inner_go_ubuf_offset], | ||
| 384 | + AscendC::DataCopyExtParams(epiTokenNum, | ||
| 385 | + embed * 4, 0, (kvSplitCoreNum * strideQO - embed) * 4, 0)); | ||
| 386 | + } | ||
| 387 | + } | ||
| 388 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID4); | ||
| 389 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID4); | ||
| 329 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | 390 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); |
| 330 | AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | 391 | AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); |
| 331 | } else { | 392 | } else { |
| @@ -406,7 +467,7 @@ public: | |||
| 406 | uint32_t isLastNTile, | 467 | uint32_t isLastNTile, |
| 407 | uint32_t curHeadNum, | 468 | uint32_t curHeadNum, |
| 408 | uint32_t rescaleOPingPongFlag, | 469 | uint32_t rescaleOPingPongFlag, |
| 409 | - uint32_t &glFlag) | 470 | + uint32_t *glFlag, uint32_t taskPingPongFlag) |
| 410 | { | 471 | { |
| 411 | uint32_t tokenNumPerHead = layoutOutput.shape(0); | 472 | uint32_t tokenNumPerHead = layoutOutput.shape(0); |
| 412 | uint32_t embed = layoutInput.shape(1); | 473 | uint32_t embed = layoutInput.shape(1); |
| @@ -450,12 +511,13 @@ public: | |||
| 450 | proTokenNum = (tokenNumPerHead - epiTokenNum) % tokenNumPerHead; | 511 | proTokenNum = (tokenNumPerHead - epiTokenNum) % tokenNumPerHead; |
| 451 | integralHeadNum = (rowActualCurCycle - proTokenNum) / tokenNumPerHead; | 512 | integralHeadNum = (rowActualCurCycle - proTokenNum) / tokenNumPerHead; |
| 452 | epiTokenNum = rowActualCurCycle - proTokenNum - integralHeadNum * tokenNumPerHead; | 513 | epiTokenNum = rowActualCurCycle - proTokenNum - integralHeadNum * tokenNumPerHead; |
| 514 | + int64_t headIdx = rowOffsetLoop / tokenNumPerHead; | ||
| 453 | SubCoreCompute(gInputThisCurCycle, gUpdateCurCycle, gOutputCurCycle, | 515 | SubCoreCompute(gInputThisCurCycle, gUpdateCurCycle, gOutputCurCycle, |
| 454 | - gOCoreTmp[rowOffsetLoop * embed * kvSplitCoreNum], | 516 | + gOCoreTmp[headIdx * kvSplitCoreNum * embed], |
| 455 | - gl[rowOffsetLoop * kvSplitCoreNum], | 517 | + gl[headIdx * kvSplitCoreNum], |
| 456 | layoutInputCurCycle, layoutOutputCurCycle, layoutUpdateCurCycle, | 518 | layoutInputCurCycle, layoutOutputCurCycle, layoutUpdateCurCycle, |
| 457 | nIdx, isLastNTile, needRowLoop, rowLoopIdx, | 519 | nIdx, isLastNTile, needRowLoop, rowLoopIdx, |
| 458 | - proTokenIdx, proTokenNum, epiTokenNum, integralHeadNum, rescaleOPingPongFlag, glFlag); | 520 | + proTokenIdx, proTokenNum, epiTokenNum, integralHeadNum, rescaleOPingPongFlag, glFlag, taskPingPongFlag); |
| 459 | } | 521 | } |
| 460 | } | 522 | } |
| 461 | } | 523 | } |
| @@ -471,7 +533,7 @@ private: | |||
| 471 | AscendC::LocalTensor<float> tvUbTensor; | 533 | AscendC::LocalTensor<float> tvUbTensor; |
| 472 | AscendC::LocalTensor<float> goUbTensor32; | 534 | AscendC::LocalTensor<float> goUbTensor32; |
| 473 | AscendC::LocalTensor<float> hmUbTensor; | 535 | AscendC::LocalTensor<float> hmUbTensor; |
| 474 | - AscendC::LocalTensor<float> gmUbTensor; | 536 | + AscendC::LocalTensor<float> gmUbTensor[2]; |
| 475 | }; | 537 | }; |
| 476 | 538 | ||
| 477 | } // namespace Catlass::Epilogue::Block | 539 | } // namespace Catlass::Epilogue::Block |
| @@ -64,13 +64,15 @@ public: | |||
| 64 | static constexpr uint32_t HALF_DM_UB_SIZE = 128; | 64 | static constexpr uint32_t HALF_DM_UB_SIZE = 128; |
| 65 | static constexpr uint32_t VECTOR_SIZE = 128; | 65 | static constexpr uint32_t VECTOR_SIZE = 128; |
| 66 | static constexpr uint32_t HALF_LL_UB_SIZE = 256; | 66 | static constexpr uint32_t HALF_LL_UB_SIZE = 256; |
| 67 | + static constexpr uint32_t REDUCE_UB_SIZE = 1024; | ||
| 67 | 68 | ||
| 68 | CATLASS_DEVICE | 69 | CATLASS_DEVICE |
| 69 | BlockEpilogue(Arch::Resource<ArchTag> &resource, half tor_, uint32_t kvSplitCoreNum_) | 70 | BlockEpilogue(Arch::Resource<ArchTag> &resource, half tor_, uint32_t kvSplitCoreNum_) |
| 70 | { | 71 | { |
| 71 | // Allocate UB space | 72 | // Allocate UB space |
| 72 | constexpr uint32_t LS_UB_TENSOR_OFFSET = 0; | 73 | constexpr uint32_t LS_UB_TENSOR_OFFSET = 0; |
| 73 | - constexpr uint32_t LP_UB_TENSOR_OFFSET = 2 * UB_UINT8_BLOCK_SIZE_MLA; | 74 | + constexpr uint32_t LP_UB_TENSOR_OFFSET = 0; |
| 75 | + // constexpr uint32_t LP_UB_TENSOR_OFFSET = 2 * UB_UINT8_BLOCK_SIZE_MLA; | ||
| 74 | constexpr uint32_t LM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA; | 76 | constexpr uint32_t LM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA; |
| 75 | constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; | 77 | constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; |
| 76 | constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 6 * UB_UINT8_LINE_SIZE; | 78 | constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 6 * UB_UINT8_LINE_SIZE; |
| @@ -85,7 +87,8 @@ public: | |||
| 85 | lsUbTensor = resource.ubBuf.template GetBufferByByte<float>(LS_UB_TENSOR_OFFSET); | 87 | lsUbTensor = resource.ubBuf.template GetBufferByByte<float>(LS_UB_TENSOR_OFFSET); |
| 86 | lmUbTensor = resource.ubBuf.template GetBufferByByte<float>(LM_UB_TENSOR_OFFSET); | 88 | lmUbTensor = resource.ubBuf.template GetBufferByByte<float>(LM_UB_TENSOR_OFFSET); |
| 87 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | 89 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); |
| 88 | - gmUbTensor = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | 90 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); |
| 91 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 89 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); | 92 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); |
| 90 | llUbTensor = resource.ubBuf.template GetBufferByByte<float>(LL_UB_TENSOR_OFFSET); | 93 | llUbTensor = resource.ubBuf.template GetBufferByByte<float>(LL_UB_TENSOR_OFFSET); |
| 91 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); | 94 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); |
| @@ -96,6 +99,38 @@ public: | |||
| 96 | { | 99 | { |
| 97 | } | 100 | } |
| 98 | 101 | ||
| 102 | + CATLASS_DEVICE | ||
| 103 | + void SetVecMask(int32_t len) | ||
| 104 | + { | ||
| 105 | + uint64_t mask = 0; | ||
| 106 | + uint64_t one = 1; | ||
| 107 | + uint64_t temp = len % FLOAT_VECTOR_SIZE; | ||
| 108 | + for (int64_t i = 0; i < temp; i++) { | ||
| 109 | + mask |= one << i; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + if (len == VECTOR_SIZE || len == 0) { | ||
| 113 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 114 | + } else if (len >= FLOAT_VECTOR_SIZE) { | ||
| 115 | + AscendC::SetVectorMask<int8_t>(mask, (uint64_t)-1); | ||
| 116 | + } else { | ||
| 117 | + AscendC::SetVectorMask<int8_t>(0x0, mask); | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + CATLASS_DEVICE | ||
| 122 | + void SetBlockReduceMask(int32_t len) | ||
| 123 | + { | ||
| 124 | + if (len > 8 || len < 1) { | ||
| 125 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 126 | + return; | ||
| 127 | + } | ||
| 128 | + uint64_t subMask = ((uint64_t)1 << len) - 1; | ||
| 129 | + uint64_t maskValue = (subMask << 48) + (subMask << 32) + (subMask << 16) + subMask + (subMask << 56) + | ||
| 130 | + (subMask << 40) + (subMask << 24) + (subMask << 8); | ||
| 131 | + AscendC::SetVectorMask<int8_t>(maskValue, maskValue); | ||
| 132 | + } | ||
| 133 | + | ||
| 99 | CATLASS_DEVICE | 134 | CATLASS_DEVICE |
| 100 | void SetMask(int32_t len) | 135 | void SetMask(int32_t len) |
| 101 | { | 136 | { |
| @@ -196,6 +231,59 @@ public: | |||
| 196 | AscendC::PipeBarrier<PIPE_V>(); | 231 | AscendC::PipeBarrier<PIPE_V>(); |
| 197 | } | 232 | } |
| 198 | 233 | ||
| 234 | + CATLASS_DEVICE | ||
| 235 | + void RowsumTAILTILE(const AscendC::LocalTensor<float> &srcUb, const AscendC::LocalTensor<float> &rowsumUb, | ||
| 236 | + const AscendC::LocalTensor<float> &tvUbTensor, uint32_t numRowsRound, uint32_t numElems, | ||
| 237 | + uint32_t numElemsAligned) | ||
| 238 | + { | ||
| 239 | + if (numElems >= FLOAT_VECTOR_SIZE) { | ||
| 240 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb, numRowsRound, 0, 1, 1, | ||
| 241 | + numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 242 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 243 | + AscendC::BlockReduceSum<float, false>( | ||
| 244 | + rowsumUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, | ||
| 245 | + 1, 1, 8); | ||
| 246 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 247 | + for (uint64_t rowSumIdx = 1; rowSumIdx < (uint64_t)numElems / FLOAT_VECTOR_SIZE; ++rowSumIdx) { | ||
| 248 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb[rowSumIdx * FLOAT_VECTOR_SIZE], numRowsRound, 0, | ||
| 249 | + 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 250 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 251 | + AscendC::BlockReduceSum<float, false>( | ||
| 252 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 253 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 254 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 255 | + SetVecMask(numRowsRound); | ||
| 256 | + AscendC::Add<float, false>(rowsumUb, rowsumUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 257 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 258 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 259 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 260 | + } | ||
| 261 | + } | ||
| 262 | + if (numElems % FLOAT_VECTOR_SIZE > 0) { | ||
| 263 | + SetVecMask(numElems % FLOAT_VECTOR_SIZE); | ||
| 264 | + AscendC::BlockReduceSum<float, false>(tvUbTensor, srcUb[numElems / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 265 | + numRowsRound, 0, 1, 1, numElemsAligned / FLOAT_BLOCK_SIZE); | ||
| 266 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 267 | + SetBlockReduceMask((numElems % FLOAT_VECTOR_SIZE + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE); | ||
| 268 | + if (numElems < FLOAT_VECTOR_SIZE) { | ||
| 269 | + AscendC::BlockReduceSum<float, false>( | ||
| 270 | + rowsumUb, tvUbTensor, (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | ||
| 271 | + 0, 1, 1, 8); | ||
| 272 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 273 | + } else { | ||
| 274 | + AscendC::BlockReduceSum<float, false>( | ||
| 275 | + tvUbTensor[REDUCE_UB_SIZE], tvUbTensor, | ||
| 276 | + (numRowsRound * FLOAT_BLOCK_SIZE + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, 0, 1, 1, 8); | ||
| 277 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 278 | + SetVecMask(numRowsRound); | ||
| 279 | + AscendC::Add<float, false>(rowsumUb, rowsumUb, tvUbTensor[REDUCE_UB_SIZE], (uint64_t)0, 1, | ||
| 280 | + AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | ||
| 281 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 282 | + } | ||
| 283 | + AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 284 | + } | ||
| 285 | + } | ||
| 286 | + | ||
| 199 | CATLASS_DEVICE | 287 | CATLASS_DEVICE |
| 200 | void ReduceMaxRepeatM( | 288 | void ReduceMaxRepeatM( |
| 201 | const AscendC::LocalTensor<float> &dst, | 289 | const AscendC::LocalTensor<float> &dst, |
| @@ -253,7 +341,7 @@ public: | |||
| 253 | const LayoutInput &layoutInput, | 341 | const LayoutInput &layoutInput, |
| 254 | uint32_t nIdx, | 342 | uint32_t nIdx, |
| 255 | uint32_t softmaxPingPongFlag, | 343 | uint32_t softmaxPingPongFlag, |
| 256 | - uint32_t &glFlag) | 344 | + uint32_t *glFlag, uint32_t taskPingPongFlag, uint32_t sUbOffset) |
| 257 | { | 345 | { |
| 258 | uint32_t curRowNum = layoutInput.shape(0); | 346 | uint32_t curRowNum = layoutInput.shape(0); |
| 259 | uint32_t kSeqTile = layoutInput.shape(1); | 347 | uint32_t kSeqTile = layoutInput.shape(1); |
| @@ -262,45 +350,27 @@ public: | |||
| 262 | uint32_t sub_m_d64 = (curRowNum + 63) / 64; // up aligned to 128 | 350 | uint32_t sub_m_d64 = (curRowNum + 63) / 64; // up aligned to 128 |
| 263 | uint64_t dmUbOffsetCurCycle = (uint64_t)(softmaxPingPongFlag * HALF_DM_UB_SIZE); | 351 | uint64_t dmUbOffsetCurCycle = (uint64_t)(softmaxPingPongFlag * HALF_DM_UB_SIZE); |
| 264 | uint64_t llUbOffsetCurCycle = (uint64_t)(softmaxPingPongFlag * HALF_LL_UB_SIZE); | 352 | uint64_t llUbOffsetCurCycle = (uint64_t)(softmaxPingPongFlag * HALF_LL_UB_SIZE); |
| 265 | - AscendC::WaitFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID2); | 353 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(softmaxPingPongFlag + 6); |
| 266 | - AscendC::DataCopy(lsUbTensor, gInput, | 354 | + AscendC::DataCopy(lsUbTensor[sUbOffset], gInput, |
| 267 | AscendC::DataCopyParams(1, curRowNum * kSeqTileRound / FLOAT_BLOCK_SIZE, 0, 0)); | 355 | AscendC::DataCopyParams(1, curRowNum * kSeqTileRound / FLOAT_BLOCK_SIZE, 0, 0)); |
| 268 | 356 | ||
| 269 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | 357 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); |
| 270 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | 358 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); |
| 271 | 359 | ||
| 272 | // muls scale_value | 360 | // muls scale_value |
| 273 | - for (uint32_t mulsIdx = 0; mulsIdx < kSeqTile / FLOAT_VECTOR_SIZE; ++mulsIdx) { | 361 | + AscendC::Muls<float, false>(lsUbTensor[sUbOffset], lsUbTensor[sUbOffset], tor, (uint64_t)0, |
| 274 | - AscendC::Muls<float, false>( | 362 | + (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, |
| 275 | - lsUbTensor[mulsIdx * FLOAT_VECTOR_SIZE], | 363 | + AscendC::UnaryRepeatParams(1, 1, 8, 8)); |
| 276 | - lsUbTensor[mulsIdx * FLOAT_VECTOR_SIZE], | ||
| 277 | - tor, | ||
| 278 | - (uint64_t)0, | ||
| 279 | - curRowNum, | ||
| 280 | - AscendC::UnaryRepeatParams(1, 1, kSeqTileRound / FLOAT_BLOCK_SIZE, kSeqTileRound / FLOAT_BLOCK_SIZE)); | ||
| 281 | - } | ||
| 282 | - if (kSeqTile % FLOAT_VECTOR_SIZE > 0) { | ||
| 283 | - SetMask(kSeqTile % FLOAT_VECTOR_SIZE); | ||
| 284 | - AscendC::Muls<float, false>( | ||
| 285 | - lsUbTensor[kSeqTile / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 286 | - lsUbTensor[kSeqTile / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], | ||
| 287 | - tor, | ||
| 288 | - (uint64_t)0, | ||
| 289 | - curRowNum, | ||
| 290 | - AscendC::UnaryRepeatParams(1, 1, kSeqTileRound / FLOAT_BLOCK_SIZE, kSeqTileRound / FLOAT_BLOCK_SIZE)); | ||
| 291 | - | ||
| 292 | - AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | ||
| 293 | - } | ||
| 294 | AscendC::PipeBarrier<PIPE_V>(); | 364 | AscendC::PipeBarrier<PIPE_V>(); |
| 295 | 365 | ||
| 296 | // *** lm = rowmax(ls) | 366 | // *** lm = rowmax(ls) |
| 297 | - ReduceMaxRepeatM(lmUbTensor, lsUbTensor, lpUbTensor32, curRowNum, kSeqTile, kSeqTileRound); | 367 | + ReduceMaxRepeatM(lmUbTensor, lsUbTensor[sUbOffset], tvUbTensor, curRowNum, kSeqTile, kSeqTileRound); |
| 298 | 368 | ||
| 299 | if (nIdx != 0) { | 369 | if (nIdx != 0) { |
| 300 | AscendC::Max<float, false>( | 370 | AscendC::Max<float, false>( |
| 301 | hmUbTensor, | 371 | hmUbTensor, |
| 302 | lmUbTensor, | 372 | lmUbTensor, |
| 303 | - gmUbTensor, | 373 | + gmUbTensor[taskPingPongFlag], |
| 304 | (uint64_t)0, | 374 | (uint64_t)0, |
| 305 | sub_m_d64, | 375 | sub_m_d64, |
| 306 | AscendC::BinaryRepeatParams( | 376 | AscendC::BinaryRepeatParams( |
| @@ -308,7 +378,7 @@ public: | |||
| 308 | AscendC::PipeBarrier<PIPE_V>(); | 378 | AscendC::PipeBarrier<PIPE_V>(); |
| 309 | AscendC::Sub<float, false>( | 379 | AscendC::Sub<float, false>( |
| 310 | dmUbTensor[dmUbOffsetCurCycle], | 380 | dmUbTensor[dmUbOffsetCurCycle], |
| 311 | - gmUbTensor, | 381 | + gmUbTensor[taskPingPongFlag], |
| 312 | hmUbTensor, | 382 | hmUbTensor, |
| 313 | (uint64_t)0, | 383 | (uint64_t)0, |
| 314 | sub_m_d64, | 384 | sub_m_d64, |
| @@ -320,44 +390,45 @@ public: | |||
| 320 | AscendC::PipeBarrier<PIPE_V>(); | 390 | AscendC::PipeBarrier<PIPE_V>(); |
| 321 | } | 391 | } |
| 322 | // *** gm = hm | 392 | // *** gm = hm |
| 323 | - AscendC::DataCopy(gmUbTensor, hmUbTensor, AscendC::DataCopyParams(1, subMRound / FLOAT_BLOCK_SIZE, 0, 0)); | 393 | + AscendC::DataCopy(gmUbTensor[taskPingPongFlag], hmUbTensor, AscendC::DataCopyParams(1, subMRound / FLOAT_BLOCK_SIZE, 0, 0)); |
| 324 | AscendC::PipeBarrier<PIPE_V>(); | 394 | AscendC::PipeBarrier<PIPE_V>(); |
| 325 | 395 | ||
| 326 | if (kvSplitCoreNum != 1) { | 396 | if (kvSplitCoreNum != 1) { |
| 327 | if (nIdx == 0) { | 397 | if (nIdx == 0) { |
| 328 | - if (glFlag == 1) { | 398 | + if (glFlag[taskPingPongFlag] == 1) { |
| 329 | - AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | 399 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(taskPingPongFlag + 2); |
| 330 | - glFlag = 0; | 400 | + glFlag[taskPingPongFlag] = 0; |
| 331 | } | 401 | } |
| 332 | } | 402 | } |
| 333 | } | 403 | } |
| 334 | 404 | ||
| 335 | // *** ls = ls - hm_block | 405 | // *** ls = ls - hm_block |
| 336 | - TensorSubValueRepeatM(lsUbTensor, lsUbTensor, | 406 | + TensorSubValueRepeatM(lsUbTensor[sUbOffset], lsUbTensor[sUbOffset], |
| 337 | hmUbTensor, tvUbTensor, | 407 | hmUbTensor, tvUbTensor, |
| 338 | curRowNum, subMRound, kSeqTile, kSeqTileRound); | 408 | curRowNum, subMRound, kSeqTile, kSeqTileRound); |
| 339 | 409 | ||
| 340 | AscendC::Exp<float, false>( | 410 | AscendC::Exp<float, false>( |
| 341 | - lsUbTensor, | 411 | + lsUbTensor[sUbOffset], |
| 342 | - lsUbTensor, | 412 | + lsUbTensor[sUbOffset], |
| 343 | (uint64_t)0, | 413 | (uint64_t)0, |
| 344 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | 414 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, |
| 345 | AscendC::UnaryRepeatParams(1, 1, 8, 8)); | 415 | AscendC::UnaryRepeatParams(1, 1, 8, 8)); |
| 346 | 416 | ||
| 347 | AscendC::PipeBarrier<PIPE_V>(); | 417 | AscendC::PipeBarrier<PIPE_V>(); |
| 418 | + RowsumTAILTILE(lsUbTensor[sUbOffset], llUbTensor[llUbOffsetCurCycle], tvUbTensor, curRowNum, kSeqTile, kSeqTileRound); | ||
| 419 | + | ||
| 348 | // *** lp = castfp32to16(ls) | 420 | // *** lp = castfp32to16(ls) |
| 349 | if (std::is_same<ElementOutput, bfloat16_t>::value) { | 421 | if (std::is_same<ElementOutput, bfloat16_t>::value) { |
| 350 | AscendC::Cast<ElementOutput, float, false>( | 422 | AscendC::Cast<ElementOutput, float, false>( |
| 351 | - tvUbTensor16, lsUbTensor, AscendC::RoundMode::CAST_RINT, (uint64_t)0, | 423 | + tvUbTensor16[sUbOffset * 2], lsUbTensor[sUbOffset], AscendC::RoundMode::CAST_RINT, (uint64_t)0, |
| 352 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | 424 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, |
| 353 | AscendC::UnaryRepeatParams(1, 1, 4, 8)); | 425 | AscendC::UnaryRepeatParams(1, 1, 4, 8)); |
| 354 | } else { | 426 | } else { |
| 355 | AscendC::Cast<ElementOutput, float, false>( | 427 | AscendC::Cast<ElementOutput, float, false>( |
| 356 | - tvUbTensor16, lsUbTensor, AscendC::RoundMode::CAST_NONE, (uint64_t)0, | 428 | + tvUbTensor16[sUbOffset * 2], lsUbTensor[sUbOffset], AscendC::RoundMode::CAST_NONE, (uint64_t)0, |
| 357 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | 429 | (curRowNum * kSeqTileRound + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, |
| 358 | AscendC::UnaryRepeatParams(1, 1, 4, 8)); | 430 | AscendC::UnaryRepeatParams(1, 1, 4, 8)); |
| 359 | } | 431 | } |
| 360 | - | ||
| 361 | AscendC::PipeBarrier<PIPE_V>(); | 432 | AscendC::PipeBarrier<PIPE_V>(); |
| 362 | 433 | ||
| 363 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); | 434 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); |
| @@ -369,17 +440,15 @@ public: | |||
| 369 | uint16_t dstStride = 0; | 440 | uint16_t dstStride = 0; |
| 370 | 441 | ||
| 371 | AscendC::DataCopy(gOutput, | 442 | AscendC::DataCopy(gOutput, |
| 372 | - tvUbTensor16, | 443 | + tvUbTensor16[sUbOffset * 2], |
| 373 | AscendC::DataCopyParams( | 444 | AscendC::DataCopyParams( |
| 374 | - blockCount, // blockCount | 445 | + blockCount, |
| 375 | - blockLen, // blockLen | 446 | + blockLen, |
| 376 | - srcStride, // srcGap | 447 | + srcStride, |
| 377 | dstStride)); | 448 | dstStride)); |
| 378 | 449 | ||
| 379 | // *** ll = rowsum(ls32) | 450 | // *** ll = rowsum(ls32) |
| 380 | - ReduceSumRepeatM(llUbTensor[llUbOffsetCurCycle], lsUbTensor, curRowNum, kSeqTile, kSeqTileRound); | 451 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(softmaxPingPongFlag + 6); |
| 381 | - AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(EVENT_ID2); | ||
| 382 | - AscendC::PipeBarrier<PIPE_V>(); | ||
| 383 | } | 452 | } |
| 384 | 453 | ||
| 385 | CATLASS_DEVICE | 454 | CATLASS_DEVICE |
| @@ -392,7 +461,7 @@ public: | |||
| 392 | uint32_t nIdx, | 461 | uint32_t nIdx, |
| 393 | uint32_t curHeadNum, | 462 | uint32_t curHeadNum, |
| 394 | uint32_t softmaxPingPongFlag, | 463 | uint32_t softmaxPingPongFlag, |
| 395 | - uint32_t &glFlag) | 464 | + uint32_t *glFlag, uint32_t taskPingPongFlag) |
| 396 | { | 465 | { |
| 397 | uint32_t rowActual = actualBlockShape.m(); | 466 | uint32_t rowActual = actualBlockShape.m(); |
| 398 | uint32_t nActual = actualBlockShape.n(); | 467 | uint32_t nActual = actualBlockShape.n(); |
| @@ -400,6 +469,7 @@ public: | |||
| 400 | 469 | ||
| 401 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | 470 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); |
| 402 | uint32_t subBlockNum = AscendC::GetSubBlockNum(); | 471 | uint32_t subBlockNum = AscendC::GetSubBlockNum(); |
| 472 | + uint32_t sUbOffset = softmaxPingPongFlag * 8192; | ||
| 403 | 473 | ||
| 404 | uint32_t curHeadSplitSubBlock = curHeadNum / subBlockNum; | 474 | uint32_t curHeadSplitSubBlock = curHeadNum / subBlockNum; |
| 405 | uint32_t curHeadThisSubBlock = (subBlockIdx == 0) ? curHeadSplitSubBlock : (curHeadNum - curHeadSplitSubBlock); | 475 | uint32_t curHeadThisSubBlock = (subBlockIdx == 0) ? curHeadSplitSubBlock : (curHeadNum - curHeadSplitSubBlock); |
| @@ -415,7 +485,7 @@ public: | |||
| 415 | auto gOutputThisSubBlock = gOutput[offsetOutput]; | 485 | auto gOutputThisSubBlock = gOutput[offsetOutput]; |
| 416 | auto layoutOutputThisSubBlock = layoutOutput.GetTileLayout(MatrixCoord(rowActualThisSubBlock, nActual)); | 486 | auto layoutOutputThisSubBlock = layoutOutput.GetTileLayout(MatrixCoord(rowActualThisSubBlock, nActual)); |
| 417 | SubCoreCompute(gOutputThisSubBlock, gInputThisSubBlock, layoutOutputThisSubBlock, layoutInputThisSubBlock, | 487 | SubCoreCompute(gOutputThisSubBlock, gInputThisSubBlock, layoutOutputThisSubBlock, layoutInputThisSubBlock, |
| 418 | - nIdx, softmaxPingPongFlag, glFlag); | 488 | + nIdx, softmaxPingPongFlag, glFlag, taskPingPongFlag, sUbOffset); |
| 419 | } | 489 | } |
| 420 | } | 490 | } |
| 421 | 491 | ||
| @@ -428,7 +498,7 @@ private: | |||
| 428 | AscendC::LocalTensor<float> lsUbTensor; | 498 | AscendC::LocalTensor<float> lsUbTensor; |
| 429 | AscendC::LocalTensor<float> lmUbTensor; | 499 | AscendC::LocalTensor<float> lmUbTensor; |
| 430 | AscendC::LocalTensor<float> hmUbTensor; | 500 | AscendC::LocalTensor<float> hmUbTensor; |
| 431 | - AscendC::LocalTensor<float> gmUbTensor; | 501 | + AscendC::LocalTensor<float> gmUbTensor[2]; |
| 432 | AscendC::LocalTensor<float> dmUbTensor; | 502 | AscendC::LocalTensor<float> dmUbTensor; |
| 433 | AscendC::LocalTensor<float> llUbTensor; | 503 | AscendC::LocalTensor<float> llUbTensor; |
| 434 | AscendC::LocalTensor<float> tvUbTensor; | 504 | AscendC::LocalTensor<float> tvUbTensor; |
| @@ -1,40 +1,33 @@ | |||
| 1 | /** | 1 | /** |
| 2 | - * Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. |
| 3 | - * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| 4 | - * CANN Open Software License Agreement Version 2.0 (the "License"). | 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). |
| 5 | - * Please refer to the License for details. You may not use this file except in compliance with the License. | 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. |
| 6 | - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, |
| 7 | - * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 8 | - * See LICENSE in the root of the software repository for the full text of the License. | 8 | + * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | - */ | 9 | + */ |
| 10 | - | ||
| 11 | 10 | ||
| 12 | 11 | ||
| 13 | - | ||
| 14 | 12 | ||
| 15 | 13 | ||
| 16 | 14 | ||
| 17 | 15 | ||
| 18 | 16 | ||
| 19 | 17 | ||
| 20 | - | ||
| 21 | namespace Catlass::Epilogue::Block { | 18 | namespace Catlass::Epilogue::Block { |
| 22 | - | ||
| 23 | template <class OutputType_, class UpdateType_, class InputType_> | 19 | template <class OutputType_, class UpdateType_, class InputType_> |
| 24 | class BlockEpilogue<EpilogueAtlasA2MLATP1RescaleO, OutputType_, UpdateType_, InputType_> { | 20 | class BlockEpilogue<EpilogueAtlasA2MLATP1RescaleO, OutputType_, UpdateType_, InputType_> { |
| 25 | public: | 21 | public: |
| 26 | // Type aliases | 22 | // Type aliases |
| 27 | using DispatchPolicy = EpilogueAtlasA2MLATP1RescaleO; | 23 | using DispatchPolicy = EpilogueAtlasA2MLATP1RescaleO; |
| 28 | using ArchTag = typename DispatchPolicy::ArchTag; | 24 | using ArchTag = typename DispatchPolicy::ArchTag; |
| 29 | - | ||
| 30 | using ElementOutput = typename OutputType_::Element; | 25 | using ElementOutput = typename OutputType_::Element; |
| 31 | using ElementUpdate = typename UpdateType_::Element; | 26 | using ElementUpdate = typename UpdateType_::Element; |
| 32 | using ElementInput = typename InputType_::Element; | 27 | using ElementInput = typename InputType_::Element; |
| 33 | - | ||
| 34 | using LayoutOutput = typename OutputType_::Layout; | 28 | using LayoutOutput = typename OutputType_::Layout; |
| 35 | using LayoutUpdate = typename UpdateType_::Layout; | 29 | using LayoutUpdate = typename UpdateType_::Layout; |
| 36 | using LayoutInput = typename InputType_::Layout; | 30 | using LayoutInput = typename InputType_::Layout; |
| 37 | - | ||
| 38 | static constexpr uint32_t HALF_ELENUM_PER_BLK = 16; | 31 | static constexpr uint32_t HALF_ELENUM_PER_BLK = 16; |
| 39 | static constexpr uint32_t HALF_ELENUM_PER_VECCALC = 128; | 32 | static constexpr uint32_t HALF_ELENUM_PER_VECCALC = 128; |
| 40 | static constexpr uint32_t FLOAT_ELENUM_PER_VECCALC = 64; | 33 | static constexpr uint32_t FLOAT_ELENUM_PER_VECCALC = 64; |
| @@ -50,33 +43,31 @@ public: | |||
| 50 | static constexpr uint32_t HALF_LL_UB_SIZE = 256; | 43 | static constexpr uint32_t HALF_LL_UB_SIZE = 256; |
| 51 | static constexpr uint32_t VECTOR_SIZE = 128; | 44 | static constexpr uint32_t VECTOR_SIZE = 128; |
| 52 | static constexpr uint32_t NUM4 = 4; | 45 | static constexpr uint32_t NUM4 = 4; |
| 53 | - | ||
| 54 | CATLASS_DEVICE | 46 | CATLASS_DEVICE |
| 55 | BlockEpilogue(Arch::Resource<ArchTag> &resource, uint32_t kvSplitCoreNum_ = 1) | 47 | BlockEpilogue(Arch::Resource<ArchTag> &resource, uint32_t kvSplitCoreNum_ = 1) |
| 56 | { | 48 | { |
| 57 | // Allocate UB space | 49 | // Allocate UB space |
| 58 | - constexpr uint32_t LO_UB_TENSOR_OFFSET = 4 * UB_UINT8_BLOCK_SIZE_MLA; | 50 | + constexpr uint32_t LO_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA; |
| 59 | - constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 6 * UB_UINT8_LINE_SIZE; | ||
| 60 | - constexpr uint32_t GL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 16 * UB_UINT8_LINE_SIZE; | ||
| 61 | constexpr uint32_t GO_UB_TENSOR_OFFSET = 8 * UB_UINT8_BLOCK_SIZE_MLA; | 51 | constexpr uint32_t GO_UB_TENSOR_OFFSET = 8 * UB_UINT8_BLOCK_SIZE_MLA; |
| 62 | - constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA; | 52 | + constexpr uint32_t DM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 2 * UB_UINT8_LINE_SIZE; |
| 63 | - constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; | 53 | + constexpr uint32_t GL_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 7 * UB_UINT8_LINE_SIZE; |
| 64 | - constexpr uint32_t GM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 14 * UB_UINT8_LINE_SIZE; | 54 | + constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 9 * UB_UINT8_LINE_SIZE; |
| 65 | - | 55 | + constexpr uint32_t HM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; |
| 56 | + constexpr uint32_t GM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 5 * UB_UINT8_LINE_SIZE; | ||
| 66 | kvSplitCoreNum = kvSplitCoreNum_; | 57 | kvSplitCoreNum = kvSplitCoreNum_; |
| 67 | loUbTensor = resource.ubBuf.template GetBufferByByte<float>(LO_UB_TENSOR_OFFSET); | 58 | loUbTensor = resource.ubBuf.template GetBufferByByte<float>(LO_UB_TENSOR_OFFSET); |
| 68 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); | 59 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); |
| 69 | - glUbTensor = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); | 60 | + glUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); |
| 61 | + glUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 70 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); | 62 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); |
| 71 | goUbTensor16 = resource.ubBuf.template GetBufferByByte<ElementOutput>(GO_UB_TENSOR_OFFSET); | 63 | goUbTensor16 = resource.ubBuf.template GetBufferByByte<ElementOutput>(GO_UB_TENSOR_OFFSET); |
| 72 | goUbTensor32 = resource.ubBuf.template GetBufferByByte<float>(GO_UB_TENSOR_OFFSET); | 64 | goUbTensor32 = resource.ubBuf.template GetBufferByByte<float>(GO_UB_TENSOR_OFFSET); |
| 73 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | 65 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); |
| 74 | - gmUbTensor = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | 66 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); |
| 67 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 75 | } | 68 | } |
| 76 | - | ||
| 77 | CATLASS_DEVICE | 69 | CATLASS_DEVICE |
| 78 | ~BlockEpilogue() {} | 70 | ~BlockEpilogue() {} |
| 79 | - | ||
| 80 | CATLASS_DEVICE | 71 | CATLASS_DEVICE |
| 81 | void SetMask(int32_t len) | 72 | void SetMask(int32_t len) |
| 82 | { | 73 | { |
| @@ -86,7 +77,6 @@ public: | |||
| 86 | for (int64_t i = 0; i < temp; i++) { | 77 | for (int64_t i = 0; i < temp; i++) { |
| 87 | mask |= one << i; | 78 | mask |= one << i; |
| 88 | } | 79 | } |
| 89 | - | ||
| 90 | if (len == VECTOR_SIZE) { | 80 | if (len == VECTOR_SIZE) { |
| 91 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | 81 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); |
| 92 | } else if (len >= FLOAT_VECTOR_SIZE) { | 82 | } else if (len >= FLOAT_VECTOR_SIZE) { |
| @@ -95,20 +85,18 @@ public: | |||
| 95 | AscendC::SetVectorMask<int8_t>(0x0, mask); | 85 | AscendC::SetVectorMask<int8_t>(0x0, mask); |
| 96 | } | 86 | } |
| 97 | } | 87 | } |
| 98 | - | ||
| 99 | CATLASS_DEVICE | 88 | CATLASS_DEVICE |
| 100 | void SetkvSplitCoreNum(uint32_t kvSplitCoreNum_) | 89 | void SetkvSplitCoreNum(uint32_t kvSplitCoreNum_) |
| 101 | { | 90 | { |
| 102 | kvSplitCoreNum = kvSplitCoreNum_; | 91 | kvSplitCoreNum = kvSplitCoreNum_; |
| 103 | } | 92 | } |
| 104 | - | ||
| 105 | CATLASS_DEVICE | 93 | CATLASS_DEVICE |
| 106 | void SubCoreCompute(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, | 94 | void SubCoreCompute(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, |
| 107 | AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, | 95 | AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, |
| 108 | AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, | 96 | AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, |
| 109 | const LayoutOutput &layoutOutput, const LayoutUpdate &layoutUpdate, uint32_t nIdx, | 97 | const LayoutOutput &layoutOutput, const LayoutUpdate &layoutUpdate, uint32_t nIdx, |
| 110 | uint32_t isLastNTile, uint32_t needRowLoop, uint32_t rowLoopIdx, uint32_t rescaleOPingPongFlag, | 98 | uint32_t isLastNTile, uint32_t needRowLoop, uint32_t rowLoopIdx, uint32_t rescaleOPingPongFlag, |
| 111 | - uint32_t &glFlag) | 99 | + uint32_t *glFlag, uint32_t taskPingPongFlag) |
| 112 | { | 100 | { |
| 113 | uint32_t curRowNum = layoutInput.shape(0); | 101 | uint32_t curRowNum = layoutInput.shape(0); |
| 114 | uint32_t embed = layoutInput.shape(1); | 102 | uint32_t embed = layoutInput.shape(1); |
| @@ -173,11 +161,10 @@ public: | |||
| 173 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); | 161 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVENT_ID0); |
| 174 | } | 162 | } |
| 175 | AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(oPingPangFlag); | 163 | AscendC::SetFlag<AscendC::HardEvent::V_MTE2>(oPingPangFlag); |
| 176 | - | ||
| 177 | if (isLastNTile) { | 164 | if (isLastNTile) { |
| 178 | // *** gl_block = expand_to_block(gl), 存放于 tv | 165 | // *** gl_block = expand_to_block(gl), 存放于 tv |
| 179 | AscendC::Brcb(tvUbTensor.ReinterpretCast<uint32_t>(), | 166 | AscendC::Brcb(tvUbTensor.ReinterpretCast<uint32_t>(), |
| 180 | - glUbTensor.ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], | 167 | + glUbTensor[taskPingPongFlag].ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], |
| 181 | curRowNumRound / FLOAT_BLOCK_SIZE, | 168 | curRowNumRound / FLOAT_BLOCK_SIZE, |
| 182 | AscendC::BrcbRepeatParams(1, 8)); | 169 | AscendC::BrcbRepeatParams(1, 8)); |
| 183 | AscendC::PipeBarrier<PIPE_V>(); | 170 | AscendC::PipeBarrier<PIPE_V>(); |
| @@ -202,7 +189,6 @@ public: | |||
| 202 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | 189 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); |
| 203 | } | 190 | } |
| 204 | AscendC::PipeBarrier<PIPE_V>(); | 191 | AscendC::PipeBarrier<PIPE_V>(); |
| 205 | - | ||
| 206 | if (kvSplitCoreNum != 1) { | 192 | if (kvSplitCoreNum != 1) { |
| 207 | // log(l) | 193 | // log(l) |
| 208 | AscendC::Ln<float, false>( | 194 | AscendC::Ln<float, false>( |
| @@ -214,7 +200,7 @@ public: | |||
| 214 | AscendC::PipeBarrier<PIPE_V>(); | 200 | AscendC::PipeBarrier<PIPE_V>(); |
| 215 | AscendC::Brcb( | 201 | AscendC::Brcb( |
| 216 | hmUbTensor.ReinterpretCast<uint32_t>(), | 202 | hmUbTensor.ReinterpretCast<uint32_t>(), |
| 217 | - gmUbTensor.ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], | 203 | + gmUbTensor[taskPingPongFlag].ReinterpretCast<uint32_t>()[rowLoopIdx * ROW_WISE_CYCLE_TILE], |
| 218 | curRowNumRound / FLOAT_BLOCK_SIZE, | 204 | curRowNumRound / FLOAT_BLOCK_SIZE, |
| 219 | AscendC::BrcbRepeatParams(1, 8)); | 205 | AscendC::BrcbRepeatParams(1, 8)); |
| 220 | AscendC::PipeBarrier<PIPE_V>(); | 206 | AscendC::PipeBarrier<PIPE_V>(); |
| @@ -227,21 +213,19 @@ public: | |||
| 227 | curRowNum, | 213 | curRowNum, |
| 228 | AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | 214 | AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); |
| 229 | AscendC::PipeBarrier<PIPE_V>(); | 215 | AscendC::PipeBarrier<PIPE_V>(); |
| 230 | - | ||
| 231 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); | 216 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); |
| 232 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); | 217 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID2); |
| 233 | AscendC::DataCopyPad(gl, tvUbTensor, | 218 | AscendC::DataCopyPad(gl, tvUbTensor, |
| 234 | AscendC::DataCopyExtParams(curRowNum, 4, 0, (kvSplitCoreNum - 1) * 4, 0)); | 219 | AscendC::DataCopyExtParams(curRowNum, 4, 0, (kvSplitCoreNum - 1) * 4, 0)); |
| 235 | - | 220 | + if (glFlag[taskPingPongFlag] == 0) { |
| 236 | - if (glFlag == 0) { | 221 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(taskPingPongFlag + 2); |
| 237 | - AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | 222 | + glFlag[taskPingPongFlag] = 1; |
| 238 | - glFlag = 1; | ||
| 239 | } | 223 | } |
| 240 | uint32_t srcGap = ((embed % 16 <= 8) && (embed % 16 > 0)) ? 1 : 0; | 224 | uint32_t srcGap = ((embed % 16 <= 8) && (embed % 16 > 0)) ? 1 : 0; |
| 241 | AscendC::DataCopyPad(gOCoreTmp, goUbTensor32[oUbOffset], | 225 | AscendC::DataCopyPad(gOCoreTmp, goUbTensor32[oUbOffset], |
| 242 | AscendC::DataCopyExtParams(curRowNum, embed * 4, srcGap, (kvSplitCoreNum - 1) * embed * 4, 0)); | 226 | AscendC::DataCopyExtParams(curRowNum, embed * 4, srcGap, (kvSplitCoreNum - 1) * embed * 4, 0)); |
| 243 | - AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | 227 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID4); |
| 244 | - AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID3); | 228 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID4); |
| 245 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | 229 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); |
| 246 | AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); | 230 | AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(EVENT_ID1); |
| 247 | } else { | 231 | } else { |
| @@ -261,7 +245,6 @@ public: | |||
| 261 | } | 245 | } |
| 262 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); | 246 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); |
| 263 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); | 247 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVENT_ID0); |
| 264 | - | ||
| 265 | // ********************* move O to GM ************************ | 248 | // ********************* move O to GM ************************ |
| 266 | AscendC::DataCopyPad(gOutput, goUbTensor16[oUbOffset * 2], | 249 | AscendC::DataCopyPad(gOutput, goUbTensor16[oUbOffset * 2], |
| 267 | AscendC::DataCopyExtParams(curRowNum, embed * 2, 0, 0, 0)); | 250 | AscendC::DataCopyExtParams(curRowNum, embed * 2, 0, 0, 0)); |
| @@ -275,25 +258,21 @@ public: | |||
| 275 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(oPingPangFlag + 4); | 258 | AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(oPingPangFlag + 4); |
| 276 | oPingPangFlag = 1 - oPingPangFlag; | 259 | oPingPangFlag = 1 - oPingPangFlag; |
| 277 | } | 260 | } |
| 278 | - | ||
| 279 | CATLASS_DEVICE | 261 | CATLASS_DEVICE |
| 280 | void operator()(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, | 262 | void operator()(AscendC::GlobalTensor<ElementInput> gInput, AscendC::GlobalTensor<ElementUpdate> gUpdate, |
| 281 | AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, | 263 | AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementUpdate> gOCoreTmp, |
| 282 | AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, | 264 | AscendC::GlobalTensor<ElementUpdate> gl, const LayoutInput &layoutInput, |
| 283 | const LayoutUpdate &layoutUpdate, const LayoutOutput &layoutOutput, GemmCoord actualBlockShape, | 265 | const LayoutUpdate &layoutUpdate, const LayoutOutput &layoutOutput, GemmCoord actualBlockShape, |
| 284 | - uint32_t nIdx, uint32_t isLastNTile, uint32_t rescaleOPingPongFlag, uint32_t &glFlag) | 266 | + uint32_t nIdx, uint32_t isLastNTile, uint32_t rescaleOPingPongFlag, uint32_t *glFlag, uint32_t taskPingPongFlag) |
| 285 | { | 267 | { |
| 286 | uint32_t embed = layoutInput.shape(1); | 268 | uint32_t embed = layoutInput.shape(1); |
| 287 | uint32_t rowActual = actualBlockShape.m(); | 269 | uint32_t rowActual = actualBlockShape.m(); |
| 288 | uint32_t columnActual = actualBlockShape.n(); | 270 | uint32_t columnActual = actualBlockShape.n(); |
| 289 | - | ||
| 290 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | 271 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); |
| 291 | uint32_t subBlockNum = AscendC::GetSubBlockNum(); | 272 | uint32_t subBlockNum = AscendC::GetSubBlockNum(); |
| 292 | - | ||
| 293 | uint32_t curRowSplitSubBlock = rowActual / subBlockNum; | 273 | uint32_t curRowSplitSubBlock = rowActual / subBlockNum; |
| 294 | uint32_t rowActualThisSubBlock = (subBlockIdx == 0) ? curRowSplitSubBlock : (rowActual - curRowSplitSubBlock); | 274 | uint32_t rowActualThisSubBlock = (subBlockIdx == 0) ? curRowSplitSubBlock : (rowActual - curRowSplitSubBlock); |
| 295 | uint32_t rowOffsetSubBlock = subBlockIdx * curRowSplitSubBlock; | 275 | uint32_t rowOffsetSubBlock = subBlockIdx * curRowSplitSubBlock; |
| 296 | - | ||
| 297 | if (rowActualThisSubBlock > 0) { | 276 | if (rowActualThisSubBlock > 0) { |
| 298 | uint32_t rowLoop = (rowActualThisSubBlock + ROW_WISE_CYCLE_TILE - 1) / ROW_WISE_CYCLE_TILE; | 277 | uint32_t rowLoop = (rowActualThisSubBlock + ROW_WISE_CYCLE_TILE - 1) / ROW_WISE_CYCLE_TILE; |
| 299 | uint32_t needRowLoop = (rowLoop > 1) ? 1 : 0; | 278 | uint32_t needRowLoop = (rowLoop > 1) ? 1 : 0; |
| @@ -305,37 +284,31 @@ public: | |||
| 305 | int64_t offsetInput = layoutInput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | 284 | int64_t offsetInput = layoutInput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); |
| 306 | auto gInputThisCurCycle = gInput[offsetInput]; | 285 | auto gInputThisCurCycle = gInput[offsetInput]; |
| 307 | auto layoutInputCurCycle = layoutInput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | 286 | auto layoutInputCurCycle = layoutInput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); |
| 308 | - | ||
| 309 | int64_t offsetUpdate = layoutUpdate.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | 287 | int64_t offsetUpdate = layoutUpdate.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); |
| 310 | auto gUpdateCurCycle = gUpdate[offsetUpdate]; | 288 | auto gUpdateCurCycle = gUpdate[offsetUpdate]; |
| 311 | auto layoutUpdateCurCycle = layoutUpdate.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | 289 | auto layoutUpdateCurCycle = layoutUpdate.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); |
| 312 | - | ||
| 313 | int64_t offsetOutput = layoutOutput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); | 290 | int64_t offsetOutput = layoutOutput.GetOffset(MatrixCoord(rowOffsetCurCycle, 0)); |
| 314 | auto gOutputCurCycle = gOutput[offsetOutput]; | 291 | auto gOutputCurCycle = gOutput[offsetOutput]; |
| 315 | auto layoutOutputCurCycle = layoutOutput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); | 292 | auto layoutOutputCurCycle = layoutOutput.GetTileLayout(MatrixCoord(rowActualCurCycle, columnActual)); |
| 316 | - | ||
| 317 | SubCoreCompute(gInputThisCurCycle, gUpdateCurCycle, gOutputCurCycle, | 293 | SubCoreCompute(gInputThisCurCycle, gUpdateCurCycle, gOutputCurCycle, |
| 318 | gOCoreTmp[rowOffsetLoop * embed * kvSplitCoreNum], | 294 | gOCoreTmp[rowOffsetLoop * embed * kvSplitCoreNum], |
| 319 | gl[rowOffsetLoop * kvSplitCoreNum], layoutInputCurCycle, | 295 | gl[rowOffsetLoop * kvSplitCoreNum], layoutInputCurCycle, |
| 320 | layoutOutputCurCycle, layoutUpdateCurCycle, nIdx, isLastNTile, needRowLoop, rowLoopIdx, | 296 | layoutOutputCurCycle, layoutUpdateCurCycle, nIdx, isLastNTile, needRowLoop, rowLoopIdx, |
| 321 | - rescaleOPingPongFlag, glFlag); | 297 | + rescaleOPingPongFlag, glFlag, taskPingPongFlag); |
| 322 | } | 298 | } |
| 323 | } | 299 | } |
| 324 | } | 300 | } |
| 325 | - | ||
| 326 | private: | 301 | private: |
| 327 | uint32_t kvSplitCoreNum = 1; | 302 | uint32_t kvSplitCoreNum = 1; |
| 328 | uint32_t oPingPangFlag = 0; | 303 | uint32_t oPingPangFlag = 0; |
| 329 | AscendC::LocalTensor<float> loUbTensor; | 304 | AscendC::LocalTensor<float> loUbTensor; |
| 330 | AscendC::LocalTensor<float> dmUbTensor; | 305 | AscendC::LocalTensor<float> dmUbTensor; |
| 331 | - AscendC::LocalTensor<float> glUbTensor; | 306 | + AscendC::LocalTensor<float> glUbTensor[2]; |
| 332 | AscendC::LocalTensor<float> tvUbTensor; | 307 | AscendC::LocalTensor<float> tvUbTensor; |
| 333 | AscendC::LocalTensor<ElementOutput> goUbTensor16; | 308 | AscendC::LocalTensor<ElementOutput> goUbTensor16; |
| 334 | AscendC::LocalTensor<float> goUbTensor32; | 309 | AscendC::LocalTensor<float> goUbTensor32; |
| 335 | AscendC::LocalTensor<float> hmUbTensor; | 310 | AscendC::LocalTensor<float> hmUbTensor; |
| 336 | - AscendC::LocalTensor<float> gmUbTensor; | 311 | + AscendC::LocalTensor<float> gmUbTensor[2]; |
| 337 | }; | 312 | }; |
| 338 | - | ||
| 339 | } // namespace Catlass::Epilogue::Block | 313 | } // namespace Catlass::Epilogue::Block |
| 340 | - | ||
| 341 | 314 | ||
| @@ -55,13 +55,14 @@ public: | |||
| 55 | static constexpr uint32_t UB_UINT8_BLOCK_SIZE_MLA = 16384; | 55 | static constexpr uint32_t UB_UINT8_BLOCK_SIZE_MLA = 16384; |
| 56 | static constexpr uint32_t VECTOR_SIZE = 128; | 56 | static constexpr uint32_t VECTOR_SIZE = 128; |
| 57 | 57 | ||
| 58 | - static constexpr uint32_t REDUCE_UB_SIZE = 1024; | 58 | + static constexpr uint32_t REDUCE_UB_SIZE = 1536; |
| 59 | static constexpr uint32_t ROW_OPS_SPEC_MASK_32 = 32; | 59 | static constexpr uint32_t ROW_OPS_SPEC_MASK_32 = 32; |
| 60 | static constexpr uint32_t ROW_OPS_SPEC_MASK_4 = 4; | 60 | static constexpr uint32_t ROW_OPS_SPEC_MASK_4 = 4; |
| 61 | static constexpr uint32_t S_BLOCK_STACK = 4; | 61 | static constexpr uint32_t S_BLOCK_STACK = 4; |
| 62 | static constexpr int64_t UB_FLOAT_LINE_SIZE = 64; | 62 | static constexpr int64_t UB_FLOAT_LINE_SIZE = 64; |
| 63 | - static constexpr uint32_t M_SLICE = 16; | 63 | + static constexpr uint32_t M_SLICE = 24; |
| 64 | static constexpr uint32_t QK_READY_ID = 1; | 64 | static constexpr uint32_t QK_READY_ID = 1; |
| 65 | + static constexpr uint32_t LS_CHUNK_SIZE = 12288; | ||
| 65 | 66 | ||
| 66 | CATLASS_DEVICE | 67 | CATLASS_DEVICE |
| 67 | BlockEpilogue(Arch::Resource<ArchTag> &resource, half tor_, uint32_t kvSplitCoreNum_ = 1) | 68 | BlockEpilogue(Arch::Resource<ArchTag> &resource, half tor_, uint32_t kvSplitCoreNum_ = 1) |
| @@ -69,13 +70,13 @@ public: | |||
| 69 | // Allocate UB space | 70 | // Allocate UB space |
| 70 | constexpr uint32_t LS_UB_TENSOR_OFFSET = 0; | 71 | constexpr uint32_t LS_UB_TENSOR_OFFSET = 0; |
| 71 | constexpr uint32_t LP_UB_TENSOR_OFFSET = 0; | 72 | constexpr uint32_t LP_UB_TENSOR_OFFSET = 0; |
| 72 | - constexpr uint32_t LM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA; | 73 | + constexpr uint32_t LM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA; |
| 73 | - constexpr uint32_t HM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; | 74 | + constexpr uint32_t HM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 1 * UB_UINT8_LINE_SIZE; |
| 74 | - constexpr uint32_t DM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 6 * UB_UINT8_LINE_SIZE; | 75 | + constexpr uint32_t DM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 2 * UB_UINT8_LINE_SIZE; |
| 75 | - constexpr uint32_t LL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 10 * UB_UINT8_LINE_SIZE; | 76 | + constexpr uint32_t LL_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 4 * UB_UINT8_LINE_SIZE; |
| 76 | - constexpr uint32_t GM_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 14 * UB_UINT8_LINE_SIZE; | 77 | + constexpr uint32_t GM_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 5 * UB_UINT8_LINE_SIZE; |
| 77 | - constexpr uint32_t GL_UB_TENSOR_OFFSET = 6 * UB_UINT8_BLOCK_SIZE_MLA + 16 * UB_UINT8_LINE_SIZE; | 78 | + constexpr uint32_t GL_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 7 * UB_UINT8_LINE_SIZE; |
| 78 | - constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA; | 79 | + constexpr uint32_t TV_UB_TENSOR_OFFSET = 10 * UB_UINT8_BLOCK_SIZE_MLA + 9 * UB_UINT8_LINE_SIZE; |
| 79 | 80 | ||
| 80 | tor = tor_; | 81 | tor = tor_; |
| 81 | kvSplitCoreNum = kvSplitCoreNum_; | 82 | kvSplitCoreNum = kvSplitCoreNum_; |
| @@ -83,11 +84,13 @@ public: | |||
| 83 | lpUbTensor = resource.ubBuf.template GetBufferByByte<ElementOutput>(LP_UB_TENSOR_OFFSET); | 84 | lpUbTensor = resource.ubBuf.template GetBufferByByte<ElementOutput>(LP_UB_TENSOR_OFFSET); |
| 84 | lmUbTensor = resource.ubBuf.template GetBufferByByte<float>(LM_UB_TENSOR_OFFSET); | 85 | lmUbTensor = resource.ubBuf.template GetBufferByByte<float>(LM_UB_TENSOR_OFFSET); |
| 85 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); | 86 | hmUbTensor = resource.ubBuf.template GetBufferByByte<float>(HM_UB_TENSOR_OFFSET); |
| 86 | - gmUbTensor = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); | 87 | + gmUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET); |
| 88 | + gmUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GM_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 87 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); | 89 | dmUbTensor = resource.ubBuf.template GetBufferByByte<float>(DM_UB_TENSOR_OFFSET); |
| 88 | llUbTensor = resource.ubBuf.template GetBufferByByte<float>(LL_UB_TENSOR_OFFSET); | 90 | llUbTensor = resource.ubBuf.template GetBufferByByte<float>(LL_UB_TENSOR_OFFSET); |
| 89 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); | 91 | tvUbTensor = resource.ubBuf.template GetBufferByByte<float>(TV_UB_TENSOR_OFFSET); |
| 90 | - glUbTensor = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); | 92 | + glUbTensor[0] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET); |
| 93 | + glUbTensor[1] = resource.ubBuf.template GetBufferByByte<float>(GL_UB_TENSOR_OFFSET + UB_UINT8_LINE_SIZE); | ||
| 91 | } | 94 | } |
| 92 | 95 | ||
| 93 | CATLASS_DEVICE | 96 | CATLASS_DEVICE |
| @@ -315,13 +318,14 @@ public: | |||
| 315 | CATLASS_DEVICE | 318 | CATLASS_DEVICE |
| 316 | void SubCoreCompute(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, | 319 | void SubCoreCompute(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, |
| 317 | uint32_t m, uint32_t nReal, uint32_t nStride, uint32_t pingpongFlag, uint32_t rowOffset, | 320 | uint32_t m, uint32_t nReal, uint32_t nStride, uint32_t pingpongFlag, uint32_t rowOffset, |
| 318 | - uint32_t sUbOffset, uint32_t nIdx, uint32_t &glFlag) | 321 | + uint32_t sUbOffset, uint32_t nIdx, uint32_t *glFlag, uint32_t taskPingPongFlag, uint32_t gSPingPongFlag) |
| 319 | { | 322 | { |
| 320 | uint32_t round_m = (m + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE * FLOAT_BLOCK_SIZE; | 323 | uint32_t round_m = (m + FLOAT_BLOCK_SIZE - 1) / FLOAT_BLOCK_SIZE * FLOAT_BLOCK_SIZE; |
| 321 | - AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(pingpongFlag); | 324 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_MTE2>(gSPingPongFlag); |
| 322 | // input QK | 325 | // input QK |
| 323 | AscendC::DataCopy(lsUbTensor[sUbOffset], gInput, AscendC::DataCopyParams(m, nStride / FLOAT_BLOCK_SIZE, 0, 0)); | 326 | AscendC::DataCopy(lsUbTensor[sUbOffset], gInput, AscendC::DataCopyParams(m, nStride / FLOAT_BLOCK_SIZE, 0, 0)); |
| 324 | 327 | ||
| 328 | + | ||
| 325 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); | 329 | AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); |
| 326 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); | 330 | AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(pingpongFlag); |
| 327 | 331 | ||
| @@ -334,9 +338,9 @@ public: | |||
| 334 | 338 | ||
| 335 | if (kvSplitCoreNum != 1) { | 339 | if (kvSplitCoreNum != 1) { |
| 336 | if (nIdx == 0) { | 340 | if (nIdx == 0) { |
| 337 | - if (glFlag == 1) { | 341 | + if (glFlag[taskPingPongFlag] == 1) { |
| 338 | - AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVENT_ID2); | 342 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(taskPingPongFlag + 2); |
| 339 | - glFlag = 0; | 343 | + glFlag[taskPingPongFlag] = 0; |
| 340 | } | 344 | } |
| 341 | } | 345 | } |
| 342 | } | 346 | } |
| @@ -349,45 +353,51 @@ public: | |||
| 349 | RowmaxTAILTILE(lsUbTensor[sUbOffset], lmUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | 353 | RowmaxTAILTILE(lsUbTensor[sUbOffset], lmUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); |
| 350 | } | 354 | } |
| 351 | 355 | ||
| 356 | + | ||
| 352 | if (nIdx == 0) { | 357 | if (nIdx == 0) { |
| 353 | AscendC::DataCopy(hmUbTensor[rowOffset], lmUbTensor[rowOffset], | 358 | AscendC::DataCopy(hmUbTensor[rowOffset], lmUbTensor[rowOffset], |
| 354 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | 359 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); |
| 360 | + | ||
| 355 | AscendC::PipeBarrier<PIPE_V>(); | 361 | AscendC::PipeBarrier<PIPE_V>(); |
| 356 | } else { | 362 | } else { |
| 357 | SetVecMask(m); | 363 | SetVecMask(m); |
| 358 | // *** hm = vmax(lm, gm) | 364 | // *** hm = vmax(lm, gm) |
| 359 | - AscendC::Max<float, false>(hmUbTensor[rowOffset], lmUbTensor[rowOffset], gmUbTensor[rowOffset], (uint64_t)0, | 365 | + AscendC::Max<float, false>(hmUbTensor[rowOffset], lmUbTensor[rowOffset], gmUbTensor[taskPingPongFlag][rowOffset], (uint64_t)0, |
| 360 | 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | 366 | 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); |
| 361 | 367 | ||
| 362 | AscendC::PipeBarrier<PIPE_V>(); | 368 | AscendC::PipeBarrier<PIPE_V>(); |
| 363 | // *** dm = gm - hm | 369 | // *** dm = gm - hm |
| 364 | - AscendC::Sub<float, false>(dmUbTensor[((nIdx / S_BLOCK_STACK) % 2) * UB_FLOAT_LINE_SIZE + rowOffset], | 370 | + AscendC::Sub<float, false>(dmUbTensor[gSPingPongFlag * UB_FLOAT_LINE_SIZE + rowOffset], |
| 365 | - gmUbTensor[rowOffset], hmUbTensor[rowOffset], (uint64_t)0, 1, | 371 | + gmUbTensor[taskPingPongFlag][rowOffset], hmUbTensor[rowOffset], (uint64_t)0, 1, |
| 366 | AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | 372 | AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); |
| 367 | 373 | ||
| 368 | AscendC::PipeBarrier<PIPE_V>(); | 374 | AscendC::PipeBarrier<PIPE_V>(); |
| 369 | // *** dm = exp(dm) | 375 | // *** dm = exp(dm) |
| 370 | - AscendC::Exp<float, false>(dmUbTensor[((nIdx / S_BLOCK_STACK) % 2) * UB_FLOAT_LINE_SIZE + rowOffset], | 376 | + AscendC::Exp<float, false>(dmUbTensor[gSPingPongFlag * UB_FLOAT_LINE_SIZE + rowOffset], |
| 371 | - dmUbTensor[((nIdx / S_BLOCK_STACK) % 2) * UB_FLOAT_LINE_SIZE + rowOffset], | 377 | + dmUbTensor[gSPingPongFlag * UB_FLOAT_LINE_SIZE + rowOffset], |
| 372 | (uint64_t)0, 1, AscendC::UnaryRepeatParams(1, 1, 8, 8)); | 378 | (uint64_t)0, 1, AscendC::UnaryRepeatParams(1, 1, 8, 8)); |
| 373 | } | 379 | } |
| 380 | + | ||
| 374 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | 381 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); |
| 375 | AscendC::PipeBarrier<PIPE_V>(); | 382 | AscendC::PipeBarrier<PIPE_V>(); |
| 376 | // *** gm = hm | 383 | // *** gm = hm |
| 377 | - AscendC::DataCopy(gmUbTensor[rowOffset], hmUbTensor[rowOffset], | 384 | + AscendC::DataCopy(gmUbTensor[taskPingPongFlag][rowOffset], hmUbTensor[rowOffset], |
| 378 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | 385 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); |
| 379 | AscendC::PipeBarrier<PIPE_V>(); | 386 | AscendC::PipeBarrier<PIPE_V>(); |
| 387 | + | ||
| 380 | // *** hm_block = expand_to_block(hm), 存放于 tv | 388 | // *** hm_block = expand_to_block(hm), 存放于 tv |
| 381 | AscendC::Brcb(tvUbTensor.template ReinterpretCast<uint32_t>(), | 389 | AscendC::Brcb(tvUbTensor.template ReinterpretCast<uint32_t>(), |
| 382 | hmUbTensor[rowOffset].template ReinterpretCast<uint32_t>(), round_m / FLOAT_BLOCK_SIZE, | 390 | hmUbTensor[rowOffset].template ReinterpretCast<uint32_t>(), round_m / FLOAT_BLOCK_SIZE, |
| 383 | AscendC::BrcbRepeatParams(1, 8)); | 391 | AscendC::BrcbRepeatParams(1, 8)); |
| 384 | AscendC::PipeBarrier<PIPE_V>(); | 392 | AscendC::PipeBarrier<PIPE_V>(); |
| 393 | + | ||
| 385 | // *** ls = ls - hm_block | 394 | // *** ls = ls - hm_block |
| 386 | for (uint32_t subIdx = 0; subIdx < nReal / FLOAT_VECTOR_SIZE; ++subIdx) { | 395 | for (uint32_t subIdx = 0; subIdx < nReal / FLOAT_VECTOR_SIZE; ++subIdx) { |
| 387 | AscendC::Sub<float, false>( | 396 | AscendC::Sub<float, false>( |
| 388 | lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], | 397 | lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], lsUbTensor[sUbOffset][subIdx * FLOAT_VECTOR_SIZE], |
| 389 | tvUbTensor, (uint64_t)0, m, | 398 | tvUbTensor, (uint64_t)0, m, |
| 390 | AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | 399 | AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); |
| 400 | + | ||
| 391 | } | 401 | } |
| 392 | if (nReal % FLOAT_VECTOR_SIZE > 0) { | 402 | if (nReal % FLOAT_VECTOR_SIZE > 0) { |
| 393 | SetVecMask(nReal % FLOAT_VECTOR_SIZE); | 403 | SetVecMask(nReal % FLOAT_VECTOR_SIZE); |
| @@ -396,6 +406,7 @@ public: | |||
| 396 | lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], tvUbTensor, (uint64_t)0, m, | 406 | lsUbTensor[sUbOffset][nReal / FLOAT_VECTOR_SIZE * FLOAT_VECTOR_SIZE], tvUbTensor, (uint64_t)0, m, |
| 397 | AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); | 407 | AscendC::BinaryRepeatParams(1, 1, 0, nStride / FLOAT_BLOCK_SIZE, nStride / FLOAT_BLOCK_SIZE, 1)); |
| 398 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | 408 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); |
| 409 | + | ||
| 399 | } | 410 | } |
| 400 | AscendC::PipeBarrier<PIPE_V>(); | 411 | AscendC::PipeBarrier<PIPE_V>(); |
| 401 | 412 | ||
| @@ -404,6 +415,7 @@ public: | |||
| 404 | (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, | 415 | (m * nStride + FLOAT_VECTOR_SIZE - 1) / FLOAT_VECTOR_SIZE, |
| 405 | AscendC::UnaryRepeatParams(1, 1, 8, 8)); | 416 | AscendC::UnaryRepeatParams(1, 1, 8, 8)); |
| 406 | AscendC::PipeBarrier<PIPE_V>(); | 417 | AscendC::PipeBarrier<PIPE_V>(); |
| 418 | + | ||
| 407 | // *** ll = rowsum(ls32) | 419 | // *** ll = rowsum(ls32) |
| 408 | if (nReal == 512) { | 420 | if (nReal == 512) { |
| 409 | RowsumSPECTILE512(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | 421 | RowsumSPECTILE512(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); |
| @@ -413,6 +425,7 @@ public: | |||
| 413 | RowsumTAILTILE(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); | 425 | RowsumTAILTILE(lsUbTensor[sUbOffset], llUbTensor[rowOffset], tvUbTensor, round_m, nReal, nStride); |
| 414 | } | 426 | } |
| 415 | 427 | ||
| 428 | + | ||
| 416 | // *** lp = castfp32to16(ls) | 429 | // *** lp = castfp32to16(ls) |
| 417 | if (std::is_same<ElementOutput, bfloat16_t>::value) { | 430 | if (std::is_same<ElementOutput, bfloat16_t>::value) { |
| 418 | AscendC::Cast<ElementOutput, float, false>( | 431 | AscendC::Cast<ElementOutput, float, false>( |
| @@ -426,24 +439,28 @@ public: | |||
| 426 | 439 | ||
| 427 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); | 440 | AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); |
| 428 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); | 441 | AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(pingpongFlag); |
| 442 | + | ||
| 429 | AscendC::DataCopy(gOutput, lpUbTensor[sUbOffset * 2], AscendC::DataCopyParams(m, nStride * 2 / 32, 0, 0)); | 443 | AscendC::DataCopy(gOutput, lpUbTensor[sUbOffset * 2], AscendC::DataCopyParams(m, nStride * 2 / 32, 0, 0)); |
| 430 | - AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(pingpongFlag); | 444 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_MTE2>(gSPingPongFlag); |
| 431 | if (nIdx == 0) { | 445 | if (nIdx == 0) { |
| 432 | // *** gl = ll | 446 | // *** gl = ll |
| 433 | - AscendC::DataCopy(glUbTensor[rowOffset], llUbTensor[rowOffset], | 447 | + AscendC::DataCopy(glUbTensor[taskPingPongFlag][rowOffset], llUbTensor[rowOffset], |
| 434 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); | 448 | AscendC::DataCopyParams(1, round_m / FLOAT_BLOCK_SIZE, 0, 0)); |
| 449 | + | ||
| 435 | AscendC::PipeBarrier<PIPE_V>(); | 450 | AscendC::PipeBarrier<PIPE_V>(); |
| 436 | } else { | 451 | } else { |
| 437 | SetVecMask(m); | 452 | SetVecMask(m); |
| 438 | - // *** gl = dm * gl | 453 | + // // *** gl = dm * gl |
| 439 | AscendC::Mul<float, false>( | 454 | AscendC::Mul<float, false>( |
| 440 | - glUbTensor[rowOffset], dmUbTensor[((nIdx / S_BLOCK_STACK) % 2) * UB_FLOAT_LINE_SIZE + rowOffset], | 455 | + glUbTensor[taskPingPongFlag][rowOffset], dmUbTensor[gSPingPongFlag * UB_FLOAT_LINE_SIZE + rowOffset], |
| 441 | - glUbTensor[rowOffset], (uint64_t)0, 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | 456 | + glUbTensor[taskPingPongFlag][rowOffset], (uint64_t)0, 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); |
| 442 | AscendC::PipeBarrier<PIPE_V>(); | 457 | AscendC::PipeBarrier<PIPE_V>(); |
| 443 | - // *** gl = ll + gl | 458 | + |
| 444 | - AscendC::Add<float, false>(glUbTensor[rowOffset], glUbTensor[rowOffset], llUbTensor[rowOffset], (uint64_t)0, | 459 | + // // *** gl = ll + gl |
| 460 | + AscendC::Add<float, false>(glUbTensor[taskPingPongFlag][rowOffset], glUbTensor[taskPingPongFlag][rowOffset], llUbTensor[rowOffset], (uint64_t)0, | ||
| 445 | 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); | 461 | 1, AscendC::BinaryRepeatParams(1, 1, 1, 8, 8, 8)); |
| 446 | AscendC::PipeBarrier<PIPE_V>(); | 462 | AscendC::PipeBarrier<PIPE_V>(); |
| 463 | + | ||
| 447 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); | 464 | AscendC::SetVectorMask<int8_t>((uint64_t)-1, (uint64_t)-1); |
| 448 | } | 465 | } |
| 449 | } | 466 | } |
| @@ -451,11 +468,12 @@ public: | |||
| 451 | CATLASS_DEVICE | 468 | CATLASS_DEVICE |
| 452 | void operator()(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, | 469 | void operator()(AscendC::GlobalTensor<ElementOutput> gOutput, AscendC::GlobalTensor<ElementInput> gInput, |
| 453 | const LayoutOutput &layoutOutput, const LayoutInput &layoutInput, GemmCoord actualBlockShape, | 470 | const LayoutOutput &layoutOutput, const LayoutInput &layoutInput, GemmCoord actualBlockShape, |
| 454 | - uint32_t nIdx, uint32_t &glFlag) | 471 | + uint32_t nIdx, uint32_t *glFlag, uint32_t taskPingPongFlag, uint32_t gSPingPongFlag) |
| 455 | { | 472 | { |
| 456 | uint32_t cur_head_num = actualBlockShape.m(); | 473 | uint32_t cur_head_num = actualBlockShape.m(); |
| 457 | uint32_t qkN = actualBlockShape.n(); | 474 | uint32_t qkN = actualBlockShape.n(); |
| 458 | uint32_t qkRoundN = layoutInput.stride(0); | 475 | uint32_t qkRoundN = layoutInput.stride(0); |
| 476 | + | ||
| 459 | uint32_t pingpongFlag = 0; | 477 | uint32_t pingpongFlag = 0; |
| 460 | 478 | ||
| 461 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); | 479 | uint32_t subBlockIdx = AscendC::GetSubBlockIdx(); |
| @@ -468,7 +486,7 @@ public: | |||
| 468 | for (uint32_t mInd = 0; mInd < mEnd; mInd++) { | 486 | for (uint32_t mInd = 0; mInd < mEnd; mInd++) { |
| 469 | uint32_t rowOffset = mInd * M_SLICE; | 487 | uint32_t rowOffset = mInd * M_SLICE; |
| 470 | uint32_t currM = mInd == mEnd - 1 ? subM - rowOffset : M_SLICE; | 488 | uint32_t currM = mInd == mEnd - 1 ? subM - rowOffset : M_SLICE; |
| 471 | - uint32_t sUbOffset = pingpongFlag * 8192; | 489 | + uint32_t sUbOffset = gSPingPongFlag * LS_CHUNK_SIZE; |
| 472 | int64_t offsetOutput = rowOffset * qkRoundN; | 490 | int64_t offsetOutput = rowOffset * qkRoundN; |
| 473 | auto gOutputThisSubBlock = gOutput[offsetOutput]; | 491 | auto gOutputThisSubBlock = gOutput[offsetOutput]; |
| 474 | int64_t offsetInput = rowOffset * qkRoundN; | 492 | int64_t offsetInput = rowOffset * qkRoundN; |
| @@ -480,8 +498,9 @@ public: | |||
| 480 | continue; | 498 | continue; |
| 481 | } | 499 | } |
| 482 | SubCoreCompute(gOutputThisSubBlock, gInputThisSubBlock, currM, qkN, qkRoundN, pingpongFlag, rowOffset, | 500 | SubCoreCompute(gOutputThisSubBlock, gInputThisSubBlock, currM, qkN, qkRoundN, pingpongFlag, rowOffset, |
| 483 | - sUbOffset, nIdx, glFlag); | 501 | + sUbOffset, nIdx, glFlag, taskPingPongFlag, gSPingPongFlag); |
| 484 | pingpongFlag = 1 - pingpongFlag; | 502 | pingpongFlag = 1 - pingpongFlag; |
| 503 | + | ||
| 485 | } | 504 | } |
| 486 | } | 505 | } |
| 487 | 506 | ||
| @@ -494,13 +513,14 @@ private: | |||
| 494 | AscendC::LocalTensor<ElementOutput> lpUbTensor; | 513 | AscendC::LocalTensor<ElementOutput> lpUbTensor; |
| 495 | AscendC::LocalTensor<float> lmUbTensor; | 514 | AscendC::LocalTensor<float> lmUbTensor; |
| 496 | AscendC::LocalTensor<float> hmUbTensor; | 515 | AscendC::LocalTensor<float> hmUbTensor; |
| 497 | - AscendC::LocalTensor<float> gmUbTensor; | 516 | + AscendC::LocalTensor<float> gmUbTensor[2]; |
| 498 | AscendC::LocalTensor<float> dmUbTensor; | 517 | AscendC::LocalTensor<float> dmUbTensor; |
| 499 | AscendC::LocalTensor<float> llUbTensor; | 518 | AscendC::LocalTensor<float> llUbTensor; |
| 500 | AscendC::LocalTensor<float> tvUbTensor; | 519 | AscendC::LocalTensor<float> tvUbTensor; |
| 501 | - AscendC::LocalTensor<float> glUbTensor; | 520 | + AscendC::LocalTensor<float> glUbTensor[2]; |
| 502 | 521 | ||
| 503 | Arch::CrossCoreFlag qkReady{QK_READY_ID}; | 522 | Arch::CrossCoreFlag qkReady{QK_READY_ID}; |
| 523 | + | ||
| 504 | }; | 524 | }; |
| 505 | 525 | ||
| 506 | } // namespace Catlass::Epilogue::Block | 526 | } // namespace Catlass::Epilogue::Block |
| @@ -91,6 +91,16 @@ struct EpilogueAtlasA2MLATP1RescaleO { | |||
| 91 | using ArchTag = Arch::AtlasA2; | 91 | using ArchTag = Arch::AtlasA2; |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | +// For AtlasA2, AMLA TP1 Softmax | ||
| 95 | +struct EpilogueAtlasA2AMLATP1Softmax { | ||
| 96 | + using ArchTag = Arch::AtlasA2; | ||
| 97 | +}; | ||
| 98 | + | ||
| 99 | +// For AtlasA2, AMLA TP1 RescaleO | ||
| 100 | +struct EpilogueAtlasA2AMLATP1RescaleO { | ||
| 101 | + using ArchTag = Arch::AtlasA2; | ||
| 102 | +}; | ||
| 103 | + | ||
| 94 | // For AtlasA2, per token dequant | 104 | // For AtlasA2, per token dequant |
| 95 | template <uint32_t UB_STAGES_> | 105 | template <uint32_t UB_STAGES_> |
| 96 | struct EpilogueAtlasA2PerTokenDequant { | 106 | struct EpilogueAtlasA2PerTokenDequant { |
| @@ -33,7 +33,7 @@ struct BlockMmad { | |||
| 33 | static_assert(DEPENDENT_FALSE<DispatchPolicy>, "BlockMmad is not implemented for this DispatchPolicy"); | 33 | static_assert(DEPENDENT_FALSE<DispatchPolicy>, "BlockMmad is not implemented for this DispatchPolicy"); |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | -#if (defined (CATLASS_ARCH) && CATLASS_ARCH == 2201) | 36 | +#if (defined (CATLASS_ARCH) && CATLASS_ARCH == 2201) |
| 37 | /// new add for the reason that i am using the dispatchpolicy which is same as the policy of the optimized_matmul | 37 | /// new add for the reason that i am using the dispatchpolicy which is same as the policy of the optimized_matmul |
| 38 | // so i add a new one class to avoid the conflict | 38 | // so i add a new one class to avoid the conflict |
| 39 | template < | 39 | template < |
| @@ -137,6 +137,9 @@ struct BlockPrologue { | |||
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | 139 | ||
| 140 | + | ||
| 141 | + | ||
| 142 | + | ||
| 140 | 143 | ||
| 141 | 144 | ||
| 142 | 145 | ||
新增文件的copyright修改为2026,统一排查下