已合并
TopkV2算子性能优化 #2821
cy_hw创建于 5月19日
TopkV2算子性能优化 #2821
已合并
共 7 个文件变更+1841-394
| @@ -50,7 +50,7 @@ public: | |||
| 50 | const SortRegBaseTilingData* tilingData, TPipe* pipe); | 50 | const SortRegBaseTilingData* tilingData, TPipe* pipe); |
| 51 | __aicore__ inline void Process(); | 51 | __aicore__ inline void Process(); |
| 52 | 52 | ||
| 53 | -private: | 53 | +protected: |
| 54 | struct MergeListContext { | 54 | struct MergeListContext { |
| 55 | uint32_t remains[MERGE_LIST_MAX_NUM] = {0}; | 55 | uint32_t remains[MERGE_LIST_MAX_NUM] = {0}; |
| 56 | uint32_t gmOffsets[MERGE_LIST_MAX_NUM] = {0}; | 56 | uint32_t gmOffsets[MERGE_LIST_MAX_NUM] = {0}; |
| @@ -30,6 +30,10 @@ const uint32_t BIN_NUM = 256; | |||
| 30 | const uint32_t TILE_SIZE_DECREASING_FACTOR = 32; | 30 | const uint32_t TILE_SIZE_DECREASING_FACTOR = 32; |
| 31 | const uint32_t TMP_DATA_NUM = 7680; // 默认UB一次性能处理的非64位数据的个数,可根据场景动态调整 | 31 | const uint32_t TMP_DATA_NUM = 7680; // 默认UB一次性能处理的非64位数据的个数,可根据场景动态调整 |
| 32 | const uint32_t TMP_DATA_NUM_B64 = 5120; // 默认UB一次性能处理的64位数据的个数,可根据场景动态调整 | 32 | const uint32_t TMP_DATA_NUM_B64 = 5120; // 默认UB一次性能处理的64位数据的个数,可根据场景动态调整 |
| 33 | +const uint32_t SINGLE_BLOCK_DATA_NUM = 15360; | ||
| 34 | +const uint32_t SINGLE_BLOCK_DATA_NUM_B64 = 10240; | ||
| 35 | +const uint32_t SINGLE_CORE_DATA_NUM = 15360; | ||
| 36 | +const uint32_t SINGLE_CORE_DATA_NUM_B64 = 10240; | ||
| 33 | const uint64_t AGLIN_FACTOR = 32; | 37 | const uint64_t AGLIN_FACTOR = 32; |
| 34 | const uint32_t SMALL_MAX_DATA_SZIE = 1024; | 38 | const uint32_t SMALL_MAX_DATA_SZIE = 1024; |
| 35 | const uint32_t MERGE_SORT_TILING_OFFSET = 10000; | 39 | const uint32_t MERGE_SORT_TILING_OFFSET = 10000; |
| @@ -38,6 +42,8 @@ const uint32_t MULT_CORE_MODE = 2; | |||
| 38 | const uint32_t MULT_CORE_OPTIM_MODE = 4; | 42 | const uint32_t MULT_CORE_OPTIM_MODE = 4; |
| 39 | const uint32_t SINGLE_BLOCK_MODE = 3; | 43 | const uint32_t SINGLE_BLOCK_MODE = 3; |
| 40 | const uint32_t SORT_AND_TOP_K_MODE = 5; | 44 | const uint32_t SORT_AND_TOP_K_MODE = 5; |
| 45 | +const uint32_t FP32_MERGE_MORE_CORE_MODE = 6; | ||
| 46 | +const uint32_t FP32_MERGE_INTRA_CORE_MODE = 7; | ||
| 41 | const uint32_t INT64_BYTE = 8; | 47 | const uint32_t INT64_BYTE = 8; |
| 42 | const uint32_t INT32_BYTE = 4; | 48 | const uint32_t INT32_BYTE = 4; |
| 43 | // SortAndTopk的阈值,排序轴大于该阈值的场景,走sortAndTopK模板 | 49 | // SortAndTopk的阈值,排序轴大于该阈值的场景,走sortAndTopK模板 |
| @@ -45,6 +51,17 @@ const uint32_t SORT_AND_TOP_K_THRESHOLD = 10000000; | |||
| 45 | const uint32_t CONST_SIMT_SPACE = 32768; // 获取到的UB大小需要预留32KB给simt | 51 | const uint32_t CONST_SIMT_SPACE = 32768; // 获取到的UB大小需要预留32KB给simt |
| 46 | const uint32_t SUPPORT_SORT_MAX_BYTE_SIZE = 8000; | 52 | const uint32_t SUPPORT_SORT_MAX_BYTE_SIZE = 8000; |
| 47 | const uint32_t SUPPORT_SORT_MAX_SIZE = 2000; | 53 | const uint32_t SUPPORT_SORT_MAX_SIZE = 2000; |
| 54 | +const uint32_t TOPK_MERGE_SORT_MORE_CORE_TILING_KEY_FLOAT = 23003; | ||
| 55 | +const uint32_t TOPK_MERGE_SORT_INTRA_CORE_TILING_KEY_FLOAT = 33003; | ||
| 56 | +const double FP32_K_LAST_AXIS_LOWER_RATIO = 0.25; | ||
| 57 | +const double FP32_K_LAST_AXIS_UPPER_RATIO = 0.50; | ||
| 58 | +const uint32_t SORT_STRUCT_SIZE_FP32 = 8; | ||
| 59 | +const uint32_t FP32_MERGE_SORT_MAX_SIZE = 4096; | ||
| 60 | +const uint32_t MERGE_SORT_DISABLE_DOUBLE_BUFFER_SIZE = 2048; | ||
| 61 | +const uint32_t MERGE_MORE_CORE_ONE_CORE_DATA_SIZE = 2048; | ||
| 62 | +const uint32_t MERGE_MORE_CORE_LIST_MAX_NUM = 4; | ||
| 63 | +const uint32_t MERGE_INTRA_CORE_SORT_ALIGN = 32; | ||
| 64 | +const uint32_t MERGE_INTRA_CORE_MAX_BLOCKS = 256; | ||
| 48 | const float LAST_LOOP_CORE_UTILIZATION = 0.7; | 65 | const float LAST_LOOP_CORE_UTILIZATION = 0.7; |
| 49 | const uint32_t SMALL_LOOP_UPPER_NUM = 4; | 66 | const uint32_t SMALL_LOOP_UPPER_NUM = 4; |
| 50 | const uint32_t SMALL_LOOP_LOWER_NUM = 2; | 67 | const uint32_t SMALL_LOOP_LOWER_NUM = 2; |
| @@ -70,6 +87,7 @@ struct TopkTileInfo { | |||
| 70 | uint32_t tailBatchNum = 0; | 87 | uint32_t tailBatchNum = 0; |
| 71 | uint32_t tailTileNum = 0; | 88 | uint32_t tailTileNum = 0; |
| 72 | int64_t topKOutLastAxisNum = 0; | 89 | int64_t topKOutLastAxisNum = 0; |
| 90 | + bool multiCoreBigModel = false; | ||
| 73 | }; | 91 | }; |
| 74 | struct SortTileInfo { | 92 | struct SortTileInfo { |
| 75 | uint32_t coreNumNeed = 0; | 93 | uint32_t coreNumNeed = 0; |
| @@ -102,7 +120,7 @@ struct SortTileInfo { | |||
| 102 | uint32_t blockTileNum = 0; | 120 | uint32_t blockTileNum = 0; |
| 103 | uint32_t tailTileNum = 0; | 121 | uint32_t tailTileNum = 0; |
| 104 | }; | 122 | }; |
| 105 | -struct TopkComputingNowTileSizeInfo { | 123 | +struct TopkComputeNowTileSizeInfo { |
| 106 | ge::DataType dataType; | 124 | ge::DataType dataType; |
| 107 | ge::DataType indicesDType; | 125 | ge::DataType indicesDType; |
| 108 | bool isLargest = true; | 126 | bool isLargest = true; |
| @@ -113,6 +131,7 @@ struct TopkComputingNowTileSizeInfo { | |||
| 113 | uint32_t maxCoreNum = 0; | 131 | uint32_t maxCoreNum = 0; |
| 114 | uint64_t ubSizePlatForm = 0; | 132 | uint64_t ubSizePlatForm = 0; |
| 115 | uint64_t ubBlockAlignSize = 0; // ub的对齐数值,当前为32 | 133 | uint64_t ubBlockAlignSize = 0; // ub的对齐数值,当前为32 |
| 134 | + uint32_t unsortedDimNum = 0; | ||
| 116 | }; | 135 | }; |
| 117 | static const std::map<ge::DataType, uint32_t> tilingDataTypeKeyMap = { | 136 | static const std::map<ge::DataType, uint32_t> tilingDataTypeKeyMap = { |
| 118 | {ge::DT_INT64, 1004}, {ge::DT_INT32, 1003}, {ge::DT_INT16, 1002}, {ge::DT_INT8, 1001}, | 137 | {ge::DT_INT64, 1004}, {ge::DT_INT32, 1003}, {ge::DT_INT16, 1002}, {ge::DT_INT8, 1001}, |
| @@ -127,50 +146,65 @@ static const std::map<ge::DataType, uint32_t> optDataTypeBitMap = { | |||
| 127 | static const std::map<ge::DataType, uint32_t> b64DataTypeBitMap = {{ge::DT_INT64, 8}, {ge::DT_UINT64, 8}}; | 146 | static const std::map<ge::DataType, uint32_t> b64DataTypeBitMap = {{ge::DT_INT64, 8}, {ge::DT_UINT64, 8}}; |
| 128 | } // namespace topkV2DataInfo | 147 | } // namespace topkV2DataInfo |
| 129 | 148 | ||
| 130 | -uint32_t CeilAlignDiv(int64_t a, int64_t b) | 149 | +// ==================== Helper Functions ==================== |
| 150 | + | ||
| 151 | + | ||
| 152 | +inline uint32_t GetDataTypeSize(ge::DataType dataType) | ||
R | |||
| 131 | { | 153 | { |
| 132 | - if (b == 0) { | 154 | + return topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second; |
| 133 | - return static_cast<uint32_t>(a); | ||
| 134 | - } | ||
| 135 | - return static_cast<uint32_t>((a + b - 1) / b); | ||
| 136 | } | 155 | } |
| 137 | 156 | ||
| 138 | -template <typename T> | 157 | +inline bool IsDataType64Bit(ge::DataType dataType) |
| 139 | -auto CeilAlignDivMul(int64_t a, int64_t b) -> T const | ||
| 140 | { | 158 | { |
| 141 | - if (b == 0) { | 159 | + return topkV2DataInfo::b64DataTypeBitMap.count(dataType) != 0; |
| 142 | - return static_cast<T>(a); | 160 | +} |
| 143 | - } | 161 | + |
| 144 | - return static_cast<T>(((a + b - 1) / b) * b); | 162 | +inline uint32_t GetDefaultTileDataSize(ge::DataType dataType) |
| 163 | +{ | ||
| 164 | + return IsDataType64Bit(dataType) ? topkV2DataInfo::TMP_DATA_NUM_B64 : | ||
| 165 | + topkV2DataInfo::TMP_DATA_NUM; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +inline uint32_t GetSingleBlockModelDefaultTileDataSize(ge::DataType dataType) | ||
| 169 | +{ | ||
| 170 | + return IsDataType64Bit(dataType) ? topkV2DataInfo::SINGLE_BLOCK_DATA_NUM_B64 : | ||
| 171 | + topkV2DataInfo::SINGLE_BLOCK_DATA_NUM; | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +inline uint32_t GetSingleCoreModelDefaultTileDataSize(ge::DataType dataType) | ||
| 175 | +{ | ||
| 176 | + return IsDataType64Bit(dataType) ? topkV2DataInfo::SINGLE_CORE_DATA_NUM_B64 : | ||
| 177 | + topkV2DataInfo::SINGLE_CORE_DATA_NUM; | ||
| 145 | } | 178 | } |
| 146 | 179 | ||
| 147 | ge::graphStatus GetTopkApiTmpBufferSize( | 180 | ge::graphStatus GetTopkApiTmpBufferSize( |
| 148 | gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, uint32_t needDataNum, int64_t kValue, | 181 | gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, uint32_t needDataNum, int64_t kValue, |
| 149 | bool isLargest, ge::DataType dtype, bool isSort, uint32_t nowTileSize) | 182 | bool isLargest, ge::DataType dtype, bool isSort, uint32_t nowTileSize) |
| 150 | { | 183 | { |
| 151 | - uint32_t maxBufferSize = 0; | 184 | + uint32_t aglinInnerValue = |
| 152 | - uint32_t minBufferSize = 0; | 185 | + static_cast<uint32_t>(Ops::Base::CeilAlign(static_cast<uint64_t>(needDataNum), topkV2DataInfo::AGLIN_FACTOR)); |
| 153 | - uint32_t aglinInnerValue = ((needDataNum + topkV2DataInfo::AGLIN_FACTOR - 1) / topkV2DataInfo::AGLIN_FACTOR) * | 186 | + |
| 154 | - topkV2DataInfo::AGLIN_FACTOR; | 187 | + uint32_t aglinKValue = (topkTilingData.get_modeType() == topkV2DataInfo::SINGLE_CORE_MODE) ? |
| 155 | - uint32_t aglinKValue = 0; | 188 | + std::min(static_cast<int64_t>(needDataNum), kValue) : |
| 156 | - if (topkTilingData.get_modeType() == topkV2DataInfo::SINGLE_CORE_MODE) { | 189 | + std::min(static_cast<int64_t>(nowTileSize), kValue); |
| 157 | - aglinKValue = std::min(static_cast<int64_t>(needDataNum), kValue); | 190 | + |
| 158 | - } else { | ||
| 159 | - aglinKValue = std::min(static_cast<int64_t>(nowTileSize), kValue); | ||
| 160 | - } | ||
| 161 | AscendC::TopKConfig topkConfig; | 191 | AscendC::TopKConfig topkConfig; |
| 162 | topkConfig.algo = AscendC::TopKAlgo::RADIX_SELECT; | 192 | topkConfig.algo = AscendC::TopKAlgo::RADIX_SELECT; |
| 163 | topkConfig.order = AscendC::TopKOrder::UNSET; | 193 | topkConfig.order = AscendC::TopKOrder::UNSET; |
| 164 | topkConfig.sorted = isSort; | 194 | topkConfig.sorted = isSort; |
| 195 | + | ||
| 196 | + uint32_t maxBufferSize = 0; | ||
| 197 | + uint32_t minBufferSize = 0; | ||
| 165 | bool isSuccess = AscendC::GetTopKMaxMinTmpSize( | 198 | bool isSuccess = AscendC::GetTopKMaxMinTmpSize( |
| 166 | - aglinInnerValue, 1, aglinKValue, false, false, AscendC::TopKMode::TOPK_NORMAL, isLargest, dtype, topkConfig, | 199 | + aglinInnerValue, 1, aglinKValue, false, false, AscendC::TopKMode::TOPK_NORMAL, |
| 167 | - maxBufferSize, minBufferSize); | 200 | + isLargest, dtype, topkConfig, maxBufferSize, minBufferSize); |
| 168 | - OP_LOGI("TopKV2TilingForAscendC", "Need tmp buffer %u byte for ac sort topk api", maxBufferSize); | 201 | + |
| 169 | - OP_LOGI( | 202 | + OP_LOGI("TopKV2TilingForAscendC", "TopK API buffer: kValue=%ld, alignedK=%u, alignedInner=%u, bufferSize=%u", |
| 170 | - "TopKV2TilingForAscendC", "Init kValue=%ld aglinKValue=%u aglinInnerValue=%u", kValue, aglinKValue, | 203 | + kValue, aglinKValue, aglinInnerValue, maxBufferSize); |
| 171 | - aglinInnerValue); | 204 | + |
| 172 | - OP_CHECK_IF( | 205 | + OP_CHECK_IF(!isSuccess, OP_LOGE(context->GetNodeName(), "Failed to get TopK API buffer size"), |
| 173 | - false == isSuccess, OP_LOGE(context->GetNodeName(), "Get topk api temp buffer fail"), return ge::GRAPH_FAILED); | 206 | + return ge::GRAPH_FAILED); |
| 207 | + | ||
| 174 | topkTilingData.set_topkAcApiTmpBufferSize(maxBufferSize); | 208 | topkTilingData.set_topkAcApiTmpBufferSize(maxBufferSize); |
| 175 | return ge::GRAPH_SUCCESS; | 209 | return ge::GRAPH_SUCCESS; |
| 176 | } | 210 | } |
| @@ -180,68 +214,67 @@ uint64_t GetTopkMultiCoreRunTimeNeedSpace( | |||
| 180 | uint32_t indexDtypeSize, int64_t kValue) | 214 | uint32_t indexDtypeSize, int64_t kValue) |
| 181 | { | 215 | { |
| 182 | OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData is 0"), return ge::GRAPH_FAILED); | 216 | OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData is 0"), return ge::GRAPH_FAILED); |
| 183 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return ge::GRAPH_FAILED); | ||
| 184 | 217 | ||
| 218 | + uint64_t aglinFactor = topkV2DataInfo::AGLIN_FACTOR; | ||
| 185 | uint32_t lastDimTileNum = (static_cast<uint32_t>(lastAxisNum) + tileData - 1) / tileData; | 219 | uint32_t lastDimTileNum = (static_cast<uint32_t>(lastAxisNum) + tileData - 1) / tileData; |
| 186 | uint32_t lastDimTileNumTimes = (lastDimTileNum + maxCoreNum - 1) / maxCoreNum; | 220 | uint32_t lastDimTileNumTimes = (lastDimTileNum + maxCoreNum - 1) / maxCoreNum; |
| 221 | + uint64_t lastDimTileNumTimesAlign = | ||
| 222 | + Ops::Base::CeilAlign(static_cast<uint64_t>(sizeof(uint32_t) * lastDimTileNumTimes), aglinFactor); | ||
| 187 | uint64_t initUb = indexDtypeSize * topkV2DataInfo::BIN_NUM * (lastDimTileNumTimes + 1) + | 223 | uint64_t initUb = indexDtypeSize * topkV2DataInfo::BIN_NUM * (lastDimTileNumTimes + 1) + |
| 188 | - Ops::Base::CeilAlign( | 224 | + lastDimTileNumTimesAlign * topkV2DataInfo::CONST_TWO; |
| 189 | - static_cast<uint64_t>(sizeof(uint32_t) * lastDimTileNumTimes), topkV2DataInfo::AGLIN_FACTOR) * | 225 | + |
| 190 | - topkV2DataInfo::CONST_TWO; | ||
| 191 | uint32_t factor = xDtypeSize * topkV2DataInfo::CONST_TWO + indexDtypeSize + indexToDtypeSize; | 226 | uint32_t factor = xDtypeSize * topkV2DataInfo::CONST_TWO + indexDtypeSize + indexToDtypeSize; |
| 192 | 227 | ||
| 193 | if (tileData < kValue) { | 228 | if (tileData < kValue) { |
| 194 | factor += xDtypeSize + indexToDtypeSize + sizeof(int32_t); | 229 | factor += xDtypeSize + indexToDtypeSize + sizeof(int32_t); |
| 195 | } else { | 230 | } else { |
| 196 | - initUb += Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * sizeof(int32_t)), topkV2DataInfo::AGLIN_FACTOR) + | 231 | + initUb += Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * sizeof(int32_t)), aglinFactor) + |
| 197 | - Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * xDtypeSize), topkV2DataInfo::AGLIN_FACTOR) + | 232 | + Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * xDtypeSize), aglinFactor) + |
| 198 | - Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * indexToDtypeSize), topkV2DataInfo::AGLIN_FACTOR); | 233 | + Ops::Base::CeilAlign(static_cast<uint64_t>(kValue * indexToDtypeSize), aglinFactor); |
| 199 | } | 234 | } |
| 200 | - OP_LOGI( | 235 | + OP_LOGI("TopKV2TilingForAscendC", "tileData=%u, initUb=%u, factor = %u", tileData, initUb, factor); |
| 201 | - "TopKV2TilingForAscendC", "GetTopkTempBuffer tileData=%u, initUb=%u, factor = %u", tileData, initUb, factor); | ||
| 202 | return initUb + factor * tileData; | 236 | return initUb + factor * tileData; |
| 203 | } | 237 | } |
| 204 | 238 | ||
| 205 | -uint32_t ComputeTopkTileData( | 239 | +uint32_t ComputeTopkRadixMoreCoreTileData(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, |
| 206 | - gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | 240 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computeNowTileSizeInfo) |
| 207 | - topkV2DataInfo::TopkComputingNowTileSizeInfo& computingNowTileSizeInfo) | ||
| 208 | { | 241 | { |
| 209 | - ge::DataType dataType = computingNowTileSizeInfo.dataType; | 242 | + uint32_t xDtypeSize = GetDataTypeSize(computeNowTileSizeInfo.dataType); |
| 210 | - ge::DataType indicesDType = computingNowTileSizeInfo.indicesDType; | 243 | + uint32_t indexDtypeSize = GetDataTypeSize(computeNowTileSizeInfo.indicesDType); |
| 211 | - bool isLargest = computingNowTileSizeInfo.isLargest; | 244 | + uint32_t tileData = GetDefaultTileDataSize(computeNowTileSizeInfo.dataType); |
| 212 | - bool isSort = computingNowTileSizeInfo.isSort; | ||
| 213 | - int64_t lastAxisNum = computingNowTileSizeInfo.lastAxisNum; | ||
| 214 | - int64_t kValue = computingNowTileSizeInfo.kValue; | ||
| 215 | - uint32_t maxCoreNum = computingNowTileSizeInfo.maxCoreNum; | ||
| 216 | - uint64_t ubSizePlatForm = computingNowTileSizeInfo.ubSizePlatForm; | ||
| 217 | - | ||
| 218 | - uint32_t xDtypeSize = topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second; | ||
| 219 | - uint32_t indexDtypeSize = topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second; | ||
| 220 | - | ||
| 221 | - uint32_t tileData = (topkV2DataInfo::b64DataTypeBitMap.count(dataType) != 0) ? | ||
| 222 | - topkV2DataInfo::TMP_DATA_NUM_B64 : topkV2DataInfo::TMP_DATA_NUM; | ||
| 223 | 245 | ||
| 224 | uint64_t runTimeNeedSpace = GetTopkMultiCoreRunTimeNeedSpace( | 246 | uint64_t runTimeNeedSpace = GetTopkMultiCoreRunTimeNeedSpace( |
| 225 | - lastAxisNum, tileData, maxCoreNum, xDtypeSize, indexDtypeSize, indexDtypeSize, kValue); | 247 | + computeNowTileSizeInfo.lastAxisNum, tileData, computeNowTileSizeInfo.maxCoreNum, xDtypeSize, |
| 226 | - int64_t lastDimTileNum = CeilAlignDiv(lastAxisNum, static_cast<int64_t>(tileData)); | 248 | + indexDtypeSize, indexDtypeSize, computeNowTileSizeInfo.kValue); |
| 227 | - int64_t maxInputK = std::max(lastDimTileNum, kValue); | 249 | + |
| 250 | + int64_t lastDimTileNum = | ||
| 251 | + Ops::Base::CeilDiv(static_cast<uint64_t>(computeNowTileSizeInfo.lastAxisNum), static_cast<uint64_t>(tileData)); | ||
| 252 | + int64_t maxInputK = std::max(lastDimTileNum, computeNowTileSizeInfo.kValue); | ||
| 228 | 253 | ||
| 229 | - GetTopkApiTmpBufferSize(context, topkTilingData, tileData, maxInputK, isLargest, dataType, isSort, tileData); | 254 | + GetTopkApiTmpBufferSize(context, topkTilingData, tileData, maxInputK, computeNowTileSizeInfo.isLargest, |
| 255 | + computeNowTileSizeInfo.dataType, computeNowTileSizeInfo.isSort, tileData); | ||
| 230 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 256 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 231 | 257 | ||
| 232 | - while (topkAcApiNeedBuffer + runTimeNeedSpace > ubSizePlatForm) { | 258 | + while (topkAcApiNeedBuffer + runTimeNeedSpace > computeNowTileSizeInfo.ubSizePlatForm) { |
| 233 | tileData -= topkV2DataInfo::BIN_NUM; | 259 | tileData -= topkV2DataInfo::BIN_NUM; |
| 234 | - OP_CHECK_IF(tileData <= 0, OP_LOGE("TopkV2", "tileData is less than 0."), return ge::GRAPH_FAILED); | 260 | + if (tileData <= 0) { |
| 235 | - | 261 | + OP_LOGD("TopKV2TilingForAscendC", "tileData is less than or equal to 0."); |
| 236 | - lastDimTileNum = CeilAlignDiv(lastAxisNum, static_cast<int64_t>(tileData)); | 262 | + return tileData; |
| 237 | - maxInputK = std::max(lastDimTileNum, kValue); | 263 | + } |
| 238 | - GetTopkApiTmpBufferSize(context, topkTilingData, tileData, maxInputK, isLargest, dataType, isSort, tileData); | 264 | + |
| 265 | + lastDimTileNum = | ||
| 266 | + Ops::Base::CeilDiv(static_cast<uint64_t>(computeNowTileSizeInfo.lastAxisNum), static_cast<uint64_t>(tileData)); | ||
| 267 | + maxInputK = std::max(lastDimTileNum, computeNowTileSizeInfo.kValue); | ||
| 268 | + GetTopkApiTmpBufferSize(context, topkTilingData, tileData, maxInputK, computeNowTileSizeInfo.isLargest, | ||
| 269 | + computeNowTileSizeInfo.dataType, computeNowTileSizeInfo.isSort, tileData); | ||
| 270 | + | ||
| 239 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 271 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 240 | runTimeNeedSpace = GetTopkMultiCoreRunTimeNeedSpace( | 272 | runTimeNeedSpace = GetTopkMultiCoreRunTimeNeedSpace( |
| 241 | - lastAxisNum, tileData, maxCoreNum, xDtypeSize, indexDtypeSize, indexDtypeSize, kValue); | 273 | + computeNowTileSizeInfo.lastAxisNum, tileData, computeNowTileSizeInfo.maxCoreNum, xDtypeSize, |
| 274 | + indexDtypeSize, indexDtypeSize, computeNowTileSizeInfo.kValue); | ||
| 242 | } | 275 | } |
| 243 | 276 | ||
| 244 | - OP_LOGI("TopKV2TilingForAscendC", "tileData=%u, ApiTempBuffer=%u", tileData, topkAcApiNeedBuffer); | 277 | + OP_LOGI("TopKV2TilingForAscendC", "Multi-core tile: data=%u, apiBuffer=%u", tileData, topkAcApiNeedBuffer); |
| 245 | return tileData; | 278 | return tileData; |
| 246 | } | 279 | } |
| 247 | 280 | ||
| @@ -257,85 +290,132 @@ bool IsLastLoopCoreUtilizationSuccess(uint32_t unsortedDimNum, uint32_t tmpOneCo | |||
| 257 | return true; | 290 | return true; |
| 258 | } | 291 | } |
| 259 | // 最后一次loop剩余待处理的轴数量/每个核处理的dim要大于0.7,确保最后一个loop有超过一半的核在处理,尽可能提高利用率 | 292 | // 最后一次loop剩余待处理的轴数量/每个核处理的dim要大于0.7,确保最后一个loop有超过一半的核在处理,尽可能提高利用率 |
| 260 | - if (sortLoopTimes >= topkV2DataInfo::SMALL_LOOP_LOWER_NUM && sortLoopTimes <= topkV2DataInfo::SMALL_LOOP_UPPER_NUM && | 293 | + bool loopTimesCondition = sortLoopTimes >= topkV2DataInfo::SMALL_LOOP_LOWER_NUM && |
| 261 | - lastLoopDimNeedCoreNum < maxCoreNum * topkV2DataInfo::LAST_LOOP_CORE_UTILIZATION) { | 294 | + sortLoopTimes <= topkV2DataInfo::SMALL_LOOP_UPPER_NUM; |
| 295 | + bool utilizationCondition = lastLoopDimNeedCoreNum < maxCoreNum * topkV2DataInfo::LAST_LOOP_CORE_UTILIZATION; | ||
| 296 | + if (loopTimesCondition && utilizationCondition) { | ||
| 262 | return false; | 297 | return false; |
| 263 | } | 298 | } |
| 264 | return true; | 299 | return true; |
| 265 | } | 300 | } |
| 266 | 301 | ||
| 267 | -uint32_t ComputeMergeSortTileData( | 302 | +uint32_t GetTileDataForMergeSort(uint32_t unsortedDimNum, uint32_t maxCoreNum, |
| 268 | - TopKV2TilingDataSimd& topkTilingData, ge::DataType dataType, ge::DataType indicesDType, int64_t lastAxisNum, | 303 | + uint32_t tileMaxData, uint32_t bufferNum, uint32_t aglinNum) |
| 269 | - uint32_t maxCoreNum, uint32_t unsortedDimNum, uint64_t ubSizePlatForm) | ||
| 270 | { | 304 | { |
| 271 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | 305 | + OP_CHECK_IF(bufferNum == 0, OP_LOGE("TopkV2", "mergeSort tiling bufferNum is invalid."), |
| 272 | - uint32_t indexToDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second); | 306 | + return topkV2DataInfo::SMALL_MAX_DATA_SZIE); |
| 273 | - uint32_t convertTypeSize = (dataType == ge::DT_BF16) ? | 307 | + OP_CHECK_IF(aglinNum == 0, OP_LOGE("TopkV2", "mergeSort tiling aglinNum is invalid."), |
| 274 | - topkV2DataInfo::optDataTypeBitMap.find(ge::DT_FLOAT)->second : | 308 | + return topkV2DataInfo::SMALL_MAX_DATA_SZIE); |
| 275 | - topkV2DataInfo::optDataTypeBitMap.find(dataType)->second; | 309 | + |
| 310 | + uint32_t tileData = topkV2DataInfo::TMP_DATA_NUM; | ||
| 311 | + uint32_t oneCoreRowNum = (tileData / bufferNum) / aglinNum; | ||
| 312 | + // 按照每个核处理默认的 tileData 来计算一个核最多能处理多少行 | ||
| 313 | + oneCoreRowNum = (oneCoreRowNum == 0) ? 1 : oneCoreRowNum; | ||
| 314 | + // virUnsortedDimNeedCoreNum: 默认最少需要多少核数 | ||
| 315 | + uint32_t virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 316 | + | ||
| 317 | + // 默认最少需要的核数如果少于总核数, 说明如果按照之前的逻辑,会有核空闲,此时就应该将 unsortedDimNum | ||
| 318 | + // 均摊到所有的核上处理,然后返回tileData | ||
| 319 | + if (virUnsortedDimNeedCoreNum < maxCoreNum) { | ||
| 320 | + oneCoreRowNum = (unsortedDimNum + maxCoreNum - 1) / maxCoreNum; | ||
| 321 | + oneCoreRowNum = (oneCoreRowNum == 0) ? 1 : oneCoreRowNum; | ||
| 322 | + virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 323 | + tileData = oneCoreRowNum * bufferNum * aglinNum; | ||
| 324 | + tileData = std::min(tileData, tileMaxData - topkV2DataInfo::BIN_NUM); | ||
| 325 | + return tileData; | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + // 按照的默认tileData来计算需要的虚拟核数比总核数还多,说明tileData切分较小,没有最大限度利用最大处理tileMaxData数据能力 | ||
| 329 | + // 在不大于tileMaxData的条件下需要适当增加 | ||
| 330 | + while (virUnsortedDimNeedCoreNum >= maxCoreNum && topkV2DataInfo::BIN_NUM + tileData < tileMaxData) { | ||
| 331 | + tileData += topkV2DataInfo::BIN_NUM; | ||
| 332 | + oneCoreRowNum = (tileData / bufferNum) / aglinNum; | ||
| 333 | + oneCoreRowNum = (oneCoreRowNum == 0) ? 1 : oneCoreRowNum; | ||
| 334 | + virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 335 | + } | ||
| 336 | + | ||
| 337 | + uint32_t tmpTileData = tileData; | ||
| 338 | + // 在经过上述操作后的tileData, 可能导致在多loop中, 前几个loop核数处理数据比较理想,但是存在最后一个loop | ||
| 339 | + // 的极少数尾轴只有1个或者少数几个核在处理,导致最后一个loop将整个处理时间拉长,此时需要平衡最后一个loop, | ||
| 340 | + // 将tileData适当减少,使得处理尾loop的核数占总核数达到一定比例(0.7),确保每个loop都是均匀处理数据 | ||
| 341 | + while (!IsLastLoopCoreUtilizationSuccess(unsortedDimNum, oneCoreRowNum, maxCoreNum)) { | ||
| 342 | + if (tileData < topkV2DataInfo::BIN_NUM) { | ||
| 343 | + OP_LOGD("TopKV2TilingForAscendC", "tileData optimization =%u", tmpTileData); | ||
| 344 | + return tmpTileData; | ||
| 345 | + } | ||
| 346 | + tileData -= topkV2DataInfo::BIN_NUM; | ||
| 347 | + oneCoreRowNum = (tileData / bufferNum) / aglinNum; | ||
| 348 | + oneCoreRowNum = (oneCoreRowNum == 0) ? 1 : oneCoreRowNum; | ||
| 349 | + virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 350 | + } | ||
| 351 | + | ||
| 352 | + return tileData; | ||
| 353 | +} | ||
| 354 | + | ||
| 355 | +uint32_t ComputeMergeSortTileData( | ||
| 356 | + TopKV2TilingDataSimd& topkTilingData, topkV2DataInfo::TopkComputeNowTileSizeInfo& computeTileSizeInfo) | ||
| 357 | +{ | ||
| 358 | + | ||
| 359 | + ge::DataType dataType = computeTileSizeInfo.dataType; | ||
| 360 | + ge::DataType indicesDType = computeTileSizeInfo.indicesDType; | ||
| 361 | + int64_t lastAxisNum = computeTileSizeInfo.lastAxisNum; | ||
| 362 | + uint32_t maxCoreNum = computeTileSizeInfo.maxCoreNum; | ||
| 363 | + uint32_t unsortedDimNum= computeTileSizeInfo.unsortedDimNum; | ||
| 364 | + uint64_t ubSizePlatForm = computeTileSizeInfo.ubSizePlatForm; | ||
| 365 | + | ||
| 366 | + uint32_t xDtypeSize = GetDataTypeSize(dataType); | ||
| 367 | + uint32_t indexToDtypeSize = GetDataTypeSize(indicesDType); | ||
| 368 | + uint32_t convertTypeSize = (dataType == ge::DT_BF16) ? GetDataTypeSize(ge::DT_FLOAT) : | ||
| 369 | + GetDataTypeSize(dataType); | ||
| 276 | 370 | ||
| 277 | uint32_t mergeSortAcApiNeedBuffer = topkTilingData.get_mergSortAcApiNeedBufferSize(); | 371 | uint32_t mergeSortAcApiNeedBuffer = topkTilingData.get_mergSortAcApiNeedBufferSize(); |
| 278 | uint32_t initUb = ubSizePlatForm - mergeSortAcApiNeedBuffer; | 372 | uint32_t initUb = ubSizePlatForm - mergeSortAcApiNeedBuffer; |
| 373 | + OP_LOGD("TopKV2TilingForAscendC", "merge sort mergeSortAcApiNeedBuffer=%u, ubSizePlatForm=%u, " | ||
| 374 | + "convertTypeSize=%u", mergeSortAcApiNeedBuffer, ubSizePlatForm, convertTypeSize); | ||
| 375 | + | ||
| 279 | uint32_t aglinNum = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / | 376 | uint32_t aglinNum = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / |
| 280 | topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; | 377 | topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; |
| 281 | - uint32_t oneCoreRowNumSize = initUb - aglinNum * sizeof(uint32_t) - | 378 | + uint32_t bufferNum = lastAxisNum >= topkV2DataInfo::MERGE_SORT_DISABLE_DOUBLE_BUFFER_SIZE ? |
| 282 | - aglinNum * topkV2DataInfo::CONST_TWO * convertTypeSize * topkV2DataInfo::INT64_BYTE; | 379 | + 1 : topkV2DataInfo::CONST_TWO; |
| 283 | - uint32_t oneCoreRowNumMax = | 380 | + uint32_t initSpace = aglinNum * sizeof(uint32_t) + |
| 284 | - oneCoreRowNumSize / (aglinNum * topkV2DataInfo::CONST_TWO * | 381 | + aglinNum * topkV2DataInfo::CONST_TWO * convertTypeSize * topkV2DataInfo::INT64_BYTE; |
| 285 | - (topkV2DataInfo::CONST_TWO * xDtypeSize + indexToDtypeSize + convertTypeSize)); | ||
| 286 | - uint32_t tileMaxData = oneCoreRowNumMax * aglinNum * 2; | ||
| 287 | - OP_LOGI("TopKV2TilingForAscendC", "tileMaxData=%u, maxCoreNum=%u", tileMaxData, maxCoreNum); | ||
| 288 | 382 | ||
| 289 | - | 383 | + if (initUb < initSpace) { |
| 290 | - // 思路:1.占满核,均匀分核 2.循环数尽可能小 | 384 | + OP_LOGD("TopKV2TilingForAscendC", "Not enough remaining space, initUb=%u, tensorSpace=%u," |
| 291 | - uint32_t tileData = topkV2DataInfo::TMP_DATA_NUM; | 385 | + " bufferNum=%u", initUb, initSpace, bufferNum); |
| 292 | - uint32_t oneCoreRowNum = (tileData / topkV2DataInfo::CONST_TWO) / aglinNum; | 386 | + // 空间不足返回默认最小tileData |
| 293 | - oneCoreRowNum = (oneCoreRowNum == 0 ? 1 : oneCoreRowNum); | 387 | + return topkV2DataInfo::SMALL_TILE_DATA_NUM; |
| 294 | - uint32_t virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 295 | - if (virUnsortedDimNeedCoreNum < maxCoreNum) { | ||
| 296 | - // 均匀分核 | ||
| 297 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return ge::GRAPH_FAILED); | ||
| 298 | - oneCoreRowNum = (unsortedDimNum + maxCoreNum - 1) / maxCoreNum; | ||
| 299 | - oneCoreRowNum = (oneCoreRowNum == 0 ? 1 : oneCoreRowNum); | ||
| 300 | - virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 301 | - tileData = oneCoreRowNum * topkV2DataInfo::CONST_TWO * aglinNum; | ||
| 302 | - tileData = std::min(tileData, tileMaxData - topkV2DataInfo::BIN_NUM); | ||
| 303 | - } else { | ||
| 304 | - // 原先占满了核则增大tileData,但必须使核占满 | ||
| 305 | - while (virUnsortedDimNeedCoreNum >= maxCoreNum && tileData < tileMaxData - topkV2DataInfo::BIN_NUM) { | ||
| 306 | - tileData += topkV2DataInfo::BIN_NUM; | ||
| 307 | - oneCoreRowNum = (tileData / topkV2DataInfo::CONST_TWO) / aglinNum; | ||
| 308 | - oneCoreRowNum = (oneCoreRowNum == 0 ? 1 : oneCoreRowNum); | ||
| 309 | - virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 310 | - } | ||
| 311 | - uint32_t tmpTileData = tileData; | ||
| 312 | - while (!IsLastLoopCoreUtilizationSuccess(unsortedDimNum, oneCoreRowNum, maxCoreNum)) { | ||
| 313 | - tileData -= topkV2DataInfo::BIN_NUM; | ||
| 314 | - // 若自减到0,说明没有合适的tileData,放弃均匀分核,采用前值 | ||
| 315 | - if (tileData <= 0) { | ||
| 316 | - OP_LOGD("TopKV2TilingForAscendC", "final tileData=%u", tmpTileData); | ||
| 317 | - return tmpTileData; | ||
| 318 | - } | ||
| 319 | - oneCoreRowNum = (tileData / topkV2DataInfo::CONST_TWO) / aglinNum; | ||
| 320 | - oneCoreRowNum = (oneCoreRowNum == 0 ? 1 : oneCoreRowNum); | ||
| 321 | - virUnsortedDimNeedCoreNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | ||
| 322 | - } | ||
| 323 | } | 388 | } |
| 324 | 389 | ||
| 390 | + uint32_t oneCoreRowNumSize = initUb - initSpace; | ||
| 391 | + // 每个核最多可以处理多少行 | ||
| 392 | + uint32_t factor = topkV2DataInfo::CONST_TWO * xDtypeSize + indexToDtypeSize + convertTypeSize; | ||
| 393 | + uint32_t oneCoreNeedSpace = aglinNum * bufferNum * factor; | ||
| 394 | + uint32_t oneCoreRowNumMax = oneCoreRowNumSize / oneCoreNeedSpace; | ||
| 395 | + | ||
| 396 | + uint32_t tileMaxData = oneCoreRowNumMax * aglinNum * bufferNum; | ||
| 397 | + OP_LOGD("TopKV2TilingForAscendC", "tileMaxData=%u, maxCoreNum=%u, oneCoreRowNumMax=%d, " | ||
| 398 | + "oneCoreRowNumSize=%u", tileMaxData, maxCoreNum, oneCoreRowNumMax, oneCoreRowNumSize); | ||
| 399 | + | ||
| 400 | + uint32_t tileData = | ||
| 401 | + GetTileDataForMergeSort(unsortedDimNum, maxCoreNum, tileMaxData, bufferNum, aglinNum); | ||
| 402 | + | ||
| 325 | return tileData; | 403 | return tileData; |
| 326 | } | 404 | } |
| 327 | 405 | ||
| 328 | void SetMergeSortTmpSize( | 406 | void SetMergeSortTmpSize( |
| 329 | gert::TilingContext* context, ge::DataType dataType, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData) | 407 | gert::TilingContext* context, ge::DataType dataType, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData) |
| 330 | { | 408 | { |
| 331 | - uint32_t aglinDataSize = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / | ||
| 332 | - topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; | ||
| 333 | - uint32_t dataTypeSize = (dataType == ge::DT_BF16) ? topkV2DataInfo::optDataTypeBitMap.find(ge::DT_FLOAT)->second : | ||
| 334 | - topkV2DataInfo::optDataTypeBitMap.find(dataType)->second; | ||
| 335 | auto platform_info = context->GetPlatformInfo(); | 409 | auto platform_info = context->GetPlatformInfo(); |
| 336 | if (nullptr == platform_info) { | 410 | if (nullptr == platform_info) { |
| 337 | OP_LOGE("TopKV2TilingForAscendC", "platform_info is nullptr."); | 411 | OP_LOGE("TopKV2TilingForAscendC", "platform_info is nullptr."); |
| 338 | } | 412 | } |
| 413 | + | ||
| 414 | + uint32_t aglinDataSize = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / | ||
| 415 | + topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; | ||
| 416 | + uint32_t dataTypeSize = (dataType == ge::DT_BF16) ? GetDefaultTileDataSize(ge::DT_FLOAT) : | ||
| 417 | + GetDefaultTileDataSize(dataType); | ||
| 418 | + | ||
| 339 | auto plat = platform_ascendc::PlatformAscendC(platform_info); | 419 | auto plat = platform_ascendc::PlatformAscendC(platform_info); |
| 340 | uint32_t dataSizeNeed = AscendC::GetConcatTmpSize(plat, aglinDataSize, dataTypeSize); | 420 | uint32_t dataSizeNeed = AscendC::GetConcatTmpSize(plat, aglinDataSize, dataTypeSize); |
| 341 | OP_LOGI("TopKV2TilingForAscendC", "Allocal buffer mergesort element len = %ld ac merge api", lastAxisNum); | 421 | OP_LOGI("TopKV2TilingForAscendC", "Allocal buffer mergesort element len = %ld ac merge api", lastAxisNum); |
| @@ -343,41 +423,44 @@ void SetMergeSortTmpSize( | |||
| 343 | topkTilingData.set_mergSortAcApiNeedBufferSize(dataSizeNeed); | 423 | topkTilingData.set_mergSortAcApiNeedBufferSize(dataSizeNeed); |
| 344 | } | 424 | } |
| 345 | 425 | ||
| 346 | -void TileModeSmallSizeOptim( | 426 | +void TileModeSmallSizeOptim(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, |
| 347 | - uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, | 427 | + topkV2DataInfo::TopkTileInfo& topkTileInfo, topkV2DataInfo::TopkComputeNowTileSizeInfo& computeTileSizeInfo) |
| 348 | - topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | ||
| 349 | { | 428 | { |
| 429 | + uint32_t unsortedDimNum = computeTileSizeInfo.unsortedDimNum; | ||
| 430 | + uint32_t maxCoreNum = computeTileSizeInfo.maxCoreNum; | ||
| 431 | + int64_t lastAxisNum = computeTileSizeInfo.lastAxisNum; | ||
| 432 | + ge::DataType dataType = computeTileSizeInfo.dataType; | ||
| 433 | + | ||
| 434 | + SetMergeSortTmpSize(context, dataType, lastAxisNum, topkTilingData); | ||
| 435 | + uint32_t nowTileSize = ComputeMergeSortTileData(topkTilingData, computeTileSizeInfo); | ||
| 436 | + | ||
| 350 | uint32_t aglinNum = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / | 437 | uint32_t aglinNum = (static_cast<uint32_t>(lastAxisNum) + topkV2DataInfo::AGLIN_FACTOR - 1) / |
| 351 | topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; | 438 | topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; |
| 352 | - uint32_t oneCoreRowNum = (nowTileSize / 2) / aglinNum; | 439 | + uint32_t bufferNum = lastAxisNum >= topkV2DataInfo::MERGE_SORT_DISABLE_DOUBLE_BUFFER_SIZE ? |
| 353 | - oneCoreRowNum = (oneCoreRowNum == 0 ? 1 : oneCoreRowNum); | 440 | + 1 : topkV2DataInfo::CONST_TWO; |
| 441 | + | ||
| 442 | + uint32_t oneCoreRowNum = std::max((nowTileSize / bufferNum) / aglinNum, 1U); | ||
| 354 | uint32_t virUnsortedDimNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; | 443 | uint32_t virUnsortedDimNum = (unsortedDimNum + oneCoreRowNum - 1) / oneCoreRowNum; |
| 355 | - uint32_t coreNumNeed = 0; | ||
| 356 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return); | ||
| 357 | uint32_t sortLoopTimes = (virUnsortedDimNum + maxCoreNum - 1) / maxCoreNum; | 444 | uint32_t sortLoopTimes = (virUnsortedDimNum + maxCoreNum - 1) / maxCoreNum; |
| 358 | - if (sortLoopTimes == 1) { | 445 | + |
| 359 | - uint32_t realCoreNum = virUnsortedDimNum % maxCoreNum; | 446 | + uint32_t realCoreNum = virUnsortedDimNum % maxCoreNum; |
| 360 | - if (realCoreNum == 0) { | 447 | + uint32_t coreNumNeed = (sortLoopTimes == 1) ? (realCoreNum == 0 ? maxCoreNum : realCoreNum) : maxCoreNum; |
| 361 | - realCoreNum = maxCoreNum; | 448 | + |
| 362 | - } | ||
| 363 | - coreNumNeed = realCoreNum; | ||
| 364 | - } else { | ||
| 365 | - coreNumNeed = maxCoreNum; | ||
| 366 | - } | ||
| 367 | topkTilingData.set_sortLoopTimes(sortLoopTimes); | 449 | topkTilingData.set_sortLoopTimes(sortLoopTimes); |
| 368 | topkTilingData.set_lastDimTileNum(1); | 450 | topkTilingData.set_lastDimTileNum(1); |
| 369 | topkTilingData.set_unsortedDimParallel(coreNumNeed); | 451 | topkTilingData.set_unsortedDimParallel(coreNumNeed); |
| 370 | topkTilingData.set_lastDimNeedCore(1); | 452 | topkTilingData.set_lastDimNeedCore(1); |
| 371 | topkTilingData.set_numTileDataSize(lastAxisNum); | 453 | topkTilingData.set_numTileDataSize(lastAxisNum); |
| 454 | + topkTilingData.set_keyParams4(bufferNum); | ||
| 455 | + | ||
| 372 | topkTileInfo.ubRealLoadDataNum = lastAxisNum; | 456 | topkTileInfo.ubRealLoadDataNum = lastAxisNum; |
| 373 | topkTileInfo.coreNumNeed = coreNumNeed; | 457 | topkTileInfo.coreNumNeed = coreNumNeed; |
| 374 | topkTileInfo.lastDimTileNum = 1; | 458 | topkTileInfo.lastDimTileNum = 1; |
| 375 | topkTileInfo.unsortedDimParallel = coreNumNeed; | 459 | topkTileInfo.unsortedDimParallel = coreNumNeed; |
| 376 | topkTileInfo.oneCoreRowNum = oneCoreRowNum; | 460 | topkTileInfo.oneCoreRowNum = oneCoreRowNum; |
| 377 | - OP_LOGI("TopKV2TilingForAscendC", "Small size opt mode oneCoreRowNum=%u", oneCoreRowNum); | 461 | + |
| 378 | - OP_LOGI( | 462 | + OP_LOGI("TopKV2TilingForAscendC", "Small size opt mode coreNumNeed=%u sortLoopTimes=%u lastAxisNum=%ld, " |
| 379 | - "TopKV2TilingForAscendC", "Small size opt mode coreNumNeed=%u sortLoopTimes=%u lastAxisNum=%ld", coreNumNeed, | 463 | + "oneCoreRowNum=%u, nowTileSize=%u.", coreNumNeed, sortLoopTimes, lastAxisNum, oneCoreRowNum, nowTileSize); |
| 380 | - sortLoopTimes, lastAxisNum); | ||
| 381 | } | 464 | } |
| 382 | 465 | ||
| 383 | uint64_t GetSingleBlockTopkRunTimeNeedSpace( | 466 | uint64_t GetSingleBlockTopkRunTimeNeedSpace( |
| @@ -397,28 +480,31 @@ uint64_t GetSingleBlockTopkRunTimeNeedSpace( | |||
| 397 | return initUb; | 480 | return initUb; |
| 398 | } | 481 | } |
| 399 | 482 | ||
| 400 | -uint32_t ComputeSingleBlockTileData( | 483 | +uint32_t ComputeSingleBlockTileData(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, |
| 401 | - gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, ge::DataType dataType, | 484 | + ge::DataType dataType, ge::DataType indicesDType, bool isLargest, bool isSort, int64_t lastAxisNum, |
| 402 | - ge::DataType indicesDType, bool isLargest, bool isSort, int64_t lastAxisNum, int64_t kValue, | 485 | + int64_t kValue, uint64_t ubSizePlatForm) |
| 403 | - uint64_t ubSizePlatForm) | ||
| 404 | { | 486 | { |
| 405 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | 487 | + uint32_t xDtypeSize = GetDataTypeSize(dataType); |
| 406 | - uint32_t indexToDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second); | 488 | + uint32_t indexToDtypeSize = GetDataTypeSize(indicesDType); |
| 407 | - uint32_t tileData = (topkV2DataInfo::b64DataTypeBitMap.count(dataType) != 0) ? topkV2DataInfo::TMP_DATA_NUM_B64 : | 489 | + uint32_t tileData = GetSingleBlockModelDefaultTileDataSize(dataType); |
| 408 | - topkV2DataInfo::TMP_DATA_NUM; | 490 | + |
| 409 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 491 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); |
| 410 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 492 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 411 | - uint64_t needSpace = | 493 | + uint64_t needSpace = GetSingleBlockTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue); |
| 412 | - GetSingleBlockTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue); | 494 | + |
| 413 | while (topkAcApiNeedBuffer + needSpace > ubSizePlatForm) { | 495 | while (topkAcApiNeedBuffer + needSpace > ubSizePlatForm) { |
| 414 | - tileData = tileData - topkV2DataInfo::BIN_NUM; | 496 | + tileData -= topkV2DataInfo::BIN_NUM; |
| 497 | + if (tileData < lastAxisNum) { | ||
| 498 | + OP_LOGI("TopKV2TilingForAscendC", "tileData is less than lastAxisNum, tileData=%u", tileData); | ||
| 499 | + return 0U; | ||
| 500 | + } | ||
| 415 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 501 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); |
| 416 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 502 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 417 | needSpace = GetSingleBlockTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue); | 503 | needSpace = GetSingleBlockTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue); |
| 418 | } | 504 | } |
| 419 | - OP_LOGI( | 505 | + |
| 420 | - "TopKV2TilingForAscendC", "single block model tileData=%u, TempBuffer=%lu, ApiTempBuffer=%u", tileData, | 506 | + OP_LOGI("TopKV2TilingForAscendC", "single block model tileData=%u, TempBuffer=%lu, ApiTempBuffer=%u", |
| 421 | - needSpace, topkAcApiNeedBuffer); | 507 | + tileData, needSpace, topkAcApiNeedBuffer); |
| 422 | return tileData; | 508 | return tileData; |
| 423 | } | 509 | } |
| 424 | 510 | ||
| @@ -443,45 +529,39 @@ uint64_t GetTopkMultiCoreOptimModeRunTimeNeedSpace( | |||
| 443 | 529 | ||
| 444 | bool IsMultiCoreOptimMode( | 530 | bool IsMultiCoreOptimMode( |
| 445 | gert::TilingContext* context, uint32_t& inputNowTileSize, TopKV2TilingDataSimd& topkTilingData, | 531 | gert::TilingContext* context, uint32_t& inputNowTileSize, TopKV2TilingDataSimd& topkTilingData, |
| 446 | - topkV2DataInfo::TopkComputingNowTileSizeInfo& computingNowTileSizeInfo) | 532 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computeNowTileSizeInfo) |
| 447 | { | 533 | { |
| 448 | - // get variable | 534 | + uint32_t xDtypeSize = GetDataTypeSize(computeNowTileSizeInfo.dataType); |
| 449 | - ge::DataType dataType = computingNowTileSizeInfo.dataType; | 535 | + uint32_t indexToDtypeSize = GetDataTypeSize(computeNowTileSizeInfo.indicesDType); |
| 450 | - ge::DataType indicesDType = computingNowTileSizeInfo.indicesDType; | 536 | + int32_t tileData = GetDefaultTileDataSize(computeNowTileSizeInfo.dataType); |
| 451 | - int64_t kValue = computingNowTileSizeInfo.kValue; | 537 | + |
| 452 | - bool isLargest = computingNowTileSizeInfo.isLargest; | 538 | + if (tileData < computeNowTileSizeInfo.kValue) { |
| 453 | - bool isSort = computingNowTileSizeInfo.isSort; | 539 | + OP_LOGD("TopKV2TilingForAscendC", "K value exceeds initial tileData"); |
| 454 | - int64_t lastAxisNum = computingNowTileSizeInfo.lastAxisNum; | ||
| 455 | - uint64_t ubBlockAlignSize = computingNowTileSizeInfo.ubBlockAlignSize; | ||
| 456 | - | ||
| 457 | - // computing runtime local tensor need space and topk api need space | ||
| 458 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | ||
| 459 | - uint32_t indexToDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second); | ||
| 460 | - int32_t tileData = (topkV2DataInfo::b64DataTypeBitMap.count(dataType) != 0) ? topkV2DataInfo::TMP_DATA_NUM_B64 : | ||
| 461 | - topkV2DataInfo::TMP_DATA_NUM; | ||
| 462 | - if (tileData < kValue) { | ||
| 463 | - OP_LOGD("TopKV2TilingForAscendC", "k is greater than init tileData."); | ||
| 464 | return false; | 540 | return false; |
| 465 | } | 541 | } |
| 466 | - GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 542 | + GetTopkApiTmpBufferSize(context, topkTilingData, tileData, computeNowTileSizeInfo.kValue, |
| 543 | + computeNowTileSizeInfo.isLargest, computeNowTileSizeInfo.dataType, computeNowTileSizeInfo.isSort, tileData); | ||
| 467 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 544 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 468 | uint64_t needSpace = GetTopkMultiCoreOptimModeRunTimeNeedSpace( | 545 | uint64_t needSpace = GetTopkMultiCoreOptimModeRunTimeNeedSpace( |
| 469 | - lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue, ubBlockAlignSize); | 546 | + computeNowTileSizeInfo.lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, |
| 547 | + computeNowTileSizeInfo.kValue, computeNowTileSizeInfo.ubBlockAlignSize); | ||
| 470 | OP_LOGD( | 548 | OP_LOGD( |
| 471 | "TopKV2TilingForAscendC", | 549 | "TopKV2TilingForAscendC", |
| 472 | "multi core optim model init tileData=%u, init tempBuffer=%lu, init apiTempBuffer=%u, xDtypeSize=%u, " | 550 | "multi core optim model init tileData=%u, init tempBuffer=%lu, init apiTempBuffer=%u, xDtypeSize=%u, " |
| 473 | "indexToDtypeSize=%u", | 551 | "indexToDtypeSize=%u", |
| 474 | tileData, needSpace, topkAcApiNeedBuffer, xDtypeSize, indexToDtypeSize); | 552 | tileData, needSpace, topkAcApiNeedBuffer, xDtypeSize, indexToDtypeSize); |
| 475 | - while (topkAcApiNeedBuffer + needSpace > computingNowTileSizeInfo.ubSizePlatForm) { | 553 | + while (topkAcApiNeedBuffer + needSpace > computeNowTileSizeInfo.ubSizePlatForm) { |
| 476 | - tileData = tileData - topkV2DataInfo::TILE_SIZE_DECREASING_FACTOR; | 554 | + tileData -= topkV2DataInfo::TILE_SIZE_DECREASING_FACTOR; |
| 477 | - if (tileData < kValue) { | 555 | + if (tileData < computeNowTileSizeInfo.kValue) { |
| 478 | - OP_LOGD("TopKV2TilingForAscendC", "k value is greater than tilingData."); | 556 | + OP_LOGD("TopKV2TilingForAscendC", "K value exceeds adjusted tileData"); |
| 479 | return false; | 557 | return false; |
| 480 | } | 558 | } |
| 481 | - GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 559 | + GetTopkApiTmpBufferSize(context, topkTilingData, tileData, computeNowTileSizeInfo.kValue, |
| 560 | + computeNowTileSizeInfo.isLargest, computeNowTileSizeInfo.dataType, computeNowTileSizeInfo.isSort, tileData); | ||
| 482 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 561 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 483 | needSpace = GetTopkMultiCoreOptimModeRunTimeNeedSpace( | 562 | needSpace = GetTopkMultiCoreOptimModeRunTimeNeedSpace( |
| 484 | - lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue, ubBlockAlignSize); | 563 | + computeNowTileSizeInfo.lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, |
| 564 | + computeNowTileSizeInfo.kValue, computeNowTileSizeInfo.ubBlockAlignSize); | ||
| 485 | OP_LOGD( | 565 | OP_LOGD( |
| 486 | "TopKV2TilingForAscendC", | 566 | "TopKV2TilingForAscendC", |
| 487 | "multi core optim model now tileData=%u, now tempBuffer=%lu, now apiTempBuffer=%u.", tileData, needSpace, | 567 | "multi core optim model now tileData=%u, now tempBuffer=%lu, now apiTempBuffer=%u.", tileData, needSpace, |
| @@ -489,22 +569,25 @@ bool IsMultiCoreOptimMode( | |||
| 489 | } | 569 | } |
| 490 | 570 | ||
| 491 | // 在确定正确的tileData之后,必须确保尾轴是多核模式,否则会出现多核的tiling模式,走的是singleBlock的模板 | 571 | // 在确定正确的tileData之后,必须确保尾轴是多核模式,否则会出现多核的tiling模式,走的是singleBlock的模板 |
| 492 | - if (tileData >= lastAxisNum) { | 572 | + if (tileData >= computeNowTileSizeInfo.lastAxisNum) { |
| 493 | - OP_LOGD("TopKV2TilingForAscendC", "tileData is greater than lastAxisNum."); | 573 | + OP_LOGD("TopKV2TilingForAscendC", "tileData >= lastAxisNum, not suitable for multi-core"); |
| 494 | return false; | 574 | return false; |
| 495 | } | 575 | } |
| 496 | 576 | ||
| 497 | - // compute tileNum multiply by kValue | 577 | + // Verify K * tileNum fits within tileData |
| 498 | - OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData is 0"), return ge::GRAPH_FAILED); | 578 | + OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData cannot be zero"), return false); |
| 499 | - uint32_t lastDimTileNum = (lastAxisNum + tileData - 1) / tileData; | 579 | + |
| 500 | - uint32_t inputTopkSize = kValue * lastDimTileNum; | 580 | + uint32_t lastDimTileNum = |
| 581 | + Ops::Base::CeilDiv(static_cast<uint64_t>(computeNowTileSizeInfo.lastAxisNum), static_cast<uint64_t>(tileData)); | ||
| 582 | + uint32_t inputTopkSize = computeNowTileSizeInfo.kValue * lastDimTileNum; | ||
| 583 | + | ||
| 501 | if (inputTopkSize <= static_cast<uint32_t>(tileData)) { | 584 | if (inputTopkSize <= static_cast<uint32_t>(tileData)) { |
| 502 | inputNowTileSize = tileData; | 585 | inputNowTileSize = tileData; |
| 503 | - OP_LOGI( | 586 | + OP_LOGI("TopKV2TilingForAscendC", "Multi-core optim valid: tileData=%u, topkSize=%u", |
| 504 | - "TopKV2TilingForAscendC", "multi core optim model final inputNowTileSize=%u, inputTopkSize=%u", | 587 | + inputNowTileSize, inputTopkSize); |
| 505 | - inputNowTileSize, inputTopkSize); | ||
| 506 | return true; | 588 | return true; |
| 507 | } | 589 | } |
| 590 | + | ||
| 508 | return false; | 591 | return false; |
| 509 | } | 592 | } |
| 510 | 593 | ||
| @@ -564,20 +647,18 @@ uint32_t ComputeSingleCoreTileData( | |||
| 564 | ge::DataType indicesDType, bool isLargest, bool isSort, int64_t lastAxisNum, int64_t kValue, | 647 | ge::DataType indicesDType, bool isLargest, bool isSort, int64_t lastAxisNum, int64_t kValue, |
| 565 | uint64_t ubSizePlatForm) | 648 | uint64_t ubSizePlatForm) |
| 566 | { | 649 | { |
| 567 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | 650 | + uint32_t xDtypeSize = GetDataTypeSize(dataType); |
| 568 | - uint32_t indexToDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second); | 651 | + uint32_t indexToDtypeSize = GetDataTypeSize(indicesDType); |
| 569 | - uint32_t tileData = (topkV2DataInfo::b64DataTypeBitMap.count(dataType) != 0) ? topkV2DataInfo::TMP_DATA_NUM_B64 : | 652 | + uint32_t tileData = GetSingleCoreModelDefaultTileDataSize(dataType); |
| 570 | - topkV2DataInfo::TMP_DATA_NUM; | 653 | + |
| 571 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 654 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); |
| 572 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 655 | uint32_t topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 573 | uint64_t needSpace = | 656 | uint64_t needSpace = |
| 574 | GetSingleCoreTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue, isSort); | 657 | GetSingleCoreTopkRunTimeNeedSpace(lastAxisNum, tileData, xDtypeSize, indexToDtypeSize, kValue, isSort); |
| 575 | - OP_LOGI( | 658 | + |
| 576 | - "TopKV2TilingForAscendC", "single core model init tileData=%u, init TempBuffer=%lu, now ApiTempBuffer=%u", | ||
| 577 | - tileData, needSpace, topkAcApiNeedBuffer); | ||
| 578 | while (topkAcApiNeedBuffer + needSpace > ubSizePlatForm) { | 659 | while (topkAcApiNeedBuffer + needSpace > ubSizePlatForm) { |
| 579 | - tileData = tileData - topkV2DataInfo::BIN_NUM; | 660 | + tileData -= topkV2DataInfo::BIN_NUM; |
| 580 | - OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData is 0"), return ge::GRAPH_FAILED); | 661 | + OP_CHECK_IF(tileData == 0, OP_LOGE("TopkV2", "tileData is 0"), return 0); |
| 581 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); | 662 | GetTopkApiTmpBufferSize(context, topkTilingData, tileData, kValue, isLargest, dataType, isSort, tileData); |
| 582 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); | 663 | topkAcApiNeedBuffer = topkTilingData.get_topkAcApiTmpBufferSize(); |
| 583 | needSpace = | 664 | needSpace = |
| @@ -604,7 +685,6 @@ void TileModeSmallSize( | |||
| 604 | uint32_t tailBatchNumTotal = unsortedDimNum % batchNumSingleLoop; | 685 | uint32_t tailBatchNumTotal = unsortedDimNum % batchNumSingleLoop; |
| 605 | uint32_t tailBatchNumSingleCore = 0; | 686 | uint32_t tailBatchNumSingleCore = 0; |
| 606 | uint32_t tailBatchNum = 0; | 687 | uint32_t tailBatchNum = 0; |
| 607 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return); | ||
| 608 | uint32_t coreNumNeed = maxCoreNum; | 688 | uint32_t coreNumNeed = maxCoreNum; |
| 609 | if (tailBatchNumTotal != 0) { | 689 | if (tailBatchNumTotal != 0) { |
| 610 | tailBatchNumSingleCore = tailBatchNumTotal / maxCoreNum; | 690 | tailBatchNumSingleCore = tailBatchNumTotal / maxCoreNum; |
| @@ -630,12 +710,11 @@ void TileModeSmallSize( | |||
| 630 | } | 710 | } |
| 631 | 711 | ||
| 632 | void TileModeSingleCore( | 712 | void TileModeSingleCore( |
| 633 | - uint32_t unsortedDimNum, uint32_t maxCoreNum, uint32_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, | 713 | + uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, |
| 634 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | 714 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) |
| 635 | { | 715 | { |
| 636 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); | 716 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); |
| 637 | uint32_t lastDimTileNum = (lastAxisNum + nowTileSize - 1) / nowTileSize; | 717 | uint32_t lastDimTileNum = (lastAxisNum + nowTileSize - 1) / nowTileSize; |
| 638 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return); | ||
| 639 | uint32_t sortLoopTimes = unsortedDimNum / maxCoreNum; | 718 | uint32_t sortLoopTimes = unsortedDimNum / maxCoreNum; |
| 640 | uint32_t tailBatchNum = unsortedDimNum % maxCoreNum; | 719 | uint32_t tailBatchNum = unsortedDimNum % maxCoreNum; |
| 641 | uint32_t tileNum = lastAxisNum / lastDimTileNum; | 720 | uint32_t tileNum = lastAxisNum / lastDimTileNum; |
| @@ -665,9 +744,6 @@ void TileModeMediumSize( | |||
| 665 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, | 744 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, |
| 666 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | 745 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) |
| 667 | { | 746 | { |
| 668 | - if (topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64) { | ||
| 669 | - nowTileSize /= topkV2DataInfo::CONST_TWO; | ||
| 670 | - } | ||
| 671 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); | 747 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); |
| 672 | uint32_t lastDimTileNum = (static_cast<uint32_t>(lastAxisNum) + nowTileSize - 1) / nowTileSize; | 748 | uint32_t lastDimTileNum = (static_cast<uint32_t>(lastAxisNum) + nowTileSize - 1) / nowTileSize; |
| 673 | uint32_t unsortedDimParallel = maxCoreNum / lastDimTileNum; | 749 | uint32_t unsortedDimParallel = maxCoreNum / lastDimTileNum; |
| @@ -699,9 +775,6 @@ void TileModeBigSize( | |||
| 699 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, | 775 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, |
| 700 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | 776 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) |
| 701 | { | 777 | { |
| 702 | - if (topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64) { | ||
| 703 | - nowTileSize /= topkV2DataInfo::CONST_TWO; | ||
| 704 | - } | ||
| 705 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); | 778 | OP_CHECK_IF(nowTileSize == 0, OP_LOGE("TopkV2", "nowTileSize is 0"), return); |
| 706 | int64_t lastDimTileNum = (lastAxisNum + nowTileSize - 1) / nowTileSize; | 779 | int64_t lastDimTileNum = (lastAxisNum + nowTileSize - 1) / nowTileSize; |
| 707 | uint32_t coreNumNeed = static_cast<uint32_t>(std::min(static_cast<int64_t>(maxCoreNum), lastDimTileNum)); | 780 | uint32_t coreNumNeed = static_cast<uint32_t>(std::min(static_cast<int64_t>(maxCoreNum), lastDimTileNum)); |
| @@ -716,27 +789,68 @@ void TileModeBigSize( | |||
| 716 | topkTileInfo.coreNumNeed = maxCoreNum; | 789 | topkTileInfo.coreNumNeed = maxCoreNum; |
| 717 | topkTileInfo.lastDimTileNum = lastDimTileNum; | 790 | topkTileInfo.lastDimTileNum = lastDimTileNum; |
| 718 | topkTileInfo.unsortedDimParallel = 1; | 791 | topkTileInfo.unsortedDimParallel = 1; |
| 719 | - OP_LOGI( | 792 | + topkTileInfo.multiCoreBigModel = true; // topk radix大规模多核标志 |
| 720 | - "TopKV2TilingForAscendC", "Big size mode coreNumNeed=%u sortLoopTimes=%u lastAxisNum=%ld", coreNumNeed, | 793 | + OP_LOGI("TopKV2TilingForAscendC", "Big size mode coreNumNeed=%u sortLoopTimes=%u lastAxisNum=%ld", coreNumNeed, |
| 721 | unsortedDimNum, lastAxisNum); | 794 | unsortedDimNum, lastAxisNum); |
| 722 | - OP_LOGI( | ||
| 723 | - "TopKV2TilingForAscendC", "Big size mode lastDimTileNum=%ld unsortedDimParallel=1 lastDimRealCore=%u", | ||
| 724 | - lastDimTileNum, coreNumNeed); | ||
| 725 | } | 795 | } |
| 726 | 796 | ||
| 797 | +/** | ||
| 798 | + * Topk自身多核基数模板 | ||
| 799 | + * 进入条件: | ||
| 800 | + * 1. 能计算出正确的tileSize; | ||
| 801 | + */ | ||
| 802 | +void TileTopkMoreCoreMode(uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, | ||
| 803 | + TopKV2TilingDataSimd& topkTilingData, topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | ||
| 804 | +{ | ||
| 805 | + uint32_t sortedDimParallelData = (nowTileSize * maxCoreNum) / 2; | ||
| 806 | + if (lastAxisNum <= sortedDimParallelData) { | ||
| 807 | + TileModeMediumSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | ||
| 808 | + } else { | ||
| 809 | + if (topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64) { | ||
| 810 | + nowTileSize /= topkV2DataInfo::CONST_TWO; | ||
| 811 | + } | ||
| 812 | + TileModeBigSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | ||
| 813 | + } | ||
| 814 | +} | ||
| 815 | + | ||
| 816 | +/** | ||
| 817 | + * Topk自身多核基数排序优化模板 | ||
| 818 | + * 进入条件: | ||
| 819 | + * 1. k * (lastAxisNum / nowTileSize) <= nowTileSize, 假设 lastAxisNum 一共需要N个核处理,每个核计算出Topk的值; | ||
| 820 | + * 然后将前面每个核的Topk的值集中到一个核(前提是这个核的UB能装的下),再进行一次Topk处理; | ||
| 821 | + */ | ||
| 727 | void TileMultiCoreOptimSize( | 822 | void TileMultiCoreOptimSize( |
| 728 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, | 823 | uint32_t unsortedDimNum, uint32_t maxCoreNum, int64_t lastAxisNum, TopKV2TilingDataSimd& topkTilingData, |
| 729 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) | 824 | topkV2DataInfo::TopkTileInfo& topkTileInfo, uint32_t nowTileSize) |
| 730 | { | 825 | { |
| 731 | - const uint32_t sortedDimParallelData = (nowTileSize * maxCoreNum) / 2; | 826 | + uint32_t sortedDimParallelData = (nowTileSize * maxCoreNum) / 2; |
| 732 | - if (topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64) { | ||
| 733 | - nowTileSize *= topkV2DataInfo::CONST_TWO; | ||
| 734 | - } | ||
| 735 | if (lastAxisNum <= sortedDimParallelData) { | 827 | if (lastAxisNum <= sortedDimParallelData) { |
| 736 | TileModeMediumSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | 828 | TileModeMediumSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 737 | } else { | 829 | } else { |
| 738 | TileModeBigSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | 830 | TileModeBigSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 739 | } | 831 | } |
| 832 | + // tiling和多核基数排序保持一致, modelType不同 | ||
| 833 | + topkTilingData.set_modeType(topkV2DataInfo::MULT_CORE_OPTIM_MODE); | ||
| 834 | +} | ||
| 835 | + | ||
| 836 | +/** | ||
| 837 | + * 进入条件: | ||
| 838 | + * 1. 尾轴不超过1000万; | ||
| 839 | + * 2. topk自有的基于多核radix基数排序算能够计算出正确的UB tileSize; | ||
| 840 | + */ | ||
| 841 | +bool IsTopkRadixMoreCoreMode(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | ||
| 842 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computeNowTileSizeInfo, uint32_t &nowTileSize) { | ||
| 843 | + if (computeNowTileSizeInfo.lastAxisNum >= topkV2DataInfo::SORT_AND_TOP_K_THRESHOLD) { | ||
| 844 | + OP_LOGD("[TopKV2Tiling] lastAxisNum exceeds 10 million."); | ||
| 845 | + return false; | ||
| 846 | + } | ||
| 847 | + uint32_t tmpTileSize = ComputeTopkRadixMoreCoreTileData(context, topkTilingData, computeNowTileSizeInfo); | ||
| 848 | + if (tmpTileSize > 0) { | ||
| 849 | + nowTileSize = tmpTileSize; | ||
| 850 | + OP_LOGD("[TopKV2Tiling]", "radix more core final tileSize=%u", nowTileSize); | ||
| 851 | + return true; | ||
| 852 | + } | ||
| 853 | + return false; | ||
| 740 | } | 854 | } |
| 741 | 855 | ||
| 742 | ge::graphStatus IsValidParam(gert::TilingContext* context) | 856 | ge::graphStatus IsValidParam(gert::TilingContext* context) |
| @@ -785,16 +899,227 @@ ge::graphStatus IsValidParam(gert::TilingContext* context) | |||
| 785 | return ge::GRAPH_SUCCESS; | 899 | return ge::GRAPH_SUCCESS; |
| 786 | } | 900 | } |
| 787 | 901 | ||
| 788 | -bool IsModeSingleCore(uint32_t unsortedDimNum, uint32_t maxCoreNum) | 902 | +/** |
| 903 | + * 判断是否为 Single Block 模式 | ||
| 904 | + * | ||
| 905 | + * 执行条件: | ||
| 906 | + * 1. lastAxisNum 能一次性装入 UB 中,即 tileSize >= lastAxisNum | ||
| 907 | + * 这样一个核可以处理多个 lastAxisNum(batch),充分利用 UB 空间 | ||
| 908 | + * 2. 能计算出有效的 tileSize(大于 0) | ||
| 909 | + */ | ||
| 910 | +bool IsSingleBlockMode(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | ||
| 911 | + uint32_t& tileSize, topkV2DataInfo::TopkComputeNowTileSizeInfo& computeTileSizeInfo) | ||
| 912 | +{ | ||
| 913 | + // 计算 Single Block 模式所需的 tileSize | ||
| 914 | + uint32_t computedTileSize = ComputeSingleBlockTileData(context, topkTilingData, computeTileSizeInfo.dataType, | ||
| 915 | + computeTileSizeInfo.indicesDType, computeTileSizeInfo.isLargest, computeTileSizeInfo.isSort, | ||
| 916 | + computeTileSizeInfo.lastAxisNum, computeTileSizeInfo.kValue, computeTileSizeInfo.ubSizePlatForm); | ||
| 917 | + | ||
| 918 | + // 判断是否为 Single Block 模式 | ||
| 919 | + // 条件1:计算出的 tileSize 必须大于 0(有效) | ||
| 920 | + // 条件2:tileSize >= lastAxisNum(能一次性装入 UB) | ||
| 921 | + bool isSingleBlockMode = (computedTileSize > 0) && (computedTileSize >= computeTileSizeInfo.lastAxisNum); | ||
| 922 | + | ||
| 923 | + if (isSingleBlockMode) { | ||
| 924 | + tileSize = computedTileSize; | ||
| 925 | + OP_LOGI("[TopKV2Tiling]", "Single block mode enabled: tileSize=%u >= lastAxisNum=%ld", | ||
| 926 | + tileSize, computeTileSizeInfo.lastAxisNum); | ||
| 927 | + } | ||
| 928 | + return isSingleBlockMode; | ||
| 929 | +} | ||
| 930 | + | ||
| 931 | +/** | ||
| 932 | + * 执行条件: | ||
| 933 | + * 1. 数据类型bf16, float16, float32, 尾轴小于等于1024; | ||
| 934 | + */ | ||
| 935 | +bool IsSmallSizeMergeSortMode(ge::DataType dataType, int64_t lastAxisNum) { | ||
| 936 | + bool isSmallMergeSort = lastAxisNum <= topkV2DataInfo::SMALL_MAX_DATA_SZIE && | ||
| 937 | + topkV2DataInfo::optDataTypeBitMap.count(dataType) != 0; | ||
| 938 | + return isSmallMergeSort; | ||
| 939 | +} | ||
| 940 | + | ||
| 941 | +/** | ||
| 942 | + * 执行条件: | ||
| 943 | + * 1. 非尾轴大于等于核数, B轴均匀分核确定是有性能收益, 均匀分核场景,需要考虑尾行处理的时间与核间同步时间的均衡; | ||
| 944 | + * 目前测试非均匀分核性能也有提升,故不区分是否均匀分核,直接返回true,后面如果有性能走这个模板有性能劣化可以考虑这一点; | ||
| 945 | + * 2. UB能找到合适的tileSize; | ||
| 946 | + */ | ||
| 947 | +bool IsSingleCoreMode(gert::TilingContext *context, TopKV2TilingDataSimd& topkTilingData, uint32_t &initTileSize, | ||
| 948 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computTileInfo) | ||
| 789 | { | 949 | { |
| 790 | - // B轴小于核数,则不走该模板 | 950 | + if (computTileInfo.unsortedDimNum < computTileInfo.maxCoreNum) { |
| 791 | - if (unsortedDimNum < maxCoreNum) { | 951 | + OP_LOGD("[TopKV2Tiling], single core model unsortedDimNum is less than maxCoreNum."); |
| 792 | return false; | 952 | return false; |
| 793 | } | 953 | } |
| 794 | - // B轴均匀分核确定是有性能收益; | 954 | + uint32_t nowTileSizeTmp = ComputeSingleCoreTileData(context, topkTilingData, computTileInfo.dataType, |
| 795 | - // 均匀分核场景,需要考虑尾行处理的时间与核间同步时间的均衡; | 955 | + computTileInfo.indicesDType, computTileInfo.isLargest, computTileInfo.isSort, computTileInfo.lastAxisNum, |
| 796 | - // 目前测试非均匀分核性能也有提升,故不区分是否均匀分核,直接返回true,后面如果有性能走这个模板有性能劣化可以考虑这一点 | 956 | + computTileInfo.kValue, computTileInfo.ubSizePlatForm); |
| 797 | - return true; | 957 | + if (nowTileSizeTmp > 0) { |
| 958 | + initTileSize = nowTileSizeTmp; | ||
| 959 | + OP_LOGD("[TopKV2Tiling]", "single core final tileSize=%u", initTileSize); | ||
| 960 | + return true; | ||
| 961 | + } | ||
| 962 | + return false; | ||
| 963 | +} | ||
| 964 | + | ||
| 965 | +uint32_t AlignTopkMergeMoreCoreWorkspaceElems(int64_t elementNum) | ||
| 966 | +{ | ||
| 967 | + if (elementNum <= 0) { | ||
| 968 | + return 0; | ||
| 969 | + } | ||
| 970 | + return static_cast<uint32_t>(Ops::Base::CeilAlign( | ||
| 971 | + static_cast<uint64_t>(elementNum * topkV2DataInfo::SORT_STRUCT_SIZE_FP32), | ||
| 972 | + topkV2DataInfo::AGLIN_FACTOR) / topkV2DataInfo::SORT_STRUCT_SIZE_FP32); | ||
| 973 | +} | ||
| 974 | + | ||
| 975 | +void GetTopkMergeMoreCoreFp32(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | ||
| 976 | + uint32_t maxCoreNum, uint32_t unsortedDimNum, int64_t lastAxisNum, int64_t outLastAxisNum, | ||
| 977 | + uint32_t onceMaxElements, uint64_t ubSizePlatForm) | ||
| 978 | +{ | ||
| 979 | + uint32_t splitCoreNum = Ops::Base::CeilDiv(static_cast<uint64_t>(lastAxisNum), | ||
| 980 | + static_cast<uint64_t>(topkV2DataInfo::MERGE_MORE_CORE_ONE_CORE_DATA_SIZE)); | ||
| 981 | + uint32_t numTileDataSize = splitCoreNum == 0 ? 0 : static_cast<uint32_t>(lastAxisNum) / splitCoreNum; | ||
| 982 | + uint32_t coreNumNeed = unsortedDimNum * splitCoreNum; | ||
| 983 | + uint32_t onceMaxElementsAlign = (onceMaxElements / topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN) * | ||
| 984 | + topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN; | ||
| 985 | + | ||
| 986 | + topkTilingData.set_modeType(topkV2DataInfo::FP32_MERGE_MORE_CORE_MODE); | ||
| 987 | + topkTilingData.set_sortLoopTimes(1); | ||
| 988 | + topkTilingData.set_unsortedDimParallel(unsortedDimNum); | ||
| 989 | + topkTilingData.set_lastDimNeedCore(splitCoreNum); | ||
| 990 | + topkTilingData.set_numTileDataSize(numTileDataSize); | ||
| 991 | + topkTilingData.set_lastDimTileNum(splitCoreNum); | ||
| 992 | + topkTilingData.set_oneCoreRowNum(1); | ||
| 993 | + topkTilingData.set_keyParams0(onceMaxElementsAlign); | ||
| 994 | + topkTilingData.set_lastAxisNum(lastAxisNum); | ||
| 995 | + topkTilingData.set_unsortedDimNum(unsortedDimNum); | ||
| 996 | + topkTilingData.set_topKRealValue(outLastAxisNum); | ||
| 997 | + topkTilingData.set_outputLastDimValue(outLastAxisNum); | ||
| 998 | + topkTilingData.set_lastDimTileNumTimes(Ops::Base::CeilDiv(static_cast<uint64_t>(splitCoreNum), static_cast<uint64_t>(maxCoreNum))); | ||
| 999 | + | ||
| 1000 | + uint32_t alignInput = AlignTopkMergeMoreCoreWorkspaceElems(lastAxisNum); | ||
| 1001 | + size_t usrSize = static_cast<size_t>(unsortedDimNum) * alignInput * | ||
| 1002 | + topkV2DataInfo::SORT_STRUCT_SIZE_FP32 * topkV2DataInfo::CONST_TWO; | ||
| 1003 | + size_t* userWorkSpaceSize = context->GetWorkspaceSizes(1); | ||
| 1004 | + userWorkSpaceSize[0] = usrSize + topkV2DataInfo::SYS_WORK_SPACE_SIZE; | ||
| 1005 | + context->SetTilingKey(topkV2DataInfo::TOPK_MERGE_SORT_MORE_CORE_TILING_KEY_FLOAT); | ||
| 1006 | + context->SetBlockDim(coreNumNeed); | ||
| 1007 | + context->SetLocalMemorySize(ubSizePlatForm); | ||
| 1008 | + context->SetScheduleMode(1); | ||
| 1009 | +} | ||
| 1010 | + | ||
| 1011 | +uint32_t ComputeTopkMergeMoreCoreOnceMaxElements(uint64_t ubSizePlatForm, ge::DataType indicesDType) | ||
| 1012 | +{ | ||
| 1013 | + uint32_t indexBytes = GetDataTypeSize(indicesDType); | ||
| 1014 | + uint32_t bytesPerElem = topkV2DataInfo::MERGE_MORE_CORE_LIST_MAX_NUM * | ||
| 1015 | + topkV2DataInfo::SORT_STRUCT_SIZE_FP32 * topkV2DataInfo::CONST_TWO; | ||
| 1016 | + bytesPerElem += topkV2DataInfo::MERGE_MORE_CORE_LIST_MAX_NUM * static_cast<uint32_t>(sizeof(uint32_t)); | ||
| 1017 | + bytesPerElem += topkV2DataInfo::MERGE_MORE_CORE_LIST_MAX_NUM * static_cast<uint32_t>(sizeof(float)); | ||
| 1018 | + if (indexBytes == topkV2DataInfo::INT64_BYTE) { | ||
| 1019 | + bytesPerElem += topkV2DataInfo::MERGE_MORE_CORE_LIST_MAX_NUM * indexBytes; | ||
| 1020 | + } | ||
| 1021 | + return bytesPerElem == 0 ? 0 : static_cast<uint32_t>(ubSizePlatForm / bytesPerElem); | ||
| 1022 | +} | ||
| 1023 | + | ||
| 1024 | +ge::graphStatus TileModeFp32MoreCoreSort(gert::TilingContext *context, TopKV2TilingDataSimd& topkTilingData, | ||
| 1025 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computNowTileInfo) { | ||
| 1026 | + | ||
| 1027 | + topkTilingData.set_isLargest(computNowTileInfo.isLargest); | ||
| 1028 | + topkTilingData.set_isSort(computNowTileInfo.isSort); | ||
| 1029 | + topkTilingData.set_isInInt32Range(computNowTileInfo.isInInt32Range); | ||
| 1030 | + topkTilingData.set_platformCoreNum(computNowTileInfo.maxCoreNum); | ||
| 1031 | + | ||
| 1032 | + uint32_t mergeMoreCoreOnceMaxElements = ComputeTopkMergeMoreCoreOnceMaxElements( | ||
| 1033 | + computNowTileInfo.ubSizePlatForm, computNowTileInfo.indicesDType); | ||
| 1034 | + | ||
| 1035 | + GetTopkMergeMoreCoreFp32(context, topkTilingData, static_cast<uint32_t>(computNowTileInfo.maxCoreNum), | ||
| 1036 | + computNowTileInfo.unsortedDimNum, computNowTileInfo.lastAxisNum, computNowTileInfo.kValue, | ||
| 1037 | + mergeMoreCoreOnceMaxElements, computNowTileInfo.ubSizePlatForm); | ||
| 1038 | + topkTilingData.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity()); | ||
| 1039 | + context->GetRawTilingData()->SetDataSize(topkTilingData.GetDataSize()); | ||
| 1040 | + OP_LOGI("TopKV2TilingForAscendC", "TopKV2 fp32 merge more-core tiling end"); | ||
| 1041 | + return ge::GRAPH_SUCCESS; | ||
| 1042 | +} | ||
| 1043 | + | ||
| 1044 | +void GetTopkMergeIntraCoreFp32(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | ||
| 1045 | + uint32_t maxCoreNum, uint32_t unsortedDimNum, int64_t lastAxisNum, int64_t outLastAxisNum, | ||
| 1046 | + uint32_t blockSortSize, uint32_t extractChunkSize, uint64_t ubSizePlatForm) | ||
| 1047 | +{ | ||
| 1048 | + uint32_t blocksPerRow = Ops::Base::CeilDiv(static_cast<uint64_t>(lastAxisNum), static_cast<uint64_t>(blockSortSize)); | ||
| 1049 | + uint32_t alignNum = blocksPerRow * blockSortSize; | ||
| 1050 | + uint32_t actualCoreNum = std::min(maxCoreNum, unsortedDimNum); | ||
| 1051 | + uint32_t batchPerCore = Ops::Base::CeilDiv(static_cast<uint64_t>(unsortedDimNum), static_cast<uint64_t>(actualCoreNum)); | ||
| 1052 | + uint32_t sortLoopTimes = 1; | ||
| 1053 | + | ||
| 1054 | + topkTilingData.set_modeType(topkV2DataInfo::FP32_MERGE_INTRA_CORE_MODE); | ||
| 1055 | + topkTilingData.set_sortLoopTimes(sortLoopTimes); | ||
| 1056 | + topkTilingData.set_unsortedDimParallel(actualCoreNum); | ||
| 1057 | + topkTilingData.set_lastDimNeedCore(actualCoreNum); | ||
| 1058 | + topkTilingData.set_numTileDataSize(blockSortSize); | ||
| 1059 | + topkTilingData.set_lastDimTileNum(blocksPerRow); | ||
| 1060 | + topkTilingData.set_oneCoreRowNum(batchPerCore); | ||
| 1061 | + topkTilingData.set_keyParams0(batchPerCore); | ||
| 1062 | + topkTilingData.set_keyParams1(blockSortSize * topkV2DataInfo::CONST_TWO); | ||
| 1063 | + topkTilingData.set_keyParams2(alignNum * topkV2DataInfo::CONST_TWO); | ||
| 1064 | + topkTilingData.set_keyParams3(alignNum); | ||
| 1065 | + topkTilingData.set_keyParams4(extractChunkSize); | ||
| 1066 | + topkTilingData.set_keyParams5(blockSortSize == 0 ? 0 : | ||
| 1067 | + static_cast<uint32_t>(std::numeric_limits<int32_t>::max() / blockSortSize)); | ||
| 1068 | + topkTilingData.set_lastAxisNum(lastAxisNum); | ||
| 1069 | + topkTilingData.set_unsortedDimNum(unsortedDimNum); | ||
| 1070 | + topkTilingData.set_topKRealValue(outLastAxisNum); | ||
| 1071 | + topkTilingData.set_outputLastDimValue(outLastAxisNum); | ||
| 1072 | + topkTilingData.set_lastDimTileNumTimes(Ops::Base::CeilDiv(static_cast<uint64_t>(blocksPerRow), static_cast<uint64_t>(maxCoreNum))); | ||
| 1073 | + | ||
| 1074 | + size_t perCoreWorkspace = static_cast<size_t>(alignNum) * topkV2DataInfo::SORT_STRUCT_SIZE_FP32 * | ||
| 1075 | + topkV2DataInfo::CONST_TWO; | ||
| 1076 | + size_t usrSize = perCoreWorkspace * actualCoreNum; | ||
| 1077 | + size_t* userWorkSpaceSize = context->GetWorkspaceSizes(1); | ||
| 1078 | + userWorkSpaceSize[0] = usrSize + topkV2DataInfo::SYS_WORK_SPACE_SIZE; | ||
| 1079 | + context->SetTilingKey(topkV2DataInfo::TOPK_MERGE_SORT_INTRA_CORE_TILING_KEY_FLOAT); | ||
| 1080 | + context->SetBlockDim(actualCoreNum); | ||
| 1081 | + context->SetLocalMemorySize(ubSizePlatForm); | ||
| 1082 | + context->SetScheduleMode(1); | ||
| 1083 | +} | ||
| 1084 | + | ||
| 1085 | +uint32_t ComputeTopkMergeIntraCoreBlockSortSize(uint64_t ubSizePlatForm) | ||
| 1086 | +{ | ||
| 1087 | + constexpr uint32_t phase2BytesPerElem = topkV2DataInfo::CONST_TWO * topkV2DataInfo::SORT_STRUCT_SIZE_FP32 * | ||
| 1088 | + topkV2DataInfo::CONST_TWO * topkV2DataInfo::CONST_TWO; | ||
| 1089 | + uint32_t blockSortSize = static_cast<uint32_t>(ubSizePlatForm / phase2BytesPerElem); | ||
| 1090 | + return (blockSortSize / topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN) * | ||
| 1091 | + topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN; | ||
| 1092 | +} | ||
| 1093 | + | ||
| 1094 | +uint32_t ComputeTopkMergeIntraCoreExtractChunkSize(uint64_t ubSizePlatForm, ge::DataType indicesDType) | ||
| 1095 | +{ | ||
| 1096 | + uint32_t indexBytes = GetDataTypeSize(indicesDType); | ||
| 1097 | + uint32_t bytesPerElem = (topkV2DataInfo::SORT_STRUCT_SIZE_FP32 + sizeof(float) + | ||
| 1098 | + sizeof(int32_t) + indexBytes) * topkV2DataInfo::CONST_TWO; | ||
| 1099 | + | ||
| 1100 | + uint32_t extractChunkSize = static_cast<uint32_t>(ubSizePlatForm / bytesPerElem); | ||
| 1101 | + return (extractChunkSize / topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN) * | ||
| 1102 | + topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN; | ||
| 1103 | +} | ||
| 1104 | + | ||
| 1105 | +ge::graphStatus TileModeFp32IntraCoreSort(gert::TilingContext *context, TopKV2TilingDataSimd& topkTilingData, | ||
| 1106 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computNowTileInfo) { | ||
| 1107 | + topkTilingData.set_isLargest(computNowTileInfo.isLargest); | ||
| 1108 | + topkTilingData.set_isSort(computNowTileInfo.isSort); | ||
| 1109 | + topkTilingData.set_isInInt32Range(computNowTileInfo.isInInt32Range); | ||
| 1110 | + topkTilingData.set_platformCoreNum(computNowTileInfo.maxCoreNum); | ||
| 1111 | + | ||
| 1112 | + uint32_t mergeIntraCoreBlockSortSize = ComputeTopkMergeIntraCoreBlockSortSize(computNowTileInfo.ubSizePlatForm); | ||
| 1113 | + uint32_t mergeIntraCoreExtractChunkSize = ComputeTopkMergeIntraCoreExtractChunkSize( | ||
| 1114 | + computNowTileInfo.ubSizePlatForm, computNowTileInfo.indicesDType); | ||
| 1115 | + | ||
| 1116 | + GetTopkMergeIntraCoreFp32(context, topkTilingData, static_cast<uint32_t>(computNowTileInfo.maxCoreNum), | ||
| 1117 | + computNowTileInfo.unsortedDimNum, computNowTileInfo.lastAxisNum, computNowTileInfo.kValue, | ||
| 1118 | + mergeIntraCoreBlockSortSize, mergeIntraCoreExtractChunkSize, computNowTileInfo.ubSizePlatForm); | ||
| 1119 | + topkTilingData.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity()); | ||
| 1120 | + context->GetRawTilingData()->SetDataSize(topkTilingData.GetDataSize()); | ||
| 1121 | + OP_LOGI("TopKV2TilingForAscendC", "TopKV2 fp32 merge intra-core tiling end"); | ||
| 1122 | + return ge::GRAPH_SUCCESS; | ||
| 798 | } | 1123 | } |
| 799 | 1124 | ||
| 800 | // sort核间模板tiling计算相关函数 | 1125 | // sort核间模板tiling计算相关函数 |
| @@ -833,9 +1158,12 @@ void AdjTmpUb(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t tileData, uin | |||
| 833 | void ComputeTileDataOne(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t lastDimTileNum, uint32_t ubExtra, | 1158 | void ComputeTileDataOne(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t lastDimTileNum, uint32_t ubExtra, |
| 834 | uint32_t &tileData, uint32_t tileFactor) | 1159 | uint32_t &tileData, uint32_t tileFactor) |
| 835 | { | 1160 | { |
| 836 | - uint32_t allCore = CeilAlignDivMul<uint32_t>(int64_t(lastDimTileNum), int64_t(sortTileInfo.maxCoreNum)); | 1161 | + uint32_t allCore = static_cast<uint32_t>( |
| 837 | - uint32_t newTileData = CeilAlignDiv(sortTileInfo.sortAxisNum, int64_t(allCore)); | 1162 | + Ops::Base::CeilAlign(static_cast<uint64_t>(lastDimTileNum), static_cast<uint64_t>(sortTileInfo.maxCoreNum))); |
| 838 | - tileData = CeilAlignDivMul<uint32_t>(int64_t(newTileData), int64_t(topkV2DataInfo::BIN_NUM)); | 1163 | + uint32_t newTileData = static_cast<uint32_t>( |
| 1164 | + Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(allCore))); | ||
| 1165 | + tileData = static_cast<uint32_t>( | ||
| 1166 | + Ops::Base::CeilAlign(static_cast<uint64_t>(newTileData), static_cast<uint64_t>(topkV2DataInfo::BIN_NUM))); | ||
| 839 | tileData = std::max(tileData, topkV2DataInfo::SMALL_TILE_DATA_NUM); | 1167 | tileData = std::max(tileData, topkV2DataInfo::SMALL_TILE_DATA_NUM); |
| 840 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); | 1168 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); |
| 841 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); | 1169 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); |
| @@ -847,8 +1175,8 @@ bool NeedAdjTileData(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t &tileD | |||
| 847 | { | 1175 | { |
| 848 | if (sortTileInfo.unSortDimNum == int64_t(1) && lastDimTileNum == uint32_t(1)) { | 1176 | if (sortTileInfo.unSortDimNum == int64_t(1) && lastDimTileNum == uint32_t(1)) { |
| 849 | OP_LOGI("RadixSortTiling", "unSortDimNum and lastDimTileNum is 1"); | 1177 | OP_LOGI("RadixSortTiling", "unSortDimNum and lastDimTileNum is 1"); |
| 850 | - uint32_t newTileData = CeilAlignDiv(sortTileInfo.sortAxisNum, int64_t(sortTileInfo.maxCoreNum)); | 1178 | + uint32_t newTileData = static_cast<uint32_t>(Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(sortTileInfo.maxCoreNum))); |
| 851 | - newTileData = CeilAlignDivMul<uint32_t>(int64_t(newTileData), int64_t(topkV2DataInfo::BIN_NUM)); | 1179 | + newTileData = static_cast<uint32_t>(Ops::Base::CeilAlign(static_cast<uint64_t>(newTileData), static_cast<uint64_t>(topkV2DataInfo::BIN_NUM))); |
| 852 | tileData = std::max(newTileData, topkV2DataInfo::SMALL_TILE_DATA_NUM); | 1180 | tileData = std::max(newTileData, topkV2DataInfo::SMALL_TILE_DATA_NUM); |
| 853 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); | 1181 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); |
| 854 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); | 1182 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); |
| @@ -865,7 +1193,7 @@ bool NeedAdjTileData(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t &tileD | |||
| 865 | OP_LOGI("RadixSortTiling", "unSortDimNum greater than 1,and unSortDimNum small and lastDimTileNum is one"); | 1193 | OP_LOGI("RadixSortTiling", "unSortDimNum greater than 1,and unSortDimNum small and lastDimTileNum is one"); |
| 866 | uint32_t hCore = sortTileInfo.maxCoreNum / static_cast<uint32_t>(sortTileInfo.unSortDimNum); | 1194 | uint32_t hCore = sortTileInfo.maxCoreNum / static_cast<uint32_t>(sortTileInfo.unSortDimNum); |
| 867 | uint32_t hTileData = static_cast<uint32_t>(sortTileInfo.sortAxisNum) / hCore; | 1195 | uint32_t hTileData = static_cast<uint32_t>(sortTileInfo.sortAxisNum) / hCore; |
| 868 | - tileData = CeilAlignDivMul<uint32_t>(int64_t(hTileData), int64_t(topkV2DataInfo::BIN_NUM)); | 1196 | + tileData = static_cast<uint32_t>(Ops::Base::CeilAlign(static_cast<uint64_t>(hTileData), static_cast<uint64_t>(topkV2DataInfo::BIN_NUM))); |
| 869 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); | 1197 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); |
| 870 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); | 1198 | AdjTmpUb(sortTileInfo, tileData, ubExtra, tileFactor); |
| 871 | return tileData; | 1199 | return tileData; |
| @@ -874,15 +1202,15 @@ bool NeedAdjTileData(topkV2DataInfo::SortTileInfo &sortTileInfo, uint32_t &tileD | |||
| 874 | // b大于1且h轴循环次数小于总核数,也就是b轴核数大于1 | 1202 | // b大于1且h轴循环次数小于总核数,也就是b轴核数大于1 |
| 875 | OP_LOGI("RadixSortTiling", "unSortDimNum is one, lastDimTileNum greater than one"); | 1203 | OP_LOGI("RadixSortTiling", "unSortDimNum is one, lastDimTileNum greater than one"); |
| 876 | int64_t newTileData = sortTileInfo.sortAxisNum / int64_t(lastDimTileNum); | 1204 | int64_t newTileData = sortTileInfo.sortAxisNum / int64_t(lastDimTileNum); |
| 877 | - tileData = CeilAlignDivMul<uint32_t>(newTileData, int64_t(topkV2DataInfo::BIN_NUM)); | 1205 | + tileData = static_cast<uint32_t>(Ops::Base::CeilAlign(static_cast<uint64_t>(newTileData), static_cast<uint64_t>(topkV2DataInfo::BIN_NUM))); |
| 878 | - lastDimTileNum = CeilAlignDiv(sortTileInfo.sortAxisNum, int64_t(tileData)); | 1206 | + lastDimTileNum = static_cast<uint32_t>(Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(tileData))); |
| 879 | uint32_t bCore = lastDimTileNum == 0 ? sortTileInfo.maxCoreNum : sortTileInfo.maxCoreNum / lastDimTileNum; | 1207 | uint32_t bCore = lastDimTileNum == 0 ? sortTileInfo.maxCoreNum : sortTileInfo.maxCoreNum / lastDimTileNum; |
| 880 | if (lastDimTileNum < sortTileInfo.maxCoreNum && sortTileInfo.unSortDimNum < int64_t(sortTileInfo.maxCoreNum)) { | 1208 | if (lastDimTileNum < sortTileInfo.maxCoreNum && sortTileInfo.unSortDimNum < int64_t(sortTileInfo.maxCoreNum)) { |
| 881 | if (sortTileInfo.unSortDimNum < int64_t(bCore)) { | 1209 | if (sortTileInfo.unSortDimNum < int64_t(bCore)) { |
| 882 | bCore = static_cast<uint32_t>(sortTileInfo.unSortDimNum); | 1210 | bCore = static_cast<uint32_t>(sortTileInfo.unSortDimNum); |
| 883 | uint32_t hCore = sortTileInfo.maxCoreNum / bCore; | 1211 | uint32_t hCore = sortTileInfo.maxCoreNum / bCore; |
| 884 | - uint32_t tileDataNew = CeilAlignDiv(int64_t(sortTileInfo.sortAxisNum), int64_t(hCore)); | 1212 | + uint32_t tileDataNew = static_cast<uint32_t>(Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(hCore))); |
| 885 | - tileData = CeilAlignDivMul<uint32_t>(int64_t(tileDataNew), int64_t(topkV2DataInfo::BIN_NUM)); | 1213 | + tileData = static_cast<uint32_t>(Ops::Base::CeilAlign(static_cast<uint64_t>(tileDataNew), static_cast<uint64_t>(topkV2DataInfo::BIN_NUM))); |
| 886 | } | 1214 | } |
| 887 | } | 1215 | } |
| 888 | if (bCore == static_cast<uint32_t>(1) && lastDimTileNum < sortTileInfo.maxCoreNum) { | 1216 | if (bCore == static_cast<uint32_t>(1) && lastDimTileNum < sortTileInfo.maxCoreNum) { |
| @@ -920,7 +1248,7 @@ uint32_t ComputeTileData(topkV2DataInfo::SortTileInfo &sortTileInfo) | |||
| 920 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); | 1248 | SetSortTmpSize(ge::DT_UINT8, tileData, false, sortTileInfo); |
| 921 | tmpUbSize = sortTileInfo.tmpUbSize; | 1249 | tmpUbSize = sortTileInfo.tmpUbSize; |
| 922 | } | 1250 | } |
| 923 | - uint32_t lastDimTileNum = CeilAlignDiv(sortTileInfo.sortAxisNum, int64_t(tileData)); | 1251 | + uint32_t lastDimTileNum = Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(tileData)); |
| 924 | OP_LOGI("RadixSortTiling", "tileData %u, lastDimTileNum %u, tmpUbSize %u", tileData, lastDimTileNum, tmpUbSize); | 1252 | OP_LOGI("RadixSortTiling", "tileData %u, lastDimTileNum %u, tmpUbSize %u", tileData, lastDimTileNum, tmpUbSize); |
| 925 | bool smallTile = (sortTileInfo.sortAxisNum <= static_cast<int64_t>(topkV2DataInfo::SMALL_TILE_DATA_NUM)) && | 1253 | bool smallTile = (sortTileInfo.sortAxisNum <= static_cast<int64_t>(topkV2DataInfo::SMALL_TILE_DATA_NUM)) && |
| 926 | lastDimTileNum == uint32_t(1); | 1254 | lastDimTileNum == uint32_t(1); |
| @@ -943,29 +1271,35 @@ void ComputeWorkSpace(gert::TilingContext *context, topkV2DataInfo::SortTileInfo | |||
| 943 | dtypeSizeWk = static_cast<uint32_t>(sizeof(int64_t)); | 1271 | dtypeSizeWk = static_cast<uint32_t>(sizeof(int64_t)); |
| 944 | } | 1272 | } |
| 945 | size_t excusiveBinsGmWkSize = static_cast<size_t>(sortTileInfo.keyParams1) * sortTileInfo.keyParams4 * dtypeSizeWk; | 1273 | size_t excusiveBinsGmWkSize = static_cast<size_t>(sortTileInfo.keyParams1) * sortTileInfo.keyParams4 * dtypeSizeWk; |
| 946 | - excusiveBinsGmWkSize = CeilAlignDivMul<size_t>(int64_t(excusiveBinsGmWkSize), int64_t(sortTileInfo.blockUbSize)); | 1274 | + excusiveBinsGmWkSize = static_cast<size_t>( |
| 1275 | + Ops::Base::CeilAlign(static_cast<uint64_t>(excusiveBinsGmWkSize), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 947 | 1276 | ||
| 948 | - size_t globalHistGmWkSize = | 1277 | + size_t globalHistGmWkSize = |
| 949 | - static_cast<size_t>(sortTileInfo.keyParams3) * sortTileInfo.keyParams2 * sortTileInfo.keyParams0 * dtypeSizeWk; | 1278 | + static_cast<size_t>(sortTileInfo.keyParams3) * sortTileInfo.keyParams2 * sortTileInfo.keyParams0 * dtypeSizeWk; |
| 950 | - globalHistGmWkSize = CeilAlignDivMul<size_t>(int64_t(globalHistGmWkSize), int64_t(sortTileInfo.blockUbSize)); | 1279 | + globalHistGmWkSize = static_cast<size_t>( |
| 1280 | + Ops::Base::CeilAlign(static_cast<uint64_t>(globalHistGmWkSize), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 951 | 1281 | ||
| 952 | size_t outIdxDbWK = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * dtypeSizeWk; | 1282 | size_t outIdxDbWK = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * dtypeSizeWk; |
| 953 | - outIdxDbWK = CeilAlignDivMul<size_t>(int64_t(outIdxDbWK), int64_t(sortTileInfo.blockUbSize)); | 1283 | + outIdxDbWK = static_cast<size_t>( |
| 1284 | + Ops::Base::CeilAlign(static_cast<uint64_t>(outIdxDbWK), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 954 | 1285 | ||
| 955 | - size_t sortOutIdxGMWK = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * | 1286 | + size_t sortOutIdxGMWK = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * |
| 956 | - sortTileInfo.y2DtypeSize; | 1287 | + sortTileInfo.y2DtypeSize; |
| 957 | - sortOutIdxGMWK = CeilAlignDivMul<size_t>(int64_t(sortOutIdxGMWK), int64_t(sortTileInfo.blockUbSize)); | 1288 | + sortOutIdxGMWK = static_cast<size_t>( |
| 1289 | + Ops::Base::CeilAlign(static_cast<uint64_t>(sortOutIdxGMWK), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 958 | 1290 | ||
| 959 | size_t histTileGmWk = static_cast<size_t>(sortTileInfo.lastDimTileNum) * topkV2DataInfo::BIN_NUM * | 1291 | size_t histTileGmWk = static_cast<size_t>(sortTileInfo.lastDimTileNum) * topkV2DataInfo::BIN_NUM * |
| 960 | sortTileInfo.unsortedDimParallel * sizeof(int16_t) * topkV2DataInfo::CONST_2; | 1292 | sortTileInfo.unsortedDimParallel * sizeof(int16_t) * topkV2DataInfo::CONST_2; |
| 961 | 1293 | ||
| 962 | size_t xB8GmWkSize = static_cast<size_t>(sortTileInfo.lastDimTileNum) * sortTileInfo.numTileDataSize * | 1294 | size_t xB8GmWkSize = static_cast<size_t>(sortTileInfo.lastDimTileNum) * sortTileInfo.numTileDataSize * |
| 963 | sortTileInfo.unsortedDimParallel; | 1295 | sortTileInfo.unsortedDimParallel; |
| 964 | - xB8GmWkSize = CeilAlignDivMul<size_t>(int64_t(xB8GmWkSize), int64_t(sortTileInfo.blockUbSize)); | 1296 | + xB8GmWkSize = static_cast<size_t>( |
| 1297 | + Ops::Base::CeilAlign(static_cast<uint64_t>(xB8GmWkSize), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 965 | 1298 | ||
| 966 | size_t outValueDbWKSize = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * | 1299 | size_t outValueDbWKSize = static_cast<size_t>(sortTileInfo.sortAxisNum) * sortTileInfo.unsortedDimParallel * |
| 967 | sortTileInfo.dtypeSize *topkV2DataInfo::CONST_2; | 1300 | sortTileInfo.dtypeSize *topkV2DataInfo::CONST_2; |
| 968 | - outValueDbWKSize = CeilAlignDivMul<size_t>(int64_t(outValueDbWKSize), int64_t(sortTileInfo.blockUbSize)); | 1301 | + outValueDbWKSize = static_cast<size_t>( |
| 1302 | + Ops::Base::CeilAlign(static_cast<uint64_t>(outValueDbWKSize), static_cast<uint64_t>(sortTileInfo.blockUbSize))); | ||
| 969 | 1303 | ||
| 970 | OP_LOGI("RadixSortTiling", | 1304 | OP_LOGI("RadixSortTiling", |
| 971 | "excusiveBinsGmWkSize %lu, globalHistGmWkSize %lu, outIdxDbWK %lu, sortOutIdxGMWK %lu, histTileGmWk %lu," | 1305 | "excusiveBinsGmWkSize %lu, globalHistGmWkSize %lu, outIdxDbWK %lu, sortOutIdxGMWK %lu, histTileGmWk %lu," |
| @@ -982,7 +1316,8 @@ ge::graphStatus GetRadixSortMoreCore(gert::TilingContext *context, topkV2DataInf | |||
| 982 | { | 1316 | { |
| 983 | sortTileInfo.ubSize = sortTileInfo.ubSize - topkV2DataInfo::SIMT_UB; | 1317 | sortTileInfo.ubSize = sortTileInfo.ubSize - topkV2DataInfo::SIMT_UB; |
| 984 | uint32_t tileData = ComputeTileData(sortTileInfo); | 1318 | uint32_t tileData = ComputeTileData(sortTileInfo); |
| 985 | - uint32_t lastDimTileNum = CeilAlignDiv(int64_t(sortTileInfo.sortAxisNum), int64_t(tileData)); | 1319 | + uint32_t lastDimTileNum = |
| 1320 | + Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.sortAxisNum), static_cast<uint64_t>(tileData)); | ||
| 986 | if (sortTileInfo.maxCoreNum <= lastDimTileNum) { | 1321 | if (sortTileInfo.maxCoreNum <= lastDimTileNum) { |
| 987 | sortTileInfo.unsortedDimParallel = static_cast<uint32_t>(1); | 1322 | sortTileInfo.unsortedDimParallel = static_cast<uint32_t>(1); |
| 988 | } else { | 1323 | } else { |
| @@ -993,7 +1328,8 @@ ge::graphStatus GetRadixSortMoreCore(gert::TilingContext *context, topkV2DataInf | |||
| 993 | } | 1328 | } |
| 994 | } | 1329 | } |
| 995 | sortTileInfo.numTileDataSize = tileData; | 1330 | sortTileInfo.numTileDataSize = tileData; |
| 996 | - sortTileInfo.sortLoopTimes = CeilAlignDiv(int64_t(sortTileInfo.unSortDimNum), int64_t(sortTileInfo.unsortedDimParallel)); | 1331 | + sortTileInfo.sortLoopTimes = |
| 1332 | + Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.unSortDimNum), static_cast<uint64_t>(sortTileInfo.unsortedDimParallel)); | ||
| 997 | sortTileInfo.lastDimNeedCore = std::min(sortTileInfo.maxCoreNum, lastDimTileNum); | 1333 | sortTileInfo.lastDimNeedCore = std::min(sortTileInfo.maxCoreNum, lastDimTileNum); |
| 998 | sortTileInfo.coreNumNeed = sortTileInfo.unsortedDimParallel * sortTileInfo.lastDimNeedCore; | 1334 | sortTileInfo.coreNumNeed = sortTileInfo.unsortedDimParallel * sortTileInfo.lastDimNeedCore; |
| 999 | sortTileInfo.lastDimTileNum = lastDimTileNum; | 1335 | sortTileInfo.lastDimTileNum = lastDimTileNum; |
| @@ -1005,18 +1341,23 @@ ge::graphStatus GetRadixSortMoreCore(gert::TilingContext *context, topkV2DataInf | |||
| 1005 | uint32_t allNumGloblHist = topkV2DataInfo::BIN_NUM * lastDimTileNum * sortTileInfo.dtypeSize * | 1341 | uint32_t allNumGloblHist = topkV2DataInfo::BIN_NUM * lastDimTileNum * sortTileInfo.dtypeSize * |
| 1006 | sortTileInfo.unsortedDimParallel; | 1342 | sortTileInfo.unsortedDimParallel; |
| 1007 | uint32_t allNumExcusiveBin = topkV2DataInfo::BIN_NUM * sortTileInfo.dtypeSize * sortTileInfo.unsortedDimParallel; | 1343 | uint32_t allNumExcusiveBin = topkV2DataInfo::BIN_NUM * sortTileInfo.dtypeSize * sortTileInfo.unsortedDimParallel; |
| 1008 | - uint32_t oneCoreSize = CeilAlignDiv(int64_t(allNumGloblHist), int64_t(sortTileInfo.coreNumNeed)); | 1344 | + uint32_t oneCoreSize = |
| 1345 | + Ops::Base::CeilDiv(static_cast<uint64_t>(allNumGloblHist), static_cast<uint64_t>(sortTileInfo.coreNumNeed)); | ||
| 1009 | sortTileInfo.keyParams5 = | 1346 | sortTileInfo.keyParams5 = |
| 1010 | std::max(static_cast<int64_t>(oneCoreSize), static_cast<int64_t>(sortTileInfo.blockUbSize)); | 1347 | std::max(static_cast<int64_t>(oneCoreSize), static_cast<int64_t>(sortTileInfo.blockUbSize)); |
| 1011 | - sortTileInfo.keyParams0 = CeilAlignDiv(int64_t(allNumGloblHist), int64_t(sortTileInfo.keyParams5)); | 1348 | + sortTileInfo.keyParams0 = |
| 1012 | - sortTileInfo.keyParams3 = CeilAlignDiv(int64_t(sortTileInfo.keyParams5), int64_t(ubSizeNum)); | 1349 | + Ops::Base::CeilDiv(static_cast<uint64_t>(allNumGloblHist), static_cast<uint64_t>(sortTileInfo.keyParams5)); |
| 1350 | + sortTileInfo.keyParams3 = | ||
| 1351 | + Ops::Base::CeilDiv(static_cast<uint64_t>(sortTileInfo.keyParams5), static_cast<uint64_t>(ubSizeNum)); | ||
| 1013 | sortTileInfo.keyParams2 = sortTileInfo.keyParams5 > ubSizeNum ? ubSizeNum : sortTileInfo.keyParams5; | 1352 | sortTileInfo.keyParams2 = sortTileInfo.keyParams5 > ubSizeNum ? ubSizeNum : sortTileInfo.keyParams5; |
| 1014 | 1353 | ||
| 1015 | - uint32_t oneCoreSize1 = CeilAlignDiv(int64_t(allNumExcusiveBin), int64_t(sortTileInfo.coreNumNeed)); | 1354 | + uint32_t oneCoreSize1 = |
| 1355 | + Ops::Base::CeilDiv(static_cast<uint64_t>(allNumExcusiveBin), static_cast<uint64_t>(sortTileInfo.coreNumNeed)); | ||
| 1016 | sortTileInfo.keyParams4 = | 1356 | sortTileInfo.keyParams4 = |
| 1017 | - std::max(static_cast<int64_t>(oneCoreSize1), static_cast<int64_t>(sortTileInfo.blockUbSize)); | 1357 | + std::max(static_cast<uint64_t>(oneCoreSize1), static_cast<uint64_t>(sortTileInfo.blockUbSize)); |
| 1018 | 1358 | ||
| 1019 | - sortTileInfo.keyParams1 = CeilAlignDiv(int64_t(allNumExcusiveBin), int64_t(sortTileInfo.keyParams4)); | 1359 | + sortTileInfo.keyParams1 = |
| 1360 | + Ops::Base::CeilDiv(static_cast<uint64_t>(allNumExcusiveBin), static_cast<uint64_t>(sortTileInfo.keyParams4)); | ||
| 1020 | 1361 | ||
| 1021 | // 取前k个结果相关流程的tile计算 | 1362 | // 取前k个结果相关流程的tile计算 |
| 1022 | uint32_t avilableUbSize = (sortTileInfo.ubSize - 1) / topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; | 1363 | uint32_t avilableUbSize = (sortTileInfo.ubSize - 1) / topkV2DataInfo::AGLIN_FACTOR * topkV2DataInfo::AGLIN_FACTOR; |
| @@ -1024,8 +1365,9 @@ ge::graphStatus GetRadixSortMoreCore(gert::TilingContext *context, topkV2DataInf | |||
| 1024 | OP_LOGE("TopKV2", "sortAndTopK Tiling avilableUbSize is zero"), return ge::GRAPH_FAILED); | 1365 | OP_LOGE("TopKV2", "sortAndTopK Tiling avilableUbSize is zero"), return ge::GRAPH_FAILED); |
| 1025 | auto dataType = context->GetInputDesc(0)->GetDataType(); | 1366 | auto dataType = context->GetInputDesc(0)->GetDataType(); |
| 1026 | auto indicesDType = context->GetOutputDesc(1)->GetDataType(); | 1367 | auto indicesDType = context->GetOutputDesc(1)->GetDataType(); |
| 1027 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | 1368 | + |
| 1028 | - uint32_t indexToDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(indicesDType)->second); | 1369 | + uint32_t xDtypeSize = GetDataTypeSize(dataType); |
| 1370 | + uint32_t indexToDtypeSize = GetDataTypeSize(indicesDType); | ||
| 1029 | uint32_t kGetDtypeSize = std::max(xDtypeSize, indexToDtypeSize); | 1371 | uint32_t kGetDtypeSize = std::max(xDtypeSize, indexToDtypeSize); |
| 1030 | OP_CHECK_IF(kGetDtypeSize == 0, OP_LOGE("GetRadixSortMoreCore", "kGetDtypeSize is zero"), return ge::GRAPH_FAILED); | 1372 | OP_CHECK_IF(kGetDtypeSize == 0, OP_LOGE("GetRadixSortMoreCore", "kGetDtypeSize is zero"), return ge::GRAPH_FAILED); |
| 1031 | sortTileInfo.tileDataSize = avilableUbSize / kGetDtypeSize; | 1373 | sortTileInfo.tileDataSize = avilableUbSize / kGetDtypeSize; |
| @@ -1154,6 +1496,32 @@ void PrintTilindDataSort(gert::TilingContext *context, topkV2DataInfo::SortTileI | |||
| 1154 | return; | 1496 | return; |
| 1155 | } | 1497 | } |
| 1156 | 1498 | ||
| 1499 | +ge::graphStatus TileModeSortAndTopK(gert::TilingContext* context, TopKV2TilingDataSimd& topkTilingData, | ||
| 1500 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computeNowTileSizeInfo) { | ||
| 1501 | + topkV2DataInfo::SortTileInfo sortTileInfo; | ||
| 1502 | + | ||
| 1503 | + OP_CHECK_IF(SortCheckParams(context, sortTileInfo) != ge::GRAPH_SUCCESS, | ||
| 1504 | + OP_LOGE(context->GetNodeName(), "sort and topk check params failed"), return ge::GRAPH_FAILED); | ||
| 1505 | + topkTilingData.set_modeType(topkV2DataInfo::SORT_AND_TOP_K_MODE); | ||
| 1506 | + OP_LOGI("[TopKV2Tiling]", "topkTilingData.set_modeType is: %u, SORT_AND_TOP_K_MODE: %u", | ||
| 1507 | + topkTilingData.get_modeType() , topkV2DataInfo::SORT_AND_TOP_K_MODE); | ||
| 1508 | + sortTileInfo.maxCoreNum = static_cast<uint32_t>(computeNowTileSizeInfo.maxCoreNum); | ||
| 1509 | + sortTileInfo.isDescend = static_cast<bool>(computeNowTileSizeInfo.isLargest); | ||
| 1510 | + sortTileInfo.isInt32 = static_cast<uint32_t>(computeNowTileSizeInfo.lastAxisNum <= topkV2DataInfo::INT32_MAX_RANGE_VALUE_FOR_SORT); | ||
| 1511 | + sortTileInfo.topKRealValue = computeNowTileSizeInfo.kValue; | ||
| 1512 | + OP_CHECK_IF(GetRadixSortMoreCore(context, sortTileInfo) != ge::GRAPH_SUCCESS, | ||
| 1513 | + OP_LOGE(context->GetNodeName(), "Get RadixSortMoreCore tiling failed"), return ge::GRAPH_FAILED); | ||
| 1514 | + auto dataTypeKey = topkV2DataInfo::tilingDataTypeKeyMap.find(computeNowTileSizeInfo.dataType)->second; | ||
| 1515 | + context->SetTilingKey(dataTypeKey); | ||
| 1516 | + context->SetBlockDim(sortTileInfo.coreNumNeed); | ||
| 1517 | + context->SetLocalMemorySize(sortTileInfo.ubSize); | ||
| 1518 | + FillTilingDataSort(context, sortTileInfo, topkTilingData); | ||
| 1519 | + PrintTilindDataSort(context, sortTileInfo); | ||
| 1520 | + // sortAndTopK模板核心是Sort,不需要后续Topk相关的tiling计算过程 | ||
| 1521 | + OP_LOGI("TopKV2TilingForAscendC", "TopKV2Tiling end"); | ||
| 1522 | + return ge::GRAPH_SUCCESS; | ||
| 1523 | +} | ||
| 1524 | + | ||
| 1157 | bool needSortWithIndex(TopKV2TilingDataSimd& topkTilingData, bool isSorted, ge::DataType dataType) | 1525 | bool needSortWithIndex(TopKV2TilingDataSimd& topkTilingData, bool isSorted, ge::DataType dataType) |
| 1158 | { | 1526 | { |
| 1159 | if (isSorted && topkTilingData.get_modeType() == topkV2DataInfo::MULT_CORE_MODE) { | 1527 | if (isSorted && topkTilingData.get_modeType() == topkV2DataInfo::MULT_CORE_MODE) { |
| @@ -1173,19 +1541,106 @@ bool needSortWithIndex(TopKV2TilingDataSimd& topkTilingData, bool isSorted, ge:: | |||
| 1173 | return false; | 1541 | return false; |
| 1174 | } | 1542 | } |
| 1175 | 1543 | ||
| 1544 | +/** | ||
| 1545 | + * 执行条件: | ||
| 1546 | + * 1. 仅处理float32数据类型, 4096 <= lastAxisNum <= 32768; | ||
| 1547 | + * 2. splitCoreNum = ceil(lastAxisNum / 2048) > 1 且非尾轴数量 unsortedDimNum * splitCoreNum <= maxCoreNum 且 K > 0; | ||
| 1548 | + */ | ||
| 1549 | +bool IsTopkMergeSortMoreCoreFp32Mode(topkV2DataInfo::TopkComputeNowTileSizeInfo& computNowTileInfo) | ||
| 1550 | +{ | ||
| 1551 | + if (computNowTileInfo.dataType != ge::DT_FLOAT || computNowTileInfo.kValue <= 0) { | ||
| 1552 | + return false; | ||
| 1553 | + } | ||
| 1554 | + double ratio = static_cast<double>(computNowTileInfo.kValue) / computNowTileInfo.lastAxisNum; | ||
| 1555 | + if (ratio < topkV2DataInfo::FP32_K_LAST_AXIS_LOWER_RATIO || topkV2DataInfo::FP32_K_LAST_AXIS_UPPER_RATIO <= ratio) { | ||
| 1556 | + return false; | ||
| 1557 | + } | ||
| 1558 | + | ||
| 1559 | + uint32_t onceMaxElements = | ||
| 1560 | + ComputeTopkMergeMoreCoreOnceMaxElements(computNowTileInfo.ubSizePlatForm, computNowTileInfo.indicesDType); | ||
| 1561 | + if (computNowTileInfo.maxCoreNum == 0 || computNowTileInfo.unsortedDimNum == 0 || | ||
| 1562 | + onceMaxElements < topkV2DataInfo::MERGE_INTRA_CORE_SORT_ALIGN) { | ||
| 1563 | + return false; | ||
| 1564 | + } | ||
| 1565 | + uint32_t splitCoreNum = Ops::Base::CeilDiv(static_cast<uint64_t>(computNowTileInfo.lastAxisNum), | ||
| 1566 | + static_cast<uint64_t>(topkV2DataInfo::MERGE_MORE_CORE_ONE_CORE_DATA_SIZE)); | ||
| 1567 | + if (splitCoreNum <= 1 || splitCoreNum > computNowTileInfo.maxCoreNum) { | ||
| 1568 | + return false; | ||
| 1569 | + } | ||
| 1570 | + if (static_cast<uint64_t>(computNowTileInfo.unsortedDimNum) * splitCoreNum <= computNowTileInfo.maxCoreNum) { | ||
| 1571 | + OP_LOGD("TopKV2Tiling", "float32 more core model onceMaxElements = %d.", onceMaxElements); | ||
| 1572 | + return true; | ||
| 1573 | + } | ||
| 1574 | + return false; | ||
| 1575 | +} | ||
| 1576 | + | ||
| 1577 | +/** | ||
| 1578 | + * 执行条件: | ||
| 1579 | + * 1. MoreCore 路由未命中, 既 IsTopkMergeSortMoreCoreFp32Mode 条件不成立; | ||
| 1580 | + * 2. dtype == fp32 且 尾轴 > 4096 且 blocksPerRow = ceil(N / blockSortSize) <= 256 且 K > 0 | ||
| 1581 | + * | ||
| 1582 | + */ | ||
| 1583 | +bool IsTopkMergeSortIntraCoreFp32Mode(topkV2DataInfo::TopkComputeNowTileSizeInfo& computTileInfo) | ||
| 1584 | +{ | ||
| 1585 | + if (computTileInfo.dataType != ge::DT_FLOAT || | ||
| 1586 | + computTileInfo.unsortedDimNum < computTileInfo.maxCoreNum / 2) { | ||
| 1587 | + return false; | ||
| 1588 | + } | ||
| 1589 | + if (computTileInfo.kValue <= 0) { | ||
| 1590 | + return false; | ||
| 1591 | + } | ||
| 1592 | + double ratio = static_cast<double>(computTileInfo.kValue) / computTileInfo.lastAxisNum; | ||
| 1593 | + if (ratio < topkV2DataInfo::FP32_K_LAST_AXIS_LOWER_RATIO || | ||
| 1594 | + topkV2DataInfo::FP32_K_LAST_AXIS_UPPER_RATIO <= ratio) { | ||
| 1595 | + return false; | ||
| 1596 | + } | ||
| 1597 | + if (!computTileInfo.isSort && computTileInfo.kValue <= topkV2DataInfo::SUPPORT_SORT_MAX_SIZE) { | ||
| 1598 | + return false; | ||
| 1599 | + } | ||
| 1600 | + | ||
| 1601 | + uint32_t blockSortSize = ComputeTopkMergeIntraCoreBlockSortSize(computTileInfo.ubSizePlatForm); | ||
| 1602 | + uint32_t extractChunkSize = ComputeTopkMergeIntraCoreExtractChunkSize(computTileInfo.ubSizePlatForm, | ||
| 1603 | + computTileInfo.indicesDType); | ||
| 1604 | + if (blockSortSize == 0 || extractChunkSize == 0) { | ||
| 1605 | + return false; | ||
| 1606 | + } | ||
| 1607 | + OP_LOGI("IsTopkMergeIntraCoreFp32", "blockSortSize = %d, extractChunkSize=%d, dataType=%d, kValue=%d.", | ||
| 1608 | + blockSortSize, extractChunkSize, computTileInfo.kValue); | ||
| 1609 | + uint32_t blocksPerRow = Ops::Base::CeilDiv(static_cast<uint64_t>(computTileInfo.lastAxisNum), static_cast<uint64_t>(blockSortSize)); | ||
| 1610 | + return blocksPerRow > 1 && blocksPerRow <= topkV2DataInfo::MERGE_INTRA_CORE_MAX_BLOCKS; | ||
| 1611 | +} | ||
| 1612 | + | ||
| 1613 | +ge::graphStatus TileModeFp32MergeSort(gert::TilingContext *context, TopKV2TilingDataSimd& topkTilingData, | ||
| 1614 | + topkV2DataInfo::TopkComputeNowTileSizeInfo& computNowTileInfo) { | ||
| 1615 | + if (IsTopkMergeSortMoreCoreFp32Mode(computNowTileInfo)) { | ||
| 1616 | + return TileModeFp32MoreCoreSort(context, topkTilingData, computNowTileInfo); | ||
| 1617 | + } else { | ||
| 1618 | + return TileModeFp32IntraCoreSort(context, topkTilingData, computNowTileInfo); | ||
| 1619 | + } | ||
| 1620 | +} | ||
| 1621 | + | ||
| 1622 | +bool IsFp32MergeSortMode(topkV2DataInfo::TopkComputeNowTileSizeInfo& computNowTileInfo) { | ||
| 1623 | + bool isMoreCoreModel = IsTopkMergeSortMoreCoreFp32Mode(computNowTileInfo); | ||
| 1624 | + bool isIntraCoreModel = IsTopkMergeSortIntraCoreFp32Mode(computNowTileInfo); | ||
| 1625 | + return isMoreCoreModel || isIntraCoreModel; | ||
| 1626 | +} | ||
| 1627 | + | ||
| 1176 | ge::graphStatus TopKV2Tiling(gert::TilingContext* context, int32_t maxCoreNum) | 1628 | ge::graphStatus TopKV2Tiling(gert::TilingContext* context, int32_t maxCoreNum) |
| 1177 | { | 1629 | { |
| 1178 | OP_LOGI("TopKV2TilingForAscendC", "TopKV2Tiling start"); | 1630 | OP_LOGI("TopKV2TilingForAscendC", "TopKV2Tiling start"); |
| 1179 | TopKV2TilingDataSimd topkTilingData; | 1631 | TopKV2TilingDataSimd topkTilingData; |
| 1180 | - OP_CHECK_IF( | 1632 | + OP_CHECK_IF(IsValidParam(context) == ge::GRAPH_FAILED, OP_LOGE("TopkV2", "Input param is invalid"), |
| 1181 | - IsValidParam(context) == ge::GRAPH_FAILED, OP_LOGE("TopkV2", "Input param is invalid"), | ||
| 1182 | return ge::GRAPH_FAILED); | 1633 | return ge::GRAPH_FAILED); |
| 1634 | + OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return ge::GRAPH_FAILED); | ||
| 1635 | + | ||
| 1183 | const gert::Shape inputShape = context->GetInputShape(0)->GetStorageShape(); | 1636 | const gert::Shape inputShape = context->GetInputShape(0)->GetStorageShape(); |
| 1184 | auto dataType = context->GetInputDesc(0)->GetDataType(); | 1637 | auto dataType = context->GetInputDesc(0)->GetDataType(); |
| 1185 | const gert::Shape outShape = context->GetOutputShape(0)->GetStorageShape(); | 1638 | const gert::Shape outShape = context->GetOutputShape(0)->GetStorageShape(); |
| 1186 | auto dataTypeKey = topkV2DataInfo::tilingDataTypeKeyMap.find(dataType)->second; | 1639 | auto dataTypeKey = topkV2DataInfo::tilingDataTypeKeyMap.find(dataType)->second; |
| 1187 | auto indicesDType = context->GetOutputDesc(1)->GetDataType(); | 1640 | auto indicesDType = context->GetOutputDesc(1)->GetDataType(); |
| 1188 | std::string opType(context->GetNodeType()); | 1641 | std::string opType(context->GetNodeType()); |
| 1642 | + | ||
| 1643 | + // check property | ||
| 1189 | auto const attrs = context->GetAttrs(); | 1644 | auto const attrs = context->GetAttrs(); |
| 1190 | OP_CHECK_NULL_WITH_CONTEXT(context, attrs); | 1645 | OP_CHECK_NULL_WITH_CONTEXT(context, attrs); |
| 1191 | const bool* isSorted = attrs->GetAttrPointer<bool>(0); | 1646 | const bool* isSorted = attrs->GetAttrPointer<bool>(0); |
| @@ -1197,19 +1652,26 @@ ge::graphStatus TopKV2Tiling(gert::TilingContext* context, int32_t maxCoreNum) | |||
| 1197 | const bool* isLargest = attrs->GetAttrPointer<bool>(2); | 1652 | const bool* isLargest = attrs->GetAttrPointer<bool>(2); |
| 1198 | OP_CHECK_NULL_WITH_CONTEXT(context, isLargest); | 1653 | OP_CHECK_NULL_WITH_CONTEXT(context, isLargest); |
| 1199 | OP_LOGI(context->GetNodeName(), "isLargest=%d", *isLargest); | 1654 | OP_LOGI(context->GetNodeName(), "isLargest=%d", *isLargest); |
| 1655 | + | ||
| 1200 | // check the indices_dtype attr and actual value of indices output | 1656 | // check the indices_dtype attr and actual value of indices output |
| 1201 | const int* indicesDTypeValuePtr = attrs->GetAttrPointer<int>(3); | 1657 | const int* indicesDTypeValuePtr = attrs->GetAttrPointer<int>(3); |
| 1202 | OP_CHECK_NULL_WITH_CONTEXT(context, indicesDTypeValuePtr); | 1658 | OP_CHECK_NULL_WITH_CONTEXT(context, indicesDTypeValuePtr); |
| 1203 | OP_LOGI(context->GetNodeName(), "indicesDTypeValuePtr=%d, outPutIndexType=%ld.", *indicesDTypeValuePtr, | 1659 | OP_LOGI(context->GetNodeName(), "indicesDTypeValuePtr=%d, outPutIndexType=%ld.", *indicesDTypeValuePtr, |
| 1204 | static_cast<int64_t>(indicesDType)); | 1660 | static_cast<int64_t>(indicesDType)); |
| 1205 | 1661 | ||
| 1662 | + // 获取输入张量的维度数量 | ||
| 1206 | size_t inputDimNum = inputShape.GetDimNum(); | 1663 | size_t inputDimNum = inputShape.GetDimNum(); |
| 1207 | - OP_CHECK_IF( | 1664 | + |
| 1208 | - *dimValuePtr < static_cast<int32_t>(-inputDimNum) || *dimValuePtr >= static_cast<int32_t>(inputDimNum), | 1665 | + // 验证 dim 参数的有效性(必须在 [-inputDimNum, inputDimNum-1] 范围内) |
| 1209 | - OP_LOGE_WITH_INVALID_ATTR(context->GetNodeName(), "dim", | 1666 | + int32_t dimMin = -static_cast<int32_t>(inputDimNum); |
| 1210 | - std::to_string(*dimValuePtr).c_str(), | 1667 | + int32_t dimMax = static_cast<int32_t>(inputDimNum) - 1; |
| 1211 | - (std::string("range [") + std::to_string(-static_cast<int64_t>(inputDimNum)) + ", " + std::to_string(static_cast<int64_t>(inputDimNum) - 1) + "]").c_str()), | 1668 | + int32_t dimValue = *dimValuePtr; |
| 1212 | - return ge::GRAPH_FAILED); | 1669 | + |
| 1670 | + OP_CHECK_IF(dimValue < dimMin || dimValue > dimMax, | ||
| 1671 | + OP_LOGE_WITH_INVALID_ATTR(context->GetNodeName(), "dim", | ||
| 1672 | + std::to_string(dimValue).c_str(), | ||
| 1673 | + (std::string("range [") + std::to_string(dimMin) + ", " + std::to_string(dimMax) + "]").c_str()), | ||
| 1674 | + return ge::GRAPH_FAILED); | ||
| 1213 | int64_t lastAxisNum = inputShape.GetDim(inputDimNum - 1); | 1675 | int64_t lastAxisNum = inputShape.GetDim(inputDimNum - 1); |
| 1214 | uint32_t unsortedDimNum = 1; | 1676 | uint32_t unsortedDimNum = 1; |
| 1215 | for (uint32_t i = 0; i < (inputDimNum - 1); i++) { | 1677 | for (uint32_t i = 0; i < (inputDimNum - 1); i++) { |
| @@ -1221,107 +1683,72 @@ ge::graphStatus TopKV2Tiling(gert::TilingContext* context, int32_t maxCoreNum) | |||
| 1221 | uint32_t isInInt32Range = static_cast<uint32_t>(lastAxisNum <= int32Max); | 1683 | uint32_t isInInt32Range = static_cast<uint32_t>(lastAxisNum <= int32Max); |
| 1222 | // Get Platform Info | 1684 | // Get Platform Info |
| 1223 | uint64_t ubSizePlatForm = 0; | 1685 | uint64_t ubSizePlatForm = 0; |
| 1686 | + uint64_t originUbSizePlatForm = 0; | ||
| 1224 | auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); | 1687 | auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); |
| 1225 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSizePlatForm); | 1688 | ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSizePlatForm); |
| 1226 | 1689 | ||
| 1227 | uint64_t ubBlock = static_cast<uint64_t>(Ops::Base::GetUbBlockSize(context)); | 1690 | uint64_t ubBlock = static_cast<uint64_t>(Ops::Base::GetUbBlockSize(context)); |
| 1228 | - OP_LOGI("[TopKV2Tiling]", "ubBlock size = : %u", ubBlock); | 1691 | + originUbSizePlatForm = ubSizePlatForm; |
| 1692 | + OP_LOGI("[TopKV2Tiling]", "ubBlock size = : %u, originUbSizePlatForm=%d", ubBlock, originUbSizePlatForm); | ||
| 1229 | 1693 | ||
| 1230 | - // 校验ubSizePlatForm | 1694 | + // 预留空间给SIMT |
| 1231 | ubSizePlatForm -= topkV2DataInfo::CONST_SIMT_SPACE; | 1695 | ubSizePlatForm -= topkV2DataInfo::CONST_SIMT_SPACE; |
| 1232 | - | 1696 | + // 用于模板tilingSize计算 |
| 1233 | - // sortAndTopk模板tiling处理流程,和topk其他模板没有关联性 | 1697 | + topkV2DataInfo::TopkComputeNowTileSizeInfo computeNowTileSizeInfo; |
| 1234 | - if (lastAxisNum > topkV2DataInfo::SORT_AND_TOP_K_THRESHOLD) { | 1698 | + computeNowTileSizeInfo.isLargest = *isLargest; |
| 1235 | - topkV2DataInfo::SortTileInfo sortTileInfo; | 1699 | + computeNowTileSizeInfo.isSort = *isSorted; |
| 1236 | - OP_CHECK_IF(SortCheckParams(context, sortTileInfo) != ge::GRAPH_SUCCESS, | 1700 | + computeNowTileSizeInfo.isInInt32Range = lastAxisNum <= int32Max; |
| 1237 | - OP_LOGE(context->GetNodeName(), "sort and topk check params failed"), return ge::GRAPH_FAILED); | 1701 | + computeNowTileSizeInfo.lastAxisNum = lastAxisNum; |
| 1238 | - topkTilingData.set_modeType(topkV2DataInfo::SORT_AND_TOP_K_MODE); | 1702 | + computeNowTileSizeInfo.kValue = outLastAxisNum; |
| 1239 | - OP_LOGI("[TopKV2Tiling]", "topkTilingData.set_modeType is: %u, SORT_AND_TOP_K_MODE: %u", | 1703 | + computeNowTileSizeInfo.maxCoreNum = maxCoreNum; |
| 1240 | - topkTilingData.get_modeType() , topkV2DataInfo::SORT_AND_TOP_K_MODE); | 1704 | + computeNowTileSizeInfo.ubSizePlatForm = ubSizePlatForm; |
| 1241 | - sortTileInfo.maxCoreNum = static_cast<uint32_t>(maxCoreNum); | 1705 | + computeNowTileSizeInfo.dataType = dataType; |
| 1242 | - sortTileInfo.isDescend = static_cast<bool>(*isLargest); | 1706 | + computeNowTileSizeInfo.indicesDType = indicesDType; |
| 1243 | - sortTileInfo.isInt32 = static_cast<uint32_t>(lastAxisNum <= topkV2DataInfo::INT32_MAX_RANGE_VALUE_FOR_SORT); | 1707 | + computeNowTileSizeInfo.ubBlockAlignSize = ubBlock; |
| 1244 | - sortTileInfo.topKRealValue = outLastAxisNum; | 1708 | + computeNowTileSizeInfo.unsortedDimNum = unsortedDimNum; |
| 1245 | - OP_CHECK_IF(GetRadixSortMoreCore(context, sortTileInfo) != ge::GRAPH_SUCCESS, | ||
| 1246 | - OP_LOGE(context->GetNodeName(), "Get RadixSortMoreCore tiling failed"), return ge::GRAPH_FAILED); | ||
| 1247 | - context->SetTilingKey(dataTypeKey); | ||
| 1248 | - context->SetBlockDim(sortTileInfo.coreNumNeed); | ||
| 1249 | - context->SetLocalMemorySize(sortTileInfo.ubSize); | ||
| 1250 | - FillTilingDataSort(context, sortTileInfo, topkTilingData); | ||
| 1251 | - PrintTilindDataSort(context, sortTileInfo); | ||
| 1252 | - // sortAndTopK模板核心是Sort,不需要后续Topk相关的tiling计算过程 | ||
| 1253 | - OP_LOGI("TopKV2TilingForAscendC", "TopKV2Tiling end"); | ||
| 1254 | - return ge::GRAPH_SUCCESS; | ||
| 1255 | - } | ||
| 1256 | - | ||
| 1257 | - // 用于核间优化模板 tilingSize计算流程 | ||
| 1258 | - topkV2DataInfo::TopkComputingNowTileSizeInfo computingNowTileSizeInfo; | ||
| 1259 | - computingNowTileSizeInfo.isLargest = *isLargest; | ||
| 1260 | - computingNowTileSizeInfo.isSort = *isSorted; | ||
| 1261 | - computingNowTileSizeInfo.isInInt32Range = lastAxisNum <= int32Max; | ||
| 1262 | - computingNowTileSizeInfo.lastAxisNum = lastAxisNum; | ||
| 1263 | - computingNowTileSizeInfo.kValue = outLastAxisNum; | ||
| 1264 | - computingNowTileSizeInfo.maxCoreNum = maxCoreNum; | ||
| 1265 | - computingNowTileSizeInfo.ubSizePlatForm = ubSizePlatForm; | ||
| 1266 | - computingNowTileSizeInfo.dataType = dataType; | ||
| 1267 | - computingNowTileSizeInfo.indicesDType = indicesDType; | ||
| 1268 | - computingNowTileSizeInfo.ubBlockAlignSize = ubBlock; | ||
| 1269 | OP_LOGI( | 1709 | OP_LOGI( |
| 1270 | "[TopKV2Tiling]", | 1710 | "[TopKV2Tiling]", |
| 1271 | - "computingNowTileSizeInfo isLargest: %u, isSort: %u, isInInt32Range: %u, lastAxisNum: %u, kValue: %u, " | 1711 | + "computeNowTileSizeInfo isLargest: %u, isSort: %u, isInInt32Range: %u, lastAxisNum: %u, kValue: %u, " |
| 1272 | "maxCoreNum: %u, ubSizePlatForm: %u", | 1712 | "maxCoreNum: %u, ubSizePlatForm: %u", |
| 1273 | - computingNowTileSizeInfo.isLargest, computingNowTileSizeInfo.isSort, computingNowTileSizeInfo.isInInt32Range, | 1713 | + computeNowTileSizeInfo.isLargest, computeNowTileSizeInfo.isSort, computeNowTileSizeInfo.isInInt32Range, |
| 1274 | - computingNowTileSizeInfo.lastAxisNum, computingNowTileSizeInfo.kValue, computingNowTileSizeInfo.maxCoreNum, | 1714 | + computeNowTileSizeInfo.lastAxisNum, computeNowTileSizeInfo.kValue, computeNowTileSizeInfo.maxCoreNum, |
| 1275 | - computingNowTileSizeInfo.ubSizePlatForm); | 1715 | + computeNowTileSizeInfo.ubSizePlatForm); |
| 1276 | 1716 | ||
| 1277 | - uint32_t nowTileSize = ComputeTopkTileData(context, topkTilingData, computingNowTileSizeInfo); | ||
| 1278 | topkV2DataInfo::TopkTileInfo topkTileInfo; | 1717 | topkV2DataInfo::TopkTileInfo topkTileInfo; |
| 1279 | topkTileInfo.topKOutLastAxisNum = outLastAxisNum; | 1718 | topkTileInfo.topKOutLastAxisNum = outLastAxisNum; |
| 1280 | - | 1719 | + uint32_t nowTileSize = topkV2DataInfo::TMP_DATA_NUM; |
| 1281 | - const uint32_t sortedDimParallelData = (nowTileSize * maxCoreNum) / 2; | 1720 | + if (IsSmallSizeMergeSortMode(dataType, lastAxisNum)) { |
| 1282 | - if (lastAxisNum <= topkV2DataInfo::SMALL_MAX_DATA_SZIE && topkV2DataInfo::optDataTypeBitMap.count(dataType) != 0) { | 1721 | + TileModeSmallSizeOptim(context, topkTilingData, topkTileInfo, computeNowTileSizeInfo); |
| 1283 | - SetMergeSortTmpSize(context, dataType, lastAxisNum, topkTilingData); | ||
| 1284 | - uint32_t nowTileSizeTmp = ComputeMergeSortTileData( | ||
| 1285 | - topkTilingData, dataType, indicesDType, lastAxisNum, maxCoreNum, unsortedDimNum, ubSizePlatForm); | ||
| 1286 | - TileModeSmallSizeOptim(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSizeTmp); | ||
| 1287 | dataTypeKey += topkV2DataInfo::MERGE_SORT_TILING_OFFSET; | 1722 | dataTypeKey += topkV2DataInfo::MERGE_SORT_TILING_OFFSET; |
| 1288 | - } else if (lastAxisNum <= nowTileSize) { | 1723 | + } else if (IsSingleBlockMode(context, topkTilingData, nowTileSize, computeNowTileSizeInfo)) { |
| 1289 | - uint32_t nowTileSizeTmp = ComputeSingleBlockTileData( | 1724 | + TileModeSmallSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 1290 | - context, topkTilingData, dataType, indicesDType, *isLargest, *isSorted, lastAxisNum, outLastAxisNum, | 1725 | + } else if (IsFp32MergeSortMode(computeNowTileSizeInfo)) { |
| 1291 | - ubSizePlatForm); | 1726 | + return TileModeFp32MergeSort(context, topkTilingData, computeNowTileSizeInfo); |
| 1292 | - TileModeSmallSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSizeTmp); | 1727 | + } else if (IsSingleCoreMode(context, topkTilingData, nowTileSize, computeNowTileSizeInfo)) { |
| 1293 | - } else if (IsModeSingleCore(unsortedDimNum, maxCoreNum)) { | 1728 | + TileModeSingleCore(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 1294 | - uint32_t nowTileSizeTmp = ComputeSingleCoreTileData( | 1729 | + } else if (IsMultiCoreOptimMode(context, nowTileSize, topkTilingData, computeNowTileSizeInfo)) { |
| 1295 | - context, topkTilingData, dataType, indicesDType, *isLargest, *isSorted, lastAxisNum, outLastAxisNum, | 1730 | + // topk核间模板优化,修改modeType, tilling不变 |
| 1296 | - ubSizePlatForm); | ||
| 1297 | - OP_CHECK_IF(nowTileSizeTmp == 0, OP_LOGE("TopkV2", "nowTileSizeTmp is 0"), return ge::GRAPH_FAILED); | ||
| 1298 | - TileModeSingleCore( | ||
| 1299 | - unsortedDimNum, maxCoreNum, static_cast<uint32_t>(lastAxisNum), topkTilingData, topkTileInfo, | ||
| 1300 | - nowTileSizeTmp); | ||
| 1301 | - } else if (IsMultiCoreOptimMode(context, nowTileSize, topkTilingData, computingNowTileSizeInfo)) { | ||
| 1302 | - // topk核间模板优化,修改modelType, tilling不变 | ||
| 1303 | TileMultiCoreOptimSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | 1731 | TileMultiCoreOptimSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 1304 | - topkTilingData.set_modeType(topkV2DataInfo::MULT_CORE_OPTIM_MODE); | 1732 | + } else if (IsTopkRadixMoreCoreMode(context, topkTilingData, computeNowTileSizeInfo, nowTileSize)) { |
| 1305 | - } else if (lastAxisNum <= sortedDimParallelData) { | 1733 | + TileTopkMoreCoreMode(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); |
| 1306 | - TileModeMediumSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); | ||
| 1307 | } else { | 1734 | } else { |
| 1308 | - TileModeBigSize(unsortedDimNum, maxCoreNum, lastAxisNum, topkTilingData, topkTileInfo, nowTileSize); // 核间模板 | 1735 | + // sortAndTopk模板处理超大尾轴 |
| 1736 | + return TileModeSortAndTopK(context, topkTilingData, computeNowTileSizeInfo); | ||
| 1309 | } | 1737 | } |
| 1310 | - int64_t maxInputK = std::max(outLastAxisNum, topkTileInfo.lastDimTileNum); | ||
| 1311 | 1738 | ||
| 1312 | if (topkTilingData.get_modeType() == topkV2DataInfo::MULT_CORE_MODE && | 1739 | if (topkTilingData.get_modeType() == topkV2DataInfo::MULT_CORE_MODE && |
| 1313 | - topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64) { | 1740 | + topkTileInfo.topKOutLastAxisNum > topkV2DataInfo::MAX_K_FOR_INT64 && topkTileInfo.multiCoreBigModel) { |
| 1741 | + OP_LOGD("[TopKV2Tiling] radix more core tileSize value halved."); | ||
| 1314 | nowTileSize /= topkV2DataInfo::CONST_TWO; | 1742 | nowTileSize /= topkV2DataInfo::CONST_TWO; |
| 1315 | } | 1743 | } |
| 1316 | 1744 | ||
| 1317 | - GetTopkApiTmpBufferSize( | 1745 | + int64_t maxInputK = std::max(outLastAxisNum, topkTileInfo.lastDimTileNum); |
| 1318 | - context, topkTilingData, topkTileInfo.ubRealLoadDataNum, maxInputK, *isLargest, dataType, *isSorted, | 1746 | + |
| 1319 | - nowTileSize); | 1747 | + GetTopkApiTmpBufferSize(context, topkTilingData, topkTileInfo.ubRealLoadDataNum, maxInputK, *isLargest, |
| 1320 | - OP_CHECK_IF(maxCoreNum == 0, OP_LOGE("TopkV2", "maxCoreNum is 0"), return ge::GRAPH_FAILED); | 1748 | + dataType, *isSorted, nowTileSize); |
| 1321 | int64_t lastDimTileNumTimesValue = (topkTileInfo.lastDimTileNum + maxCoreNum - 1) / maxCoreNum; | 1749 | int64_t lastDimTileNumTimesValue = (topkTileInfo.lastDimTileNum + maxCoreNum - 1) / maxCoreNum; |
| 1322 | - OP_LOGI( | 1750 | + OP_LOGD("[TopKV2Tiling]", "lastAxisNum: %ld, int32Max: %ld, isInInt32Range: %u, nowTileSize: %u", lastAxisNum, |
| 1323 | - "[TopKV2Tiling]", "lastAxisNum: %ld, int32Max: %ld, isInInt32Range: %u, nowTileSize: %u", lastAxisNum, int32Max, | 1751 | + int32Max, isInInt32Range, nowTileSize); |
| 1324 | - isInInt32Range, nowTileSize); | ||
| 1325 | 1752 | ||
| 1326 | // fill the topkTilingData | 1753 | // fill the topkTilingData |
| 1327 | context->SetTilingKey(dataTypeKey); | 1754 | context->SetTilingKey(dataTypeKey); |
| @@ -1357,57 +1784,43 @@ ge::graphStatus TopKV2Tiling(gert::TilingContext* context, int32_t maxCoreNum) | |||
| 1357 | topkTilingData.get_tailLoopBatchNum(), topkTilingData.get_tailBatchNum(), topkTilingData.get_tailTileNum(), | 1784 | topkTilingData.get_tailLoopBatchNum(), topkTilingData.get_tailBatchNum(), topkTilingData.get_tailTileNum(), |
| 1358 | topkTileInfo.coreNumNeed); | 1785 | topkTileInfo.coreNumNeed); |
| 1359 | 1786 | ||
| 1360 | - // TopKV2 Workspace计算流程 | 1787 | + // TopKV2 Workspace 计算流程 |
| 1361 | size_t usrSize = 0; | 1788 | size_t usrSize = 0; |
| 1362 | - OP_LOGI("[TopKV2Tiling]", "begin to calc TopKV2 Workspace size."); | 1789 | + |
| 1363 | - if (isInInt32Range) { | 1790 | + uint64_t alginFactor = topkV2DataInfo::AGLIN_FACTOR; |
| 1364 | - if (topkTilingData.get_modeType() == topkV2DataInfo::SINGLE_CORE_MODE) { | 1791 | + uint32_t modeType = topkTilingData.get_modeType(); |
| 1365 | - usrSize = topkTileInfo.lastDimTileNum * topkV2DataInfo::BIN_NUM * topkTileInfo.unsortedDimParallel * | 1792 | + uint32_t lastDimTileNum = topkTileInfo.lastDimTileNum; |
| 1366 | - sizeof(int32_t); | 1793 | + uint32_t unsortedDimParallel = topkTileInfo.unsortedDimParallel; |
| 1367 | - OP_LOGI("[TopKV2Tiling]", "TopK V2 Workspace size is : %u", usrSize); | 1794 | + |
| 1368 | - } else if (topkTilingData.get_modeType() == topkV2DataInfo::MULT_CORE_OPTIM_MODE) { | 1795 | + // 提取公共变量:索引类型大小(根据数据范围选择 int32 或 int64) |
| 1369 | - uint32_t xDtypeSize = static_cast<uint32_t>(topkV2DataInfo::tilingDataTypeBitMap.find(dataType)->second); | 1796 | + size_t indexTypeSize = isInInt32Range ? sizeof(int32_t) : sizeof(int64_t); |
| 1370 | - size_t tempSortResultNeedSize = Ops::Base::CeilAlign( | 1797 | + |
| 1371 | - static_cast<uint64_t>( | 1798 | + // 根据 modeType 计算 Workspace 大小 |
| 1372 | - xDtypeSize * topkTileInfo.lastDimTileNum * topkTileInfo.unsortedDimParallel * | 1799 | + if (modeType == topkV2DataInfo::SINGLE_CORE_MODE) { |
| 1373 | - topkTilingData.get_topKRealValue()), | 1800 | + usrSize = lastDimTileNum * topkV2DataInfo::BIN_NUM * unsortedDimParallel * indexTypeSize; |
| 1374 | - topkV2DataInfo::AGLIN_FACTOR); | 1801 | + } else if (modeType == topkV2DataInfo::MULT_CORE_OPTIM_MODE && isInInt32Range) { |
| 1375 | - size_t tempSortIndexNeedSize = Ops::Base::CeilAlign( | 1802 | + uint32_t xDtypeSize = GetDataTypeSize(dataType); |
| 1376 | - static_cast<uint64_t>( | 1803 | + uint32_t xDtypeSizeFactor = lastDimTileNum * unsortedDimParallel; |
| 1377 | - sizeof(int32_t) * topkTileInfo.lastDimTileNum * topkTileInfo.unsortedDimParallel * | 1804 | + // 计算临时排序结果空间(对齐) |
| 1378 | - topkTilingData.get_topKRealValue()), | 1805 | + size_t tempSortResultNeedSize = Ops::Base::CeilAlign( |
| 1379 | - topkV2DataInfo::AGLIN_FACTOR); | 1806 | + static_cast<uint64_t>(xDtypeSize * xDtypeSizeFactor * outLastAxisNum), alginFactor); |
| 1380 | - usrSize = tempSortResultNeedSize + tempSortIndexNeedSize; | 1807 | + // 计算临时排序索引空间(对齐) |
| 1381 | - OP_LOGI("[TopKV2Tiling]", "Workspace size for Radix Sort perf template within Int32Range is : %u", usrSize); | 1808 | + size_t tempSortIndexNeedSize = Ops::Base::CeilAlign( |
| 1382 | - } else { | 1809 | + static_cast<uint64_t>(sizeof(int32_t) * xDtypeSizeFactor * outLastAxisNum), alginFactor); |
| 1383 | - size_t dataSetCumSumHistNeedSize = | 1810 | + usrSize = tempSortResultNeedSize + tempSortIndexNeedSize; |
| 1384 | - topkV2DataInfo::BIN_NUM * sizeof(int32_t) * topkTileInfo.unsortedDimParallel; | ||
| 1385 | - size_t dataSetTileTopkNeedSize = Ops::Base::CeilAlign( | ||
| 1386 | - static_cast<uint64_t>(topkTileInfo.lastDimTileNum * sizeof(int32_t) * topkTileInfo.unsortedDimParallel), | ||
| 1387 | - topkV2DataInfo::AGLIN_FACTOR); | ||
| 1388 | - usrSize = dataSetCumSumHistNeedSize + dataSetTileTopkNeedSize * topkV2DataInfo::CONST_TWO; | ||
| 1389 | - OP_LOGI("[TopKV2Tiling]", "Workspace size for Radix Sort more core within Int32Range is : %u", usrSize); | ||
| 1390 | - } | ||
| 1391 | } else { | 1811 | } else { |
| 1392 | - if (topkTilingData.get_modeType() == topkV2DataInfo::SINGLE_CORE_MODE) { | 1812 | + size_t dataSetCumSumHistNeedSize = topkV2DataInfo::BIN_NUM * indexTypeSize * unsortedDimParallel; |
| 1393 | - usrSize = topkTileInfo.lastDimTileNum * topkV2DataInfo::BIN_NUM * topkTileInfo.unsortedDimParallel * | 1813 | + size_t dataSetTileTopkNeedSize = Ops::Base::CeilAlign( |
| 1394 | - sizeof(int64_t); | 1814 | + static_cast<uint64_t>(lastDimTileNum * indexTypeSize * unsortedDimParallel), alginFactor); |
| 1395 | - OP_LOGI("[TopKV2Tiling]", "TopK V2 Workspace size is : %u", usrSize); | 1815 | + usrSize = dataSetCumSumHistNeedSize + dataSetTileTopkNeedSize * topkV2DataInfo::CONST_TWO; |
| 1396 | - } else { | ||
| 1397 | - size_t dataSetCumSumHistNeedSize = | ||
| 1398 | - topkV2DataInfo::BIN_NUM * sizeof(int64_t) * topkTileInfo.unsortedDimParallel; | ||
| 1399 | - size_t dataSetTileTopkNeedSize = Ops::Base::CeilAlign( | ||
| 1400 | - topkTileInfo.lastDimTileNum * sizeof(int64_t) * topkTileInfo.unsortedDimParallel, | ||
| 1401 | - topkV2DataInfo::AGLIN_FACTOR); | ||
| 1402 | - usrSize = dataSetCumSumHistNeedSize + dataSetTileTopkNeedSize * topkV2DataInfo::CONST_TWO; | ||
| 1403 | - OP_LOGI("[TopKV2Tiling]", "Workspace size for Radix Sort more core beyond Int32Range is : %u", usrSize); | ||
| 1404 | - } | ||
| 1405 | } | 1816 | } |
| 1406 | 1817 | ||
| 1407 | // sortWithIndex tiling&workspace计算流程, | 1818 | // sortWithIndex tiling&workspace计算流程, |
| 1408 | if (needSortWithIndex(topkTilingData, *isSorted, dataType)) { | 1819 | if (needSortWithIndex(topkTilingData, *isSorted, dataType)) { |
| 1409 | - OP_CHECK_IF(sortWithIndex::RadixSortTilingOfIdx(context, topkTilingData, maxCoreNum, &usrSize) != ge::GRAPH_SUCCESS, | 1820 | + OP_CHECK_IF(sortWithIndex::RadixSortTilingOfIdx(context, topkTilingData, maxCoreNum, &usrSize) != |
| 1410 | - OP_LOGE(context->GetNodeName(), "SortWithIndex Tiling Simt calc failed"), return ge::GRAPH_FAILED); | 1821 | + ge::GRAPH_SUCCESS, |
| 1822 | + OP_LOGE(context->GetNodeName(), "SortWithIndex Tiling Simt calc failed"), | ||
| 1823 | + return ge::GRAPH_FAILED); | ||
| 1411 | } | 1824 | } |
| 1412 | 1825 | ||
| 1413 | // save tilingdata | 1826 | // save tilingdata |
| @@ -71,6 +71,7 @@ public: | |||
| 71 | uint32_t sortLoopTimes_ = 0; | 71 | uint32_t sortLoopTimes_ = 0; |
| 72 | uint32_t platformCoreNum_ = 0; | 72 | uint32_t platformCoreNum_ = 0; |
| 73 | uint32_t outputLastDimValue_ = 0; | 73 | uint32_t outputLastDimValue_ = 0; |
| 74 | + uint32_t bufferNum_ = DOUBLE_BUFFER; | ||
| 74 | // merge sort kernel | 75 | // merge sort kernel |
| 75 | topkV2::KernelVbsMergeSort<T, CONVERT_TYPE, IS_LARGEST> vbsSort; | 76 | topkV2::KernelVbsMergeSort<T, CONVERT_TYPE, IS_LARGEST> vbsSort; |
| 76 | }; | 77 | }; |
| @@ -100,6 +101,7 @@ __aicore__ inline void MergeSort<T, CONVERT_TYPE, TILING_DATA_TYPE, IS_LARGEST, | |||
| 100 | sortLoopTimes_ = tilingData->sortLoopTimes; | 101 | sortLoopTimes_ = tilingData->sortLoopTimes; |
| 101 | unsortedDimParallel_ = tilingData->unsortedDimParallel; | 102 | unsortedDimParallel_ = tilingData->unsortedDimParallel; |
| 102 | oneCoreRowNum_ = tilingData->oneCoreRowNum; | 103 | oneCoreRowNum_ = tilingData->oneCoreRowNum; |
| 104 | + bufferNum_ = tilingData->keyParams4; | ||
| 103 | // 高阶API需要的临时空间大小 | 105 | // 高阶API需要的临时空间大小 |
| 104 | mergSortAcApiNeedBufferSize_ = tilingData->mergSortAcApiNeedBufferSize; | 106 | mergSortAcApiNeedBufferSize_ = tilingData->mergSortAcApiNeedBufferSize; |
| 105 | } | 107 | } |
| @@ -113,10 +115,10 @@ __aicore__ inline void MergeSort<T, CONVERT_TYPE, TILING_DATA_TYPE, IS_LARGEST, | |||
| 113 | outIndexGm_.SetGlobalBuffer((__gm__ INDEX_TYPE*)(indices)); | 115 | outIndexGm_.SetGlobalBuffer((__gm__ INDEX_TYPE*)(indices)); |
| 114 | // init queue | 116 | // init queue |
| 115 | uint64_t realNum = ROUND_UP_AGLIN(numTileData_) * oneCoreRowNum_; | 117 | uint64_t realNum = ROUND_UP_AGLIN(numTileData_) * oneCoreRowNum_; |
| 116 | - pipe->InitBuffer(inQueueX_, DOUBLE_BUFFER, ROUND_UP_AGLIN(realNum) * sizeof(T)); | 118 | + pipe->InitBuffer(inQueueX_, bufferNum_, ROUND_UP_AGLIN(realNum) * sizeof(T)); |
| 117 | - pipe->InitBuffer(outValueQueue_, DOUBLE_BUFFER, ROUND_UP_AGLIN(realNum * sizeof(T))); | 119 | + pipe->InitBuffer(outValueQueue_, bufferNum_, ROUND_UP_AGLIN(realNum * sizeof(T))); |
| 118 | // 改为实际来支持int64_t | 120 | // 改为实际来支持int64_t |
| 119 | - pipe->InitBuffer(outIndexQueue_, DOUBLE_BUFFER, ROUND_UP_AGLIN(realNum * sizeof(INDEX_TYPE))); | 121 | + pipe->InitBuffer(outIndexQueue_, bufferNum_, ROUND_UP_AGLIN(realNum * sizeof(INDEX_TYPE))); |
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | template <typename T, typename CONVERT_TYPE, typename TILING_DATA_TYPE, bool IS_LARGEST, typename INDEX_TYPE> | 124 | template <typename T, typename CONVERT_TYPE, typename TILING_DATA_TYPE, bool IS_LARGEST, typename INDEX_TYPE> |
| @@ -0,0 +1,357 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | + * \file top_k_merge_sort_intra_core.h | ||
| 13 | + * \brief Intra-core block merge topk for fp32 (inherits from SortMergeIntraCore) | ||
| 14 | + * \details Inherits from Sort::SortMergeIntraCore and overrides 4 key functions to limit output to topKValue. | ||
| 15 | + * Uses this-> to access base class members (cleaner than using declarations). | ||
| 16 | + * Reuses 95% of base class code through inheritance. | ||
| 17 | + */ | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +namespace topkV2 { | ||
| 31 | +using namespace AscendC; | ||
| 32 | + | ||
| 33 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 34 | +class TopKMergeSortIntraCore : public Sort::SortMergeIntraCore<ValueType, IndexType, IsDescend> { | ||
| 35 | +public: | ||
| 36 | + using Base = Sort::SortMergeIntraCore<ValueType, IndexType, IsDescend>; | ||
| 37 | + | ||
| 38 | + __aicore__ inline TopKMergeSortIntraCore() : Base() {} | ||
| 39 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR value, GM_ADDR indices, GM_ADDR workspace, | ||
| 40 | + const TopKV2TilingDataSimd* tilingData, TPipe* pipe); | ||
| 41 | + __aicore__ inline void Process(); | ||
| 42 | + | ||
| 43 | +private: | ||
| 44 | + uint32_t topKValue_ = 0; | ||
| 45 | + | ||
| 46 | + __aicore__ inline uint32_t MergeSingleBatch(); | ||
| 47 | + __aicore__ inline void DoIncrementalMerge(int64_t dstOffsetBase, typename Base::MergeListContext& ctx); | ||
| 48 | + __aicore__ inline void MergeOneGroup(uint32_t groupStart, uint32_t groupBlockCount, | ||
| 49 | + uint32_t fullBlockElemCount, uint32_t fullBlockSortLen, uint32_t lastBlockElemCount, | ||
| 50 | + uint32_t numBlocks, uint32_t pingPongFlag, uint32_t& cumulativeOffset, | ||
| 51 | + uint32_t& mergedGroupElemCount); | ||
| 52 | + __aicore__ inline void CopyRemainingList(typename Base::MergeListContext& ctx, | ||
| 53 | + int64_t dstOffsetBase, uint32_t& dstCumulativeOffset, uint32_t& dstElemCount); | ||
| 54 | + __aicore__ inline void ExtractAndCopyOut(int64_t batchIdx, uint32_t resultRegion); | ||
| 55 | +}; | ||
| 56 | + | ||
| 57 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 58 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::Init( | ||
| 59 | + GM_ADDR x, GM_ADDR value, GM_ADDR indices, GM_ADDR workspace, | ||
| 60 | + const TopKV2TilingDataSimd* tilingData, TPipe* pipe) | ||
| 61 | +{ | ||
| 62 | + if (tilingData == nullptr || pipe == nullptr) { | ||
| 63 | + return; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + topKValue_ = static_cast<uint32_t>(tilingData->topKRealValue); | ||
| 67 | + | ||
| 68 | + SortRegBaseTilingData sortTilingData; | ||
| 69 | + sortTilingData.unsortedDimNum = tilingData->unsortedDimNum; | ||
| 70 | + sortTilingData.lastAxisNum = tilingData->lastAxisNum; | ||
| 71 | + sortTilingData.numTileDataSize = tilingData->numTileDataSize; | ||
| 72 | + sortTilingData.lastDimTileNum = tilingData->lastDimTileNum; | ||
| 73 | + sortTilingData.lastDimNeedCore = tilingData->lastDimNeedCore; | ||
| 74 | + sortTilingData.keyParams0 = tilingData->keyParams0; | ||
| 75 | + sortTilingData.keyParams3 = tilingData->keyParams3; | ||
| 76 | + sortTilingData.keyParams4 = tilingData->keyParams4; | ||
| 77 | + sortTilingData.keyParams5 = tilingData->keyParams5; | ||
| 78 | + | ||
| 79 | + Base::Init(x, value, indices, workspace, &sortTilingData, pipe); | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 83 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::Process() | ||
| 84 | +{ | ||
| 85 | + // Calculate batch range for this core | ||
| 86 | + int64_t startBatch = static_cast<int64_t>(this->blockIdx_) * this->batchPerCore_; | ||
| 87 | + int64_t endBatch = (startBatch + this->batchPerCore_ < this->batchNum_) ? | ||
| 88 | + (startBatch + this->batchPerCore_) : this->batchNum_; | ||
| 89 | + | ||
| 90 | + if (startBatch >= this->batchNum_) { | ||
| 91 | + return; // This core has no work | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + // Process each batch through all 3 phases before moving to the next batch. | ||
| 95 | + // This allows cache (workspace) to be reused across batches within the same core, | ||
| 96 | + | ||
| 97 | + // Precompute buffer sizes (loop-invariant) | ||
| 98 | + uint32_t mergeBufferSize = Sort::MERGE_LIST_MAX_NUM * this->sortBufferSize_; | ||
| 99 | + uint32_t extractInSize = AscendC::GetSortLen<ValueType>(this->extractChunkSize_) * sizeof(ValueType); | ||
| 100 | + | ||
| 101 | + for (int64_t batchIdx = startBatch; batchIdx < endBatch; batchIdx++) { | ||
| 102 | + // ========== Phase 1: Sort blocks in UB ========== | ||
| 103 | + this->pipe_->InitBuffer(this->inQueueX_, DOUBLE_BUFFER, this->blockSortSize_ * sizeof(ValueType)); | ||
| 104 | + this->pipe_->InitBuffer(this->concatTmpBuf_, this->sortBufferSize_); | ||
| 105 | + this->pipe_->InitBuffer(this->sortTmpBuf_, this->sortBufferSize_); | ||
| 106 | + this->pipe_->InitBuffer(this->sortedOutQueue_, DOUBLE_BUFFER, this->sortBufferSize_); | ||
| 107 | + this->pipe_->InitBuffer(this->indexTmpBuf_, this->blockSortSize_ * sizeof(uint32_t)); | ||
| 108 | + | ||
| 109 | + this->SortSingleBatchInUb(this->inputXGm_, batchIdx * this->sortAxisNum_); | ||
| 110 | + | ||
| 111 | + event_t eventId = static_cast<event_t>(this->pipe_->FetchEventID(HardEvent::MTE3_MTE2)); | ||
| 112 | + SetFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 113 | + WaitFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 114 | + | ||
| 115 | + this->pipe_->Reset(); | ||
| 116 | + | ||
| 117 | + // ========== Phase 2: Merge sorted blocks (4-way) ========== | ||
| 118 | + this->pipe_->InitBuffer(this->mergeInQueue_, 1, mergeBufferSize); | ||
| 119 | + this->pipe_->InitBuffer(this->mergeOutQueue_, 1, mergeBufferSize); | ||
| 120 | + | ||
| 121 | + uint32_t resultRegion = MergeSingleBatch(); | ||
| 122 | + | ||
| 123 | + eventId = static_cast<event_t>(this->pipe_->FetchEventID(HardEvent::MTE3_MTE2)); | ||
| 124 | + SetFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 125 | + WaitFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 126 | + | ||
| 127 | + this->pipe_->Reset(); | ||
| 128 | + | ||
| 129 | + // ========== Phase 3: Extract and copy output ========== | ||
| 130 | + this->pipe_->InitBuffer(this->extractInQueue_, DOUBLE_BUFFER, extractInSize); | ||
| 131 | + this->pipe_->InitBuffer(this->outValueQueue_, DOUBLE_BUFFER, this->extractChunkSize_ * sizeof(ValueType)); | ||
| 132 | + this->pipe_->InitBuffer(this->outIdxQueue_, DOUBLE_BUFFER, this->extractChunkSize_ * sizeof(uint32_t)); | ||
| 133 | + if constexpr (IsSameType<int64_t, IndexType>::value) { | ||
| 134 | + this->pipe_->InitBuffer(this->outIdxInt64Queue_, DOUBLE_BUFFER, this->extractChunkSize_ * sizeof(int64_t)); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + ExtractAndCopyOut(batchIdx, resultRegion); | ||
| 138 | + | ||
| 139 | + this->pipe_->Reset(); | ||
| 140 | + } | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 144 | +__aicore__ inline uint32_t TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::MergeSingleBatch() | ||
| 145 | +{ | ||
| 146 | + uint32_t numBlocks = this->blocksPerRow_; | ||
| 147 | + uint32_t fullBlockElemCount = this->blockSortSize_; | ||
| 148 | + uint32_t fullBlockSortLen = this->blockSortLen_; | ||
| 149 | + uint32_t lastBlockElemCount = this->lastBlockSize_; | ||
| 150 | + | ||
| 151 | + uint32_t pingPongFlag = 0; | ||
| 152 | + uint32_t mergeRounds = 0; | ||
| 153 | + | ||
| 154 | + while (numBlocks > 1) { | ||
| 155 | + uint32_t cumulativeOffset = 0; | ||
| 156 | + uint32_t newNumBlocks = 0; | ||
| 157 | + uint32_t newFullBlockElemCount = 0; | ||
| 158 | + uint32_t newLastBlockElemCount = 0; | ||
| 159 | + | ||
| 160 | + for (uint32_t i = 0; i < numBlocks; i += Sort::MERGE_LIST_MAX_NUM) { | ||
| 161 | + uint32_t groupBlockCount = (i + Sort::MERGE_LIST_MAX_NUM <= numBlocks) ? | ||
| 162 | + Sort::MERGE_LIST_MAX_NUM : (numBlocks - i); | ||
| 163 | + | ||
| 164 | + uint32_t mergedGroupElemCount = 0; | ||
| 165 | + MergeOneGroup(i, groupBlockCount, fullBlockElemCount, fullBlockSortLen, lastBlockElemCount, | ||
| 166 | + numBlocks, pingPongFlag, cumulativeOffset, mergedGroupElemCount); | ||
| 167 | + if (newNumBlocks == 0) { | ||
| 168 | + newFullBlockElemCount = mergedGroupElemCount; | ||
| 169 | + } | ||
| 170 | + newLastBlockElemCount = mergedGroupElemCount; | ||
| 171 | + newNumBlocks++; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + if (newNumBlocks == 0 || newNumBlocks >= numBlocks) { | ||
| 175 | + break; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + numBlocks = newNumBlocks; | ||
| 179 | + if (numBlocks == 1) { | ||
| 180 | + fullBlockElemCount = newLastBlockElemCount; | ||
| 181 | + } else { | ||
| 182 | + fullBlockElemCount = newFullBlockElemCount; | ||
| 183 | + } | ||
| 184 | + fullBlockSortLen = AscendC::GetSortLen<ValueType>(fullBlockElemCount); | ||
| 185 | + lastBlockElemCount = newLastBlockElemCount; | ||
| 186 | + pingPongFlag = 1 - pingPongFlag; | ||
| 187 | + mergeRounds++; | ||
| 188 | + event_t eventId = static_cast<event_t>(this->pipe_->FetchEventID(HardEvent::MTE3_MTE2)); | ||
| 189 | + SetFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 190 | + WaitFlag<HardEvent::MTE3_MTE2>(eventId); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + return (mergeRounds == 0) ? 0 : pingPongFlag; | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 197 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::MergeOneGroup( | ||
| 198 | + uint32_t groupStart, uint32_t groupBlockCount, | ||
| 199 | + uint32_t fullBlockElemCount, uint32_t fullBlockSortLen, uint32_t lastBlockElemCount, | ||
| 200 | + uint32_t numBlocks, uint32_t pingPongFlag, uint32_t& cumulativeOffset, | ||
| 201 | + uint32_t& mergedGroupElemCount) | ||
| 202 | +{ | ||
| 203 | + typename Base::MergeListContext ctx; | ||
| 204 | + ctx.listCount = groupBlockCount; | ||
| 205 | + | ||
| 206 | + int64_t srcRegionOffset = (pingPongFlag == 0) ? 0 : this->batchSortLen_; | ||
| 207 | + int64_t dstRegionOffset = (pingPongFlag == 0) ? this->batchSortLen_ : 0; | ||
| 208 | + | ||
| 209 | + for (uint32_t j = 0; j < groupBlockCount; j++) { | ||
| 210 | + uint32_t blockIdx = groupStart + j; | ||
| 211 | + ctx.srcOffsets[j] = srcRegionOffset + blockIdx * fullBlockSortLen; | ||
| 212 | + ctx.elemCounts[j] = (blockIdx < numBlocks - 1) ? fullBlockElemCount : lastBlockElemCount; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + if (groupBlockCount > 1) { | ||
| 216 | + DoIncrementalMerge(dstRegionOffset + cumulativeOffset, ctx); | ||
| 217 | + | ||
| 218 | + uint32_t totalElem = 0; | ||
| 219 | + for (uint32_t j = 0; j < groupBlockCount; j++) { | ||
| 220 | + totalElem += ctx.elemCounts[j]; | ||
| 221 | + } | ||
| 222 | + mergedGroupElemCount = (totalElem > topKValue_) ? topKValue_ : totalElem; // TopK limitation | ||
| 223 | + cumulativeOffset += AscendC::GetSortLen<ValueType>(mergedGroupElemCount); | ||
| 224 | + } else if (groupBlockCount == 1) { | ||
| 225 | + mergedGroupElemCount = (ctx.elemCounts[0] > topKValue_) ? topKValue_ : ctx.elemCounts[0]; // TopK limitation | ||
| 226 | + if (ctx.elemCounts[0] > 0) { | ||
| 227 | + int64_t srcOffset = ctx.srcOffsets[0]; | ||
| 228 | + uint32_t remainElems = mergedGroupElemCount; | ||
| 229 | + uint32_t srcChunkOffset = 0; | ||
| 230 | + while (remainElems > 0) { | ||
| 231 | + uint32_t chunkSize = (remainElems > this->blockSortSize_) ? this->blockSortSize_ : remainElems; | ||
| 232 | + if (chunkSize == 0) break; | ||
| 233 | + this->CopyBlockChunk(srcOffset + AscendC::GetSortLen<ValueType>(srcChunkOffset), | ||
| 234 | + dstRegionOffset + cumulativeOffset + AscendC::GetSortLen<ValueType>(srcChunkOffset), chunkSize); | ||
| 235 | + remainElems -= chunkSize; | ||
| 236 | + srcChunkOffset += chunkSize; | ||
| 237 | + } | ||
| 238 | + cumulativeOffset += AscendC::GetSortLen<ValueType>(mergedGroupElemCount); | ||
| 239 | + } | ||
| 240 | + } | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 244 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::DoIncrementalMerge( | ||
| 245 | + int64_t dstOffsetBase, typename Base::MergeListContext& ctx) | ||
| 246 | +{ | ||
| 247 | + if (ctx.listCount > Sort::MERGE_LIST_MAX_NUM) return; | ||
| 248 | + | ||
| 249 | + for (uint32_t i = 0; i < ctx.listCount; i++) { | ||
| 250 | + ctx.remains[i] = ctx.elemCounts[i]; | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + uint32_t dstCumulativeOffset = 0, dstElemCount = 0, loopGuard = 0; | ||
| 254 | + while (dstElemCount < topKValue_) { // TopK: early termination | ||
| 255 | + uint32_t activeLists = 0; | ||
| 256 | + for (uint32_t i = 0; i < ctx.listCount; i++) { | ||
| 257 | + if (ctx.remains[i] > 0) activeLists++; | ||
| 258 | + } | ||
| 259 | + if (activeLists <= 1) break; | ||
| 260 | + | ||
| 261 | + LocalTensor<ValueType> ubMainInput = this->mergeInQueue_.template AllocTensor<ValueType>(); | ||
| 262 | + uint16_t elementCountList[Sort::MERGE_LIST_MAX_NUM] = {0, 0, 0, 0}; | ||
| 263 | + uint32_t remainListNum = this->LoadListsToUb(ubMainInput, elementCountList, ctx); | ||
| 264 | + this->mergeInQueue_.EnQue(ubMainInput); | ||
| 265 | + | ||
| 266 | + LocalTensor<ValueType> ubMainInputCalc = this->mergeInQueue_.template DeQue<ValueType>(); | ||
| 267 | + LocalTensor<ValueType> dstLocal = this->mergeOutQueue_.template AllocTensor<ValueType>(); | ||
| 268 | + | ||
| 269 | + uint32_t listSortedNums[Sort::MERGE_LIST_MAX_NUM] = {0, 0, 0, 0}; | ||
| 270 | + uint32_t mergedCount = this->ExecuteMrgSort(dstLocal, ubMainInputCalc, | ||
| 271 | + elementCountList, listSortedNums, remainListNum); | ||
| 272 | + if (mergedCount == 0) { | ||
| 273 | + this->mergeInQueue_.FreeTensor(ubMainInputCalc); | ||
| 274 | + this->mergeOutQueue_.FreeTensor(dstLocal); | ||
| 275 | + break; | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + this->mergeOutQueue_.EnQue(dstLocal); | ||
| 279 | + this->mergeInQueue_.FreeTensor(ubMainInputCalc); | ||
| 280 | + | ||
| 281 | + LocalTensor<ValueType> dstLocalOut = this->mergeOutQueue_.template DeQue<ValueType>(); | ||
| 282 | + uint32_t copyCount = mergedCount; | ||
| 283 | + if (dstElemCount + copyCount > topKValue_) { // TopK: limit output | ||
| 284 | + copyCount = topKValue_ - dstElemCount; | ||
| 285 | + } | ||
| 286 | + DataCopyExtParams outCopyParams{1, static_cast<uint32_t>(AscendC::GetSortLen<ValueType>(copyCount) * sizeof(ValueType)), 0, 0, 0}; | ||
| 287 | + DataCopyPad(this->cacheGm_[dstOffsetBase + dstCumulativeOffset], dstLocalOut, outCopyParams); | ||
| 288 | + this->mergeOutQueue_.FreeTensor(dstLocalOut); | ||
| 289 | + | ||
| 290 | + uint32_t j = 0; | ||
| 291 | + for (uint32_t i = 0; i < ctx.listCount; i++) { | ||
| 292 | + if (ctx.remains[i] > 0) { | ||
| 293 | + ctx.gmOffsets[i] += AscendC::GetSortLen<ValueType>(listSortedNums[j]); | ||
| 294 | + ctx.remains[i] -= listSortedNums[j]; | ||
| 295 | + j++; | ||
| 296 | + } | ||
| 297 | + } | ||
| 298 | + dstCumulativeOffset += AscendC::GetSortLen<ValueType>(copyCount); | ||
| 299 | + dstElemCount += copyCount; | ||
| 300 | + if (++loopGuard > this->maxMergeIterations_) break; | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + CopyRemainingList(ctx, dstOffsetBase, dstCumulativeOffset, dstElemCount); | ||
| 304 | +} | ||
| 305 | + | ||
| 306 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 307 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::CopyRemainingList( | ||
| 308 | + typename Base::MergeListContext& ctx, int64_t dstOffsetBase, uint32_t& dstCumulativeOffset, uint32_t& dstElemCount) | ||
| 309 | +{ | ||
| 310 | + for (uint32_t listIdx = 0; listIdx < ctx.listCount && dstElemCount < topKValue_; listIdx++) { // TopK: early stop | ||
| 311 | + while (ctx.remains[listIdx] > 0) { | ||
| 312 | + if (dstElemCount >= topKValue_) { | ||
| 313 | + break; | ||
| 314 | + } | ||
| 315 | + uint32_t loadCount = (ctx.remains[listIdx] > this->blockSortSize_) ? this->blockSortSize_ : ctx.remains[listIdx]; | ||
| 316 | + uint32_t remainingTopK = topKValue_ - dstElemCount; | ||
| 317 | + loadCount = (loadCount > remainingTopK) ? remainingTopK : loadCount; // TopK: limit chunk | ||
| 318 | + if (loadCount == 0) break; | ||
| 319 | + | ||
| 320 | + this->CopyBlockChunk(ctx.srcOffsets[listIdx] + ctx.gmOffsets[listIdx], | ||
| 321 | + dstOffsetBase + dstCumulativeOffset, loadCount); | ||
| 322 | + | ||
| 323 | + ctx.gmOffsets[listIdx] += AscendC::GetSortLen<ValueType>(loadCount); | ||
| 324 | + ctx.remains[listIdx] -= loadCount; | ||
| 325 | + dstCumulativeOffset += AscendC::GetSortLen<ValueType>(loadCount); | ||
| 326 | + dstElemCount += loadCount; | ||
| 327 | + } | ||
| 328 | + } | ||
| 329 | +} | ||
| 330 | + | ||
| 331 | +template <typename ValueType, typename IndexType, bool IsDescend> | ||
| 332 | +__aicore__ inline void TopKMergeSortIntraCore<ValueType, IndexType, IsDescend>::ExtractAndCopyOut( | ||
| 333 | + int64_t batchIdx, uint32_t resultRegion) | ||
| 334 | +{ | ||
| 335 | + int64_t outputOffset = batchIdx * static_cast<int64_t>(topKValue_); // TopK: output offset | ||
| 336 | + | ||
| 337 | + int64_t cacheBatchOffset = (resultRegion == 1) ? this->batchSortLen_ : 0; | ||
| 338 | + | ||
| 339 | + uint32_t totalElem = topKValue_; // TopK: limit output count | ||
| 340 | + uint32_t elemProcessed = 0; | ||
| 341 | + uint32_t cacheOffset = 0; | ||
| 342 | + | ||
| 343 | + while (elemProcessed < totalElem) { | ||
| 344 | + uint32_t elemCount = (elemProcessed + this->extractChunkSize_ <= totalElem) ? | ||
| 345 | + this->extractChunkSize_ : (totalElem - elemProcessed); | ||
| 346 | + if (elemCount == 0) break; | ||
| 347 | + | ||
| 348 | + this->ExtractAndCopyChunk(cacheBatchOffset, cacheOffset, outputOffset, elemProcessed, elemCount); | ||
| 349 | + | ||
| 350 | + elemProcessed += elemCount; | ||
| 351 | + cacheOffset += AscendC::GetSortLen<ValueType>(elemCount); | ||
| 352 | + } | ||
| 353 | +} | ||
| 354 | + | ||
| 355 | +} // namespace topkV2 | ||
| 356 | + | ||
| 357 | + | ||
| @@ -0,0 +1,629 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | + * \file top_k_merge_sort_more_core.h | ||
| 13 | + * \brief topk merge sort more-core kernel entry | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace topkV2 { | ||
| 24 | +using namespace AscendC; | ||
| 25 | +constexpr uint32_t MORE_CORE_FP32_DTYPE = 4; | ||
| 26 | +constexpr uint32_t MORE_CORE_DOUBLE_BUFFER = 1; | ||
| 27 | +constexpr uint32_t MORE_CORE_BLOCK_UB = Ops::Base::GetUbBlockSize(); | ||
| 28 | +constexpr uint32_t MORE_CORE_MERGE_SORT_LIST_MAX_NUM = 4; | ||
| 29 | +constexpr uint32_t MORE_CORE_DEALING_CONCAT_NUM_ONCE = 16; | ||
| 30 | +constexpr uint32_t MORE_CORE_DEALING_SORT_NUM_ONCE = 32; | ||
| 31 | +constexpr uint32_t MORE_CORE_DEALING_EXTRACT_NUM_ONCE = 32; | ||
| 32 | +constexpr int32_t MORE_CORE_XOR_OP_VALUE_FP = 0x80000000; | ||
| 33 | +constexpr int16_t MORE_CORE_XOR_OP_VALUE_HALF = 0x8000; | ||
| 34 | + | ||
| 35 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 36 | +struct TopKMergeSortMoreCore { | ||
| 37 | + __aicore__ inline TopKMergeSortMoreCore() {} | ||
| 38 | + __aicore__ inline void Init(GM_ADDR inputValue, GM_ADDR value, GM_ADDR indices, GM_ADDR workSpace, const TopKV2TilingDataSimd* tilingData, TPipe* pipe); | ||
| 39 | + __aicore__ inline void Process(); | ||
| 40 | + __aicore__ inline void SortInSingleCore(uint32_t tileNum, int64_t offsetPerCore); | ||
| 41 | + __aicore__ inline void CopyInData(uint32_t tileNum, int64_t offsetPerCore); | ||
| 42 | + __aicore__ inline void InitIndexLocal(uint32_t tileNum, LocalTensor<uint32_t> sortedValueIndexLocal, int64_t offsetPerCore); | ||
| 43 | + __aicore__ inline void DoSort(uint32_t tileNum, LocalTensor<T> inputLocal, LocalTensor<CONVERT_TYPE> sortedValueLocal, LocalTensor<uint32_t> sortedValueIndexLocal); | ||
| 44 | + __aicore__ inline void DoSortBf16(uint32_t tileNum, LocalTensor<T> inputLocal, LocalTensor<CONVERT_TYPE> sortedValueLocal, LocalTensor<uint32_t> sortedValueIndexLocal); | ||
| 45 | + __aicore__ inline void CopyOutWorkSpace(uint32_t tileNum, int64_t offsetPerCore, LocalTensor<CONVERT_TYPE> sortedValueLocal); | ||
| 46 | + __aicore__ inline void CopyOutMultiCore(); | ||
| 47 | + __aicore__ inline void SortInMultiCore(); | ||
| 48 | + __aicore__ inline void FinalSortAndCopy(); | ||
| 49 | + __aicore__ inline void MultiCoreInit(); | ||
| 50 | + __aicore__ inline void FinalSortInit(); | ||
| 51 | + __aicore__ inline void FlipSignBit(LocalTensor<CONVERT_TYPE> xLocal, uint32_t aglinTileNum); | ||
| 52 | + __aicore__ inline void CopyInMultiCore(); | ||
| 53 | + __aicore__ inline void UpdateMrgParam(); | ||
| 54 | + __aicore__ inline void DealingMergeSort(); | ||
| 55 | + __aicore__ inline void UpdateSortInfo(); | ||
| 56 | + __aicore__ inline void ExtractAndCopyOut(); | ||
| 57 | + __aicore__ inline void ClearCache(); | ||
| 58 | + __aicore__ inline uint32_t GetRemainingTopK() const; | ||
| 59 | +public: | ||
| 60 | + TQue<QuePosition::VECIN, MORE_CORE_DOUBLE_BUFFER> inputQueue_; | ||
| 61 | + TQue<QuePosition::VECOUT, MORE_CORE_DOUBLE_BUFFER> outValueQueue_; | ||
| 62 | + TQue<QuePosition::VECOUT, MORE_CORE_DOUBLE_BUFFER> outIndexQueue_; | ||
| 63 | + TQue<QuePosition::VECOUT, MORE_CORE_DOUBLE_BUFFER> sortedQueue_; | ||
| 64 | + TQue<QuePosition::VECIN, MORE_CORE_DOUBLE_BUFFER> copyInQueue_; | ||
| 65 | + TQue<QuePosition::VECOUT, MORE_CORE_DOUBLE_BUFFER> castValueQueue_; | ||
| 66 | + TQue<QuePosition::VECOUT, MORE_CORE_DOUBLE_BUFFER> castIndexQueue_; | ||
| 67 | + // input value | ||
| 68 | + GlobalTensor<T> inputValueGm_; | ||
| 69 | + // output value | ||
| 70 | + GlobalTensor<T> outValueGm_; | ||
| 71 | + // output index | ||
| 72 | + GlobalTensor<INDEX_TYPE> outIndexGm_; | ||
| 73 | + | ||
| 74 | + GlobalTensor<CONVERT_TYPE> workspaceGm_[2]; | ||
| 75 | + GlobalTensor<CONVERT_TYPE> workspaceInput_; | ||
| 76 | + GlobalTensor<CONVERT_TYPE> workspaceOutput_; | ||
| 77 | + | ||
| 78 | + TBuf<QuePosition::VECCALC> sortedValueUb_; | ||
| 79 | + TBuf<QuePosition::VECCALC> sortedValueIndexUb_; | ||
| 80 | + TBuf<QuePosition::VECCALC> concatTempBuf_; | ||
| 81 | + TBuf<QuePosition::VECCALC> sortTempBuf_; | ||
| 82 | + TBuf<QuePosition::VECCALC> inputValueTempBuf_; | ||
| 83 | + TBuf<QuePosition::VECCALC> sortedValueLocalCastTbuf_; | ||
| 84 | + | ||
| 85 | + TPipe *pipe_; | ||
| 86 | + uint32_t blockIdx_ = 0; | ||
| 87 | + uint32_t numTileData_ = 0; | ||
| 88 | + uint32_t sortLoopRound_ = 0; | ||
| 89 | + uint32_t platformCoreNum_ = 0; | ||
| 90 | + uint32_t inputLastDimValue_ = 0; | ||
| 91 | + uint32_t outputTopKValue_ = 0; | ||
| 92 | + uint32_t frontCoreNum_ = 0; | ||
| 93 | + uint32_t rowIdx_ = 0; | ||
| 94 | + uint32_t rowCoreIdx_ = 0; | ||
| 95 | + uint32_t vfLenFp32_ = Ops::Base::GetVRegSize() / MORE_CORE_FP32_DTYPE; | ||
| 96 | + int64_t rowDataOffset_ = 0; | ||
| 97 | + int64_t rowWorkspaceOffset_ = 0; | ||
| 98 | + int64_t rowOutputOffset_ = 0; | ||
| 99 | + | ||
| 100 | + // SortMultiCore | ||
| 101 | + int64_t listNum_{0}; | ||
| 102 | + int64_t flag_ = 0; | ||
| 103 | + int64_t remainListNum_{0}; | ||
| 104 | + int64_t outOffset_{0}; | ||
| 105 | + int64_t offsets_[4] = {0}; | ||
| 106 | + int64_t listRemainElements_[4] = {0}; | ||
| 107 | + int64_t currentElements_{0}; | ||
| 108 | + int64_t currentTailElements_{0}; | ||
| 109 | + int64_t dealLengths_[4] = {0}; | ||
| 110 | + int64_t allRemainElements_{0}; | ||
| 111 | + int64_t curLoopSortedNum_{0}; | ||
| 112 | + int64_t onceMaxElements_{0}; | ||
| 113 | + uint16_t elementCountList_[4] = {0}; | ||
| 114 | + uint16_t validBitTail_; | ||
| 115 | + uint32_t listSortedNums_[4] = {0}; | ||
| 116 | + uint32_t workSpaceFlag_ = 0; | ||
| 117 | + LocalTensor<CONVERT_TYPE> ubInputs_[4]; | ||
| 118 | + LocalTensor<CONVERT_TYPE> ubMainInput_; | ||
| 119 | +}; | ||
| 120 | + | ||
| 121 | +__aicore__ inline int64_t Align(int64_t elementNum, int64_t bytes) | ||
| 122 | +{ | ||
| 123 | + if (bytes == 0) { | ||
| 124 | + return 0; | ||
| 125 | + } | ||
| 126 | + return (elementNum * bytes + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB * MORE_CORE_BLOCK_UB / bytes; | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 130 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::Init(GM_ADDR inputValue, | ||
| 131 | + GM_ADDR value, GM_ADDR indices, GM_ADDR workSpace, const TopKV2TilingDataSimd* tilingData, TPipe* pipe) | ||
| 132 | +{ | ||
| 133 | + blockIdx_ = GetBlockIdx(); | ||
| 134 | + pipe_ = pipe; | ||
| 135 | + inputLastDimValue_ = static_cast<uint32_t>(tilingData->lastAxisNum); | ||
| 136 | + outputTopKValue_ = static_cast<uint32_t>(tilingData->topKRealValue); | ||
| 137 | + numTileData_ = tilingData->numTileDataSize; | ||
| 138 | + frontCoreNum_ = tilingData->lastDimNeedCore; | ||
| 139 | + uint32_t sortBufferSize = 8; | ||
| 140 | + rowIdx_ = frontCoreNum_ == 0 ? 0 : blockIdx_ / frontCoreNum_; | ||
| 141 | + rowCoreIdx_ = frontCoreNum_ == 0 ? 0 : blockIdx_ % frontCoreNum_; | ||
| 142 | + rowDataOffset_ = static_cast<int64_t>(rowIdx_) * static_cast<int64_t>(inputLastDimValue_); | ||
| 143 | + rowOutputOffset_ = static_cast<int64_t>(rowIdx_) * static_cast<int64_t>(outputTopKValue_); | ||
| 144 | + // Per-row workspace stores Sort API sort-struct data. This capacity uses sortBufferSize bytes per | ||
| 145 | + // original element and UB-block byte alignment; it must cover later GetSortLen-based accesses. | ||
| 146 | + rowWorkspaceOffset_ = | ||
| 147 | + static_cast<int64_t>(rowIdx_) * Align(inputLastDimValue_, sortBufferSize) * sortBufferSize / | ||
| 148 | + sizeof(CONVERT_TYPE) * 2; | ||
| 149 | + onceMaxElements_ = tilingData->keyParams0 / MORE_CORE_DEALING_SORT_NUM_ONCE * MORE_CORE_DEALING_SORT_NUM_ONCE; | ||
| 150 | + | ||
| 151 | + inputValueGm_.SetGlobalBuffer((__gm__ T*)(inputValue)); | ||
| 152 | + outValueGm_.SetGlobalBuffer((__gm__ T*)(value)); | ||
| 153 | + outIndexGm_.SetGlobalBuffer((__gm__ INDEX_TYPE*)(indices)); | ||
| 154 | + workspaceGm_[0].SetGlobalBuffer( | ||
| 155 | + (__gm__ CONVERT_TYPE*)(workSpace) + rowWorkspaceOffset_, | ||
| 156 | + Align(inputLastDimValue_, sortBufferSize) * sortBufferSize / sizeof(CONVERT_TYPE)); | ||
| 157 | + workspaceGm_[1].SetGlobalBuffer( | ||
| 158 | + (__gm__ CONVERT_TYPE*)(workSpace) + rowWorkspaceOffset_ + | ||
| 159 | + Align(inputLastDimValue_, sortBufferSize) * sortBufferSize / sizeof(CONVERT_TYPE)); | ||
| 160 | + | ||
| 161 | + uint32_t tailNum = inputLastDimValue_ - (frontCoreNum_ - 1) * numTileData_; | ||
| 162 | + uint32_t alignTile = (tailNum + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB * MORE_CORE_BLOCK_UB; | ||
| 163 | + pipe_->InitBuffer(inputQueue_, MORE_CORE_DOUBLE_BUFFER, alignTile * sizeof(T)); | ||
| 164 | + | ||
| 165 | + pipe_->InitBuffer(sortedValueUb_, alignTile * sortBufferSize); | ||
| 166 | + pipe_->InitBuffer(sortedValueIndexUb_, alignTile * sizeof(uint32_t)); | ||
| 167 | + pipe_->InitBuffer(concatTempBuf_, alignTile * sortBufferSize); | ||
| 168 | + pipe_->InitBuffer(sortTempBuf_, alignTile * sortBufferSize); | ||
| 169 | + pipe_->InitBuffer(inputValueTempBuf_, alignTile * sizeof(CONVERT_TYPE)); | ||
| 170 | + pipe_->InitBuffer(sortedValueLocalCastTbuf_, alignTile * sortBufferSize); | ||
| 171 | +} | ||
| 172 | + | ||
| 173 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 174 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::Process() | ||
| 175 | +{ | ||
| 176 | + int64_t offsetPerCore = 0; | ||
| 177 | + if (rowCoreIdx_ < frontCoreNum_ - 1) { | ||
| 178 | + offsetPerCore = numTileData_ * rowCoreIdx_; | ||
| 179 | + SortInSingleCore(numTileData_, offsetPerCore); | ||
| 180 | + } else if (rowCoreIdx_ == frontCoreNum_ - 1) { | ||
| 181 | + uint32_t tailNum = inputLastDimValue_ - numTileData_ * (frontCoreNum_ - 1); | ||
| 182 | + offsetPerCore = numTileData_ * rowCoreIdx_; | ||
| 183 | + SortInSingleCore(tailNum, offsetPerCore); | ||
| 184 | + } | ||
| 185 | + SyncAll(); | ||
| 186 | + pipe_->Reset(); | ||
| 187 | + uint32_t sortBufferSize = 8; | ||
| 188 | + pipe_->InitBuffer(sortedQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 189 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sortBufferSize); | ||
| 190 | + pipe_->InitBuffer(copyInQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 191 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sortBufferSize); | ||
| 192 | + pipe_->InitBuffer(castValueQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 193 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sizeof(CONVERT_TYPE)); | ||
| 194 | + pipe_->InitBuffer(castIndexQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 195 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sizeof(uint32_t)); | ||
| 196 | + if constexpr (std::is_same<bfloat16_t, T>::value) { | ||
| 197 | + pipe_->InitBuffer(outValueQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 198 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sizeof(T)); | ||
| 199 | + } | ||
| 200 | + if constexpr (std::is_same<int64_t, INDEX_TYPE>::value) { | ||
| 201 | + pipe_->InitBuffer(outIndexQueue_, MORE_CORE_DOUBLE_BUFFER, | ||
| 202 | + MORE_CORE_MERGE_SORT_LIST_MAX_NUM * onceMaxElements_ * sizeof(INDEX_TYPE)); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + listNum_ = frontCoreNum_; | ||
| 206 | + currentElements_ = numTileData_; | ||
| 207 | + currentTailElements_ = inputLastDimValue_ - numTileData_ * (frontCoreNum_ - 1); | ||
| 208 | + uint32_t currentCoreNum; | ||
| 209 | + uint32_t remainListNum; | ||
| 210 | + while(listNum_ > MORE_CORE_MERGE_SORT_LIST_MAX_NUM) { | ||
| 211 | + workspaceInput_ = workspaceGm_[workSpaceFlag_]; | ||
| 212 | + workspaceOutput_ = workspaceGm_[1 - workSpaceFlag_]; | ||
| 213 | + SortInMultiCore(); | ||
| 214 | + currentCoreNum = (listNum_ + MORE_CORE_MERGE_SORT_LIST_MAX_NUM - 1) / MORE_CORE_MERGE_SORT_LIST_MAX_NUM; | ||
| 215 | + remainListNum = listNum_ - (currentCoreNum - 1) * MORE_CORE_MERGE_SORT_LIST_MAX_NUM; | ||
| 216 | + currentTailElements_ = currentElements_ * (remainListNum - 1) + currentTailElements_; | ||
| 217 | + listNum_ = currentCoreNum; | ||
| 218 | + currentElements_ = currentElements_ * MORE_CORE_MERGE_SORT_LIST_MAX_NUM; | ||
| 219 | + workSpaceFlag_ = (workSpaceFlag_ + 1) % 2; | ||
| 220 | + } | ||
| 221 | + workspaceInput_ = workspaceGm_[workSpaceFlag_]; | ||
| 222 | + workspaceOutput_ = workspaceGm_[1 - workSpaceFlag_]; | ||
| 223 | + FinalSortAndCopy(); | ||
| 224 | +} | ||
| 225 | + | ||
| 226 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 227 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::SortInSingleCore( | ||
| 228 | + uint32_t tileNum, int64_t offsetPerCore) | ||
| 229 | +{ | ||
| 230 | + CopyInData(tileNum, offsetPerCore); | ||
| 231 | + LocalTensor<T> inputLocal = inputQueue_.DeQue<T>(); | ||
| 232 | + LocalTensor<CONVERT_TYPE> sortedValueLocal = sortedValueUb_.Get<CONVERT_TYPE>(); | ||
| 233 | + LocalTensor<uint32_t> sortedValueIndexLocal = sortedValueIndexUb_.Get<uint32_t>(); | ||
| 234 | + InitIndexLocal(tileNum, sortedValueIndexLocal, offsetPerCore); | ||
| 235 | + if constexpr (std::is_same<bfloat16_t, T>::value) { | ||
| 236 | + DoSortBf16(tileNum, inputLocal, sortedValueLocal, sortedValueIndexLocal); | ||
| 237 | + } else { | ||
| 238 | + DoSort(tileNum, inputLocal, sortedValueLocal, sortedValueIndexLocal); | ||
| 239 | + } | ||
| 240 | + CopyOutWorkSpace(tileNum, offsetPerCore, sortedValueLocal); | ||
| 241 | + inputQueue_.FreeTensor(inputLocal); | ||
| 242 | +} | ||
| 243 | + | ||
| 244 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 245 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::CopyInData(uint32_t tileNum, | ||
| 246 | + int64_t offsetPerCore) | ||
| 247 | +{ | ||
| 248 | + LocalTensor<T> inputLocal = inputQueue_.AllocTensor<T>(); | ||
| 249 | + T defaultValue = IS_DESCEND ? static_cast<T>(-INFINITY) : static_cast<T>(NAN); | ||
| 250 | + uint32_t alignTile = (tileNum + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB * MORE_CORE_BLOCK_UB; | ||
| 251 | + Duplicate(inputLocal, defaultValue, alignTile); | ||
| 252 | + | ||
| 253 | + event_t eventId = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::V_MTE2)); | ||
| 254 | + SetFlag<HardEvent::V_MTE2>(eventId); | ||
| 255 | + WaitFlag<HardEvent::V_MTE2>(eventId); | ||
| 256 | + | ||
| 257 | + uint32_t currTileSizeAlign = Align(tileNum, sizeof(T)); | ||
| 258 | + DataCopyExtParams copyParams; | ||
| 259 | + copyParams.blockCount = 1; | ||
| 260 | + copyParams.blockLen = tileNum * sizeof(T); | ||
| 261 | + copyParams.srcStride = 0; | ||
| 262 | + copyParams.dstStride = 0; | ||
| 263 | + DataCopyPadExtParams<T> padParams; | ||
| 264 | + padParams.isPad = true; | ||
| 265 | + padParams.rightPadding = currTileSizeAlign - tileNum; | ||
| 266 | + padParams.paddingValue = static_cast<T>(defaultValue); | ||
| 267 | + | ||
| 268 | + AscendC::DataCopyPad(inputLocal, inputValueGm_[rowDataOffset_ + offsetPerCore], copyParams, padParams); | ||
| 269 | + inputQueue_.EnQue(inputLocal); | ||
| 270 | +} | ||
| 271 | + | ||
| 272 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 273 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::InitIndexLocal(uint32_t tileNum, | ||
| 274 | + LocalTensor<uint32_t> sortedValueIndexLocal, int64_t offsetPerCore) | ||
| 275 | +{ | ||
| 276 | + PipeBarrier<PIPE_ALL>(); | ||
| 277 | + LocalTensor<int32_t> tempIndexLocal = sortedValueIndexLocal.ReinterpretCast<int32_t>(); | ||
| 278 | + ArithProgression<int32_t>(tempIndexLocal, offsetPerCore, 1, tileNum); | ||
| 279 | + PipeBarrier<PIPE_ALL>(); | ||
| 280 | +} | ||
| 281 | + | ||
| 282 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 283 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::DoSortBf16(uint32_t tileNum, | ||
| 284 | + LocalTensor<T> inputLocal, LocalTensor<CONVERT_TYPE> sortedValueLocal, LocalTensor<uint32_t> sortedValueIndexLocal) | ||
| 285 | +{ | ||
| 286 | + AscendC::LocalTensor<CONVERT_TYPE> sortTempLocal = sortTempBuf_.Get<CONVERT_TYPE>(); | ||
| 287 | + AscendC::LocalTensor<CONVERT_TYPE> concatTempLocal = concatTempBuf_.Get<CONVERT_TYPE>(); | ||
| 288 | + AscendC::LocalTensor<CONVERT_TYPE> inputValueTempLocal = inputValueTempBuf_.Get<CONVERT_TYPE>(); | ||
| 289 | + AscendC::LocalTensor<CONVERT_TYPE> sortedValueLocalCast = sortedValueLocalCastTbuf_.Get<CONVERT_TYPE>(); | ||
| 290 | + | ||
| 291 | + uint32_t aglinTileNum = ((tileNum + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB) * MORE_CORE_BLOCK_UB; | ||
| 292 | + uint32_t sortRepeatTimes = (aglinTileNum + MORE_CORE_DEALING_SORT_NUM_ONCE - 1) / MORE_CORE_DEALING_SORT_NUM_ONCE; | ||
| 293 | + uint32_t concatRepeatTimes = (aglinTileNum + MORE_CORE_DEALING_CONCAT_NUM_ONCE - 1) / MORE_CORE_DEALING_CONCAT_NUM_ONCE; | ||
| 294 | + | ||
| 295 | + AscendC::Cast(inputValueTempLocal, inputLocal, AscendC::RoundMode::CAST_NONE, aglinTileNum); | ||
| 296 | + if constexpr (!IS_DESCEND) { | ||
| 297 | + FlipSignBit(inputValueTempLocal, aglinTileNum); | ||
| 298 | + } | ||
| 299 | + AscendC::LocalTensor<CONVERT_TYPE> concatLocal; | ||
| 300 | + AscendC::Concat(concatLocal, inputValueTempLocal, concatTempLocal, concatRepeatTimes); | ||
| 301 | + AscendC::Sort<CONVERT_TYPE, true>(sortedValueLocal, concatLocal, sortedValueIndexLocal, sortTempLocal, sortRepeatTimes); | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 305 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::DoSort(uint32_t tileNum, | ||
| 306 | + LocalTensor<T> inputLocal, LocalTensor<CONVERT_TYPE> sortedValueLocal, LocalTensor<uint32_t> sortedValueIndexLocal) | ||
| 307 | +{ | ||
| 308 | + AscendC::LocalTensor<CONVERT_TYPE> sortTempLocal = sortTempBuf_.Get<CONVERT_TYPE>(); | ||
| 309 | + AscendC::LocalTensor<CONVERT_TYPE> concatTempLocal = concatTempBuf_.Get<CONVERT_TYPE>(); | ||
| 310 | + AscendC::LocalTensor<CONVERT_TYPE> sortedValueLocalCast = sortedValueLocalCastTbuf_.Get<CONVERT_TYPE>(); | ||
| 311 | + | ||
| 312 | + uint32_t aglinTileNum = ((tileNum + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB) * MORE_CORE_BLOCK_UB; | ||
| 313 | + uint32_t sortRepeatTimes = (aglinTileNum + MORE_CORE_DEALING_SORT_NUM_ONCE - 1) / MORE_CORE_DEALING_SORT_NUM_ONCE; | ||
| 314 | + uint32_t concatRepeatTimes = (aglinTileNum + MORE_CORE_DEALING_CONCAT_NUM_ONCE - 1) / MORE_CORE_DEALING_CONCAT_NUM_ONCE; | ||
| 315 | + | ||
| 316 | + if constexpr (!IS_DESCEND) { | ||
| 317 | + FlipSignBit(inputLocal, aglinTileNum); | ||
| 318 | + } | ||
| 319 | + AscendC::LocalTensor<CONVERT_TYPE> concatLocal; | ||
| 320 | + AscendC::Concat(concatLocal, inputLocal, concatTempLocal, concatRepeatTimes); | ||
| 321 | + AscendC::Sort<CONVERT_TYPE, true>(sortedValueLocal, concatLocal, sortedValueIndexLocal, sortTempLocal, sortRepeatTimes); | ||
| 322 | +} | ||
| 323 | + | ||
| 324 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 325 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::FlipSignBit( | ||
| 326 | + LocalTensor<CONVERT_TYPE> xLocal, uint32_t aglinTileNum) | ||
| 327 | +{ | ||
| 328 | + if constexpr (std::is_same<float, CONVERT_TYPE>::value) { | ||
| 329 | + AscendC::LocalTensor<int32_t> castTensor = xLocal.template ReinterpretCast<int32_t>(); | ||
| 330 | + AscendC::Adds(castTensor, castTensor, MORE_CORE_XOR_OP_VALUE_FP, aglinTileNum); | ||
| 331 | + } else if constexpr (std::is_same<half, CONVERT_TYPE>::value ){ | ||
| 332 | + AscendC::LocalTensor<int16_t> castTensor = xLocal.template ReinterpretCast<int16_t>(); | ||
| 333 | + AscendC::Adds(castTensor, castTensor, MORE_CORE_XOR_OP_VALUE_HALF, aglinTileNum); | ||
| 334 | + } | ||
| 335 | +} | ||
| 336 | + | ||
| 337 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 338 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::CopyOutWorkSpace( | ||
| 339 | + uint32_t tileNum, int64_t offsetPerCore, LocalTensor<CONVERT_TYPE> sortedValueLocal) | ||
| 340 | +{ | ||
| 341 | + event_t eventIdVToMTE3 = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::V_MTE3)); | ||
| 342 | + SetFlag<HardEvent::V_MTE3>(eventIdVToMTE3); | ||
| 343 | + WaitFlag<HardEvent::V_MTE3>(eventIdVToMTE3); | ||
| 344 | + | ||
| 345 | + DataCopyExtParams copyParams; | ||
| 346 | + copyParams.blockCount = 1; | ||
| 347 | + copyParams.blockLen = GetSortLen<CONVERT_TYPE>(tileNum) * sizeof(CONVERT_TYPE); | ||
| 348 | + copyParams.srcStride = 0; | ||
| 349 | + copyParams.dstStride = 0; | ||
| 350 | + DataCopyPad(workspaceGm_[0][GetSortLen<CONVERT_TYPE>(offsetPerCore)], sortedValueLocal, copyParams); | ||
| 351 | +} | ||
| 352 | + | ||
| 353 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 354 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::CopyOutMultiCore() | ||
| 355 | +{ | ||
| 356 | + LocalTensor<CONVERT_TYPE> sortTempBuffer = sortedQueue_.DeQue<CONVERT_TYPE>(); | ||
| 357 | + | ||
| 358 | + uint32_t len = curLoopSortedNum_; | ||
| 359 | + DataCopyExtParams copyParams; | ||
| 360 | + copyParams.blockCount = 1; | ||
| 361 | + copyParams.blockLen = GetSortLen<CONVERT_TYPE>(len) * sizeof(CONVERT_TYPE); | ||
| 362 | + copyParams.srcStride = 0; | ||
| 363 | + copyParams.dstStride = 0; | ||
| 364 | + DataCopyPad(workspaceOutput_[outOffset_], sortTempBuffer, copyParams); | ||
| 365 | + outOffset_ += GetSortLen<CONVERT_TYPE>(len); | ||
| 366 | + sortedQueue_.FreeTensor<CONVERT_TYPE>(sortTempBuffer); | ||
| 367 | +} | ||
| 368 | + | ||
| 369 | + | ||
| 370 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 371 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::SortInMultiCore() | ||
| 372 | +{ | ||
| 373 | + uint32_t needCoreNum = (listNum_ + MORE_CORE_MERGE_SORT_LIST_MAX_NUM - 1) / MORE_CORE_MERGE_SORT_LIST_MAX_NUM; | ||
| 374 | + if (rowCoreIdx_ < needCoreNum) { | ||
| 375 | + MultiCoreInit(); | ||
| 376 | + for (; allRemainElements_ > 0;) { | ||
| 377 | + CopyInMultiCore(); | ||
| 378 | + UpdateMrgParam(); | ||
| 379 | + DealingMergeSort(); | ||
| 380 | + UpdateSortInfo(); | ||
| 381 | + CopyOutMultiCore(); | ||
| 382 | + } | ||
| 383 | + ClearCache(); | ||
| 384 | + } | ||
| 385 | + SyncAll(); | ||
| 386 | +} | ||
| 387 | + | ||
| 388 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 389 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::CopyInMultiCore() | ||
| 390 | +{ | ||
| 391 | + LocalTensor<CONVERT_TYPE> ubMainInput = copyInQueue_.AllocTensor<CONVERT_TYPE>(); | ||
| 392 | + remainListNum_ = 0; | ||
| 393 | + for (int64_t i = 0, j = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 394 | + dealLengths_[i] = (onceMaxElements_ > listRemainElements_[i] ? listRemainElements_[i] : onceMaxElements_); | ||
| 395 | + if (dealLengths_[i] > 0) { | ||
| 396 | + DataCopyExtParams copyParams; | ||
| 397 | + copyParams.blockCount = 1; | ||
| 398 | + copyParams.blockLen = GetSortLen<CONVERT_TYPE>(dealLengths_[i]) * sizeof(CONVERT_TYPE); | ||
| 399 | + copyParams.srcStride = 0; | ||
| 400 | + copyParams.dstStride = 0; | ||
| 401 | + DataCopyPadExtParams<CONVERT_TYPE> padParams{false, 0, 0, 0}; | ||
| 402 | + DataCopyPad(ubMainInput[GetSortLen<CONVERT_TYPE>(onceMaxElements_) * i], workspaceInput_[offsets_[i]], copyParams, padParams); | ||
| 403 | + elementCountList_[j] = dealLengths_[i]; | ||
| 404 | + remainListNum_ += 1; | ||
| 405 | + j++; | ||
| 406 | + } | ||
| 407 | + } | ||
| 408 | + copyInQueue_.EnQue(ubMainInput); | ||
| 409 | +} | ||
| 410 | + | ||
| 411 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 412 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::DealingMergeSort() { | ||
| 413 | + LocalTensor<CONVERT_TYPE> sortTempBuffer = sortedQueue_.AllocTensor<CONVERT_TYPE>(); | ||
| 414 | + LocalTensor<CONVERT_TYPE> ubMainInput = copyInQueue_.DeQue<CONVERT_TYPE>(); | ||
| 415 | + LocalTensor<CONVERT_TYPE> tmpUbInputs[4]; | ||
| 416 | + for (int64_t i = 0, j = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 417 | + if (dealLengths_[i] > 0) { | ||
| 418 | + tmpUbInputs[j] = ubMainInput[GetSortLen<CONVERT_TYPE>(onceMaxElements_) * i]; | ||
| 419 | + j++; | ||
| 420 | + } | ||
| 421 | + } | ||
| 422 | + if (remainListNum_ == 2) { | ||
| 423 | + MrgSortSrcList sortListTail = MrgSortSrcList(tmpUbInputs[0], tmpUbInputs[1], tmpUbInputs[0], tmpUbInputs[0]); | ||
| 424 | + MrgSort<CONVERT_TYPE, true>(sortTempBuffer, sortListTail, elementCountList_, listSortedNums_, validBitTail_, 1); | ||
| 425 | + } else if (remainListNum_ == 3) { | ||
| 426 | + MrgSortSrcList sortListTail = | ||
| 427 | + MrgSortSrcList(tmpUbInputs[0], tmpUbInputs[1], tmpUbInputs[2], tmpUbInputs[0]); | ||
| 428 | + MrgSort<CONVERT_TYPE, true>(sortTempBuffer, sortListTail, elementCountList_, listSortedNums_, validBitTail_, 1); | ||
| 429 | + } else if (remainListNum_ == 4) { | ||
| 430 | + MrgSortSrcList sortListTail = MrgSortSrcList(tmpUbInputs[0], tmpUbInputs[1], tmpUbInputs[2], tmpUbInputs[3]); | ||
| 431 | + MrgSort<CONVERT_TYPE, true>(sortTempBuffer, sortListTail, elementCountList_, listSortedNums_, validBitTail_, 1); | ||
| 432 | + } else { | ||
| 433 | + AscendC::Copy(sortTempBuffer, tmpUbInputs[0], Align(GetSortLen<CONVERT_TYPE>(elementCountList_[0]), sizeof(CONVERT_TYPE))); | ||
| 434 | + listSortedNums_[0] = elementCountList_[0]; | ||
| 435 | + } | ||
| 436 | + sortedQueue_.EnQue(sortTempBuffer); | ||
| 437 | + copyInQueue_.FreeTensor(ubMainInput); | ||
| 438 | +} | ||
| 439 | + | ||
| 440 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 441 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::UpdateSortInfo() | ||
| 442 | +{ | ||
| 443 | + curLoopSortedNum_ = 0; | ||
| 444 | + for (int64_t i = 0, j = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 445 | + if (dealLengths_[i] > 0) { | ||
| 446 | + // update remain size | ||
| 447 | + listRemainElements_[i] -= listSortedNums_[j]; | ||
| 448 | + allRemainElements_ -= listSortedNums_[j]; | ||
| 449 | + // update offset | ||
| 450 | + offsets_[i] += GetSortOffset<CONVERT_TYPE>(listSortedNums_[j]); | ||
| 451 | + // update current loop sorted nums | ||
| 452 | + curLoopSortedNum_ += listSortedNums_[j]; | ||
| 453 | + j++; | ||
| 454 | + } | ||
| 455 | + } | ||
| 456 | +} | ||
| 457 | + | ||
| 458 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 459 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::MultiCoreInit() | ||
| 460 | +{ | ||
| 461 | + outOffset_ = GetSortLen<CONVERT_TYPE>(rowCoreIdx_ * MORE_CORE_MERGE_SORT_LIST_MAX_NUM * currentElements_); | ||
| 462 | + for (int64_t i = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 463 | + uint32_t blockNum = rowCoreIdx_ * MORE_CORE_MERGE_SORT_LIST_MAX_NUM + i; | ||
| 464 | + if (blockNum < listNum_ - 1) { | ||
| 465 | + listRemainElements_[i] = currentElements_; | ||
| 466 | + offsets_[i] = GetSortOffset<CONVERT_TYPE>(blockNum * currentElements_); | ||
| 467 | + allRemainElements_ += listRemainElements_[i]; | ||
| 468 | + } else if (blockNum == listNum_ - 1) { | ||
| 469 | + listRemainElements_[i] = currentTailElements_; | ||
| 470 | + offsets_[i] = GetSortOffset<CONVERT_TYPE>(blockNum * currentElements_); | ||
| 471 | + allRemainElements_ += currentTailElements_; | ||
| 472 | + } else { | ||
| 473 | + listRemainElements_[i] = 0; | ||
| 474 | + } | ||
| 475 | + } | ||
| 476 | +} | ||
| 477 | + | ||
| 478 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 479 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::UpdateMrgParam() | ||
| 480 | +{ | ||
| 481 | + if (remainListNum_ == 2) { | ||
| 482 | + elementCountList_[2] = 0; | ||
| 483 | + elementCountList_[3] = 0; | ||
| 484 | + validBitTail_ = 0b0011; | ||
| 485 | + } else if (remainListNum_ == 3) { | ||
| 486 | + elementCountList_[3] = 0; | ||
| 487 | + validBitTail_ = 0b0111; | ||
| 488 | + } else if (remainListNum_ == 4) { | ||
| 489 | + validBitTail_ = 0b1111; | ||
| 490 | + } else { | ||
| 491 | + elementCountList_[1] = 0; | ||
| 492 | + elementCountList_[2] = 0; | ||
| 493 | + elementCountList_[3] = 0; | ||
| 494 | + validBitTail_ = 0b0001; | ||
| 495 | + } | ||
| 496 | +} | ||
| 497 | + | ||
| 498 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 499 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::FinalSortAndCopy() | ||
| 500 | +{ | ||
| 501 | + if (rowCoreIdx_ == 0) { | ||
| 502 | + FinalSortInit(); | ||
| 503 | + for (; allRemainElements_ > 0 && outOffset_ < outputTopKValue_;) { | ||
| 504 | + CopyInMultiCore(); | ||
| 505 | + UpdateMrgParam(); | ||
| 506 | + DealingMergeSort(); | ||
| 507 | + UpdateSortInfo(); | ||
| 508 | + ExtractAndCopyOut(); | ||
| 509 | + } | ||
| 510 | + ClearCache(); | ||
| 511 | + } | ||
| 512 | + SyncAll(); | ||
| 513 | +} | ||
| 514 | + | ||
| 515 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 516 | +__aicore__ inline uint32_t TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::GetRemainingTopK() const | ||
| 517 | +{ | ||
| 518 | + if (outOffset_ >= static_cast<int64_t>(outputTopKValue_)) { | ||
| 519 | + return 0; | ||
| 520 | + } | ||
| 521 | + return static_cast<uint32_t>(static_cast<int64_t>(outputTopKValue_) - outOffset_); | ||
| 522 | +} | ||
| 523 | + | ||
| 524 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 525 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::ExtractAndCopyOut() | ||
| 526 | +{ | ||
| 527 | + uint32_t copyCount = curLoopSortedNum_; | ||
| 528 | + uint32_t remainingTopK = GetRemainingTopK(); | ||
| 529 | + if (remainingTopK == 0) { | ||
| 530 | + LocalTensor<CONVERT_TYPE> sortTempBufferDrop = sortedQueue_.DeQue<CONVERT_TYPE>(); | ||
| 531 | + sortedQueue_.FreeTensor(sortTempBufferDrop); | ||
| 532 | + return; | ||
| 533 | + } | ||
| 534 | + if (copyCount > remainingTopK) { | ||
| 535 | + copyCount = remainingTopK; | ||
| 536 | + } | ||
| 537 | + LocalTensor<T> ubOutput1; | ||
| 538 | + if constexpr (std::is_same<bfloat16_t, T>::value) { | ||
| 539 | + ubOutput1 = outValueQueue_.AllocTensor<T>(); | ||
| 540 | + } | ||
| 541 | + LocalTensor<INDEX_TYPE> ubOutput2; | ||
| 542 | + if constexpr (std::is_same<int64_t, INDEX_TYPE>::value) { | ||
| 543 | + ubOutput2 = outIndexQueue_.AllocTensor<INDEX_TYPE>(); | ||
| 544 | + } | ||
| 545 | + LocalTensor<CONVERT_TYPE> sortTempBuffer = sortedQueue_.DeQue<CONVERT_TYPE>(); | ||
| 546 | + LocalTensor<CONVERT_TYPE> castValue = castValueQueue_.AllocTensor<CONVERT_TYPE>(); | ||
| 547 | + LocalTensor<uint32_t> castIndex = castIndexQueue_.AllocTensor<uint32_t>(); | ||
| 548 | + AscendC::Extract(castValue, castIndex, sortTempBuffer, ((curLoopSortedNum_ + MORE_CORE_DEALING_EXTRACT_NUM_ONCE - 1) / MORE_CORE_DEALING_EXTRACT_NUM_ONCE)); | ||
| 549 | + if constexpr (!IS_DESCEND) { | ||
| 550 | + FlipSignBit(castValue, ((curLoopSortedNum_ + MORE_CORE_BLOCK_UB - 1) / MORE_CORE_BLOCK_UB * MORE_CORE_BLOCK_UB)); | ||
| 551 | + } | ||
| 552 | + DataCopyExtParams copyParamsValue; | ||
| 553 | + copyParamsValue.blockCount = 1; | ||
| 554 | + copyParamsValue.blockLen = copyCount * sizeof(T); | ||
| 555 | + copyParamsValue.srcStride = 0; | ||
| 556 | + copyParamsValue.dstStride = 0; | ||
| 557 | + | ||
| 558 | + DataCopyExtParams copyParamsIndex; | ||
| 559 | + copyParamsIndex.blockCount = 1; | ||
| 560 | + copyParamsIndex.blockLen = copyCount * sizeof(INDEX_TYPE); | ||
| 561 | + copyParamsIndex.srcStride = 0; | ||
| 562 | + copyParamsIndex.dstStride = 0; | ||
| 563 | + | ||
| 564 | + uint32_t sortedValueAlign = Align(curLoopSortedNum_, sizeof(CONVERT_TYPE)); | ||
| 565 | + if constexpr (std::is_same<bfloat16_t, T>::value) { | ||
| 566 | + AscendC::Cast(ubOutput1, castValue, AscendC::RoundMode::CAST_RINT, sortedValueAlign); | ||
| 567 | + outValueQueue_.EnQue(ubOutput1); | ||
| 568 | + ubOutput1 = outValueQueue_.DeQue<T>(); | ||
| 569 | + DataCopyPad(outValueGm_[rowOutputOffset_ + outOffset_], ubOutput1, copyParamsValue); | ||
| 570 | + outValueQueue_.FreeTensor(ubOutput1); | ||
| 571 | + } else { | ||
| 572 | + castValueQueue_.EnQue(castValue); | ||
| 573 | + castValue = castValueQueue_.DeQue<T>(); | ||
| 574 | + DataCopyPad(outValueGm_[rowOutputOffset_ + outOffset_], castValue, copyParamsValue); | ||
| 575 | + } | ||
| 576 | + castValueQueue_.FreeTensor(castValue); | ||
| 577 | + | ||
| 578 | + uint32_t sortedIndexAlign = Align(curLoopSortedNum_, sizeof(uint32_t)); | ||
| 579 | + LocalTensor<int32_t> castIndexTemp = castIndex.template ReinterpretCast<int32_t>(); | ||
| 580 | + if constexpr (std::is_same<int64_t, INDEX_TYPE>::value) { | ||
| 581 | + AscendC::Cast(ubOutput2, castIndexTemp, AscendC::RoundMode::CAST_NONE, sortedIndexAlign); | ||
| 582 | + outIndexQueue_.EnQue(ubOutput2); | ||
| 583 | + ubOutput2 = outIndexQueue_.DeQue<INDEX_TYPE>(); | ||
| 584 | + DataCopyPad(outIndexGm_[rowOutputOffset_ + outOffset_], ubOutput2, copyParamsIndex); | ||
| 585 | + outIndexQueue_.FreeTensor(ubOutput2); | ||
| 586 | + } else { | ||
| 587 | + castIndexQueue_.EnQue(castIndex); | ||
| 588 | + castIndex = castIndexQueue_.DeQue<uint32_t>(); | ||
| 589 | + castIndexTemp = castIndex.template ReinterpretCast<int32_t>(); | ||
| 590 | + DataCopyPad(outIndexGm_[rowOutputOffset_ + outOffset_], castIndexTemp, copyParamsIndex); | ||
| 591 | + } | ||
| 592 | + castIndexQueue_.FreeTensor(castIndex); | ||
| 593 | + sortedQueue_.FreeTensor(sortTempBuffer); | ||
| 594 | + outOffset_ += copyCount; | ||
| 595 | +} | ||
| 596 | + | ||
| 597 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 598 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::FinalSortInit() | ||
| 599 | +{ | ||
| 600 | + outOffset_ = 0; | ||
| 601 | + for (int64_t i = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 602 | + if (i < listNum_ - 1) { | ||
| 603 | + listRemainElements_[i] = currentElements_; | ||
| 604 | + offsets_[i] = GetSortOffset<CONVERT_TYPE>(i * currentElements_); | ||
| 605 | + allRemainElements_ += listRemainElements_[i]; | ||
| 606 | + } else if (i == listNum_ - 1) { | ||
| 607 | + listRemainElements_[i] = currentTailElements_; | ||
| 608 | + offsets_[i] = GetSortOffset<CONVERT_TYPE>(i * currentElements_); | ||
| 609 | + allRemainElements_ += currentTailElements_; | ||
| 610 | + } else { | ||
| 611 | + listRemainElements_[i] = 0; | ||
| 612 | + } | ||
| 613 | + } | ||
| 614 | +} | ||
| 615 | + | ||
| 616 | +template <typename T, typename CONVERT_TYPE, bool IS_DESCEND, typename INDEX_TYPE> | ||
| 617 | +__aicore__ inline void TopKMergeSortMoreCore<T, CONVERT_TYPE, IS_DESCEND, INDEX_TYPE>::ClearCache() | ||
| 618 | +{ | ||
| 619 | + allRemainElements_ = 0; | ||
| 620 | + outOffset_ = 0; | ||
| 621 | + remainListNum_ = 0; | ||
| 622 | + for (int64_t i = 0; i < MORE_CORE_MERGE_SORT_LIST_MAX_NUM; i++) { | ||
| 623 | + offsets_[i] = 0; | ||
| 624 | + listRemainElements_[i] = 0; | ||
| 625 | + elementCountList_[i] = 0; | ||
| 626 | + } | ||
| 627 | +} | ||
| 628 | +} // namespace topkV2 | ||
| 629 | + | ||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 24 | 26 | ||
| @@ -41,6 +43,8 @@ using namespace SortAndTopK; | |||
| 41 | 43 | ||
| 42 | 44 | ||
| 43 | 45 | ||
| 46 | + | ||
| 47 | + | ||
| 44 | 48 | ||
| 45 | const uint32_t SINGLE_CORE_MODE = 1; | 49 | const uint32_t SINGLE_CORE_MODE = 1; |
| 46 | const uint32_t MULT_CORE_OPTIM_MODE = 4; | 50 | const uint32_t MULT_CORE_OPTIM_MODE = 4; |
| @@ -280,6 +284,42 @@ __aicore__ inline void generateMergeTopKObject( | |||
| 280 | } | 284 | } |
| 281 | } | 285 | } |
| 282 | 286 | ||
| 287 | +template <typename T, typename CONVERT_TYPE, typename INDEX_DTYPE> | ||
| 288 | +__aicore__ inline void generateMergeTopKMoreCoreObject( | ||
| 289 | + GM_ADDR x, GM_ADDR values, GM_ADDR indices, GM_ADDR globalWorkGm, GM_ADDR tiling) | ||
| 290 | +{ | ||
| 291 | + GET_TILING_DATA(tilingData, tiling); | ||
| 292 | + bool isLargest = (tilingData.isLargest > 0) ? true : false; | ||
| 293 | + TPipe pipe; | ||
| 294 | + if (isLargest) { | ||
| 295 | + topkV2::TopKMergeSortMoreCore<T, CONVERT_TYPE, true, INDEX_DTYPE> mergeSort; | ||
| 296 | + mergeSort.Init(x, values, indices, globalWorkGm, &tilingData, &pipe); | ||
| 297 | + mergeSort.Process(); | ||
| 298 | + } else { | ||
| 299 | + topkV2::TopKMergeSortMoreCore<T, CONVERT_TYPE, false, INDEX_DTYPE> mergeSort; | ||
| 300 | + mergeSort.Init(x, values, indices, globalWorkGm, &tilingData, &pipe); | ||
| 301 | + mergeSort.Process(); | ||
| 302 | + } | ||
| 303 | +} | ||
| 304 | + | ||
| 305 | +template <typename T, typename CONVERT_TYPE, typename INDEX_DTYPE> | ||
| 306 | +__aicore__ inline void generateMergeTopKIntraCoreObject( | ||
| 307 | + GM_ADDR x, GM_ADDR values, GM_ADDR indices, GM_ADDR globalWorkGm, GM_ADDR tiling) | ||
| 308 | +{ | ||
| 309 | + GET_TILING_DATA(tilingData, tiling); | ||
| 310 | + bool isLargest = (tilingData.isLargest > 0) ? true : false; | ||
| 311 | + TPipe pipe; | ||
| 312 | + if (isLargest) { | ||
| 313 | + topkV2::TopKMergeSortIntraCore<T, INDEX_DTYPE, true> mergeSort; | ||
| 314 | + mergeSort.Init(x, values, indices, globalWorkGm, &tilingData, &pipe); | ||
| 315 | + mergeSort.Process(); | ||
| 316 | + } else { | ||
| 317 | + topkV2::TopKMergeSortIntraCore<T, INDEX_DTYPE, false> mergeSort; | ||
| 318 | + mergeSort.Init(x, values, indices, globalWorkGm, &tilingData, &pipe); | ||
| 319 | + mergeSort.Process(); | ||
| 320 | + } | ||
| 321 | +} | ||
| 322 | + | ||
| 283 | extern "C" __global__ __aicore__ void top_k_v2(GM_ADDR x, GM_ADDR k, GM_ADDR values, GM_ADDR indices, GM_ADDR workspace, GM_ADDR tiling) | 323 | extern "C" __global__ __aicore__ void top_k_v2(GM_ADDR x, GM_ADDR k, GM_ADDR values, GM_ADDR indices, GM_ADDR workspace, GM_ADDR tiling) |
| 284 | { | 324 | { |
| 285 | if (workspace == nullptr) { | 325 | if (workspace == nullptr) { |
| @@ -350,11 +390,17 @@ extern "C" __global__ __aicore__ void top_k_v2(GM_ADDR x, GM_ADDR k, GM_ADDR val | |||
| 350 | 390 | ||
| 351 | TILING_KEY_IS(TOPK_COMMON_TILING_KEY_FLOAT); | 391 | TILING_KEY_IS(TOPK_COMMON_TILING_KEY_FLOAT); |
| 352 | TILING_KEY_IS(TOPK_MERGE_SORT_TILING_KEY_FLOAT); | 392 | TILING_KEY_IS(TOPK_MERGE_SORT_TILING_KEY_FLOAT); |
| 393 | + TILING_KEY_IS(TOPK_MERGE_SORT_MORE_CORE_TILING_KEY_FLOAT); | ||
| 394 | + TILING_KEY_IS(TOPK_MERGE_SORT_INTRA_CORE_TILING_KEY_FLOAT); | ||
| 353 | 395 | ||
| 354 | 396 | ||
| 355 | generateOpObject<float, uint32_t, topkV2::B32_BITE_SIZE, DTYPE_INDICES>(x, k, values, indices, globalWorkGm, tiling); | 397 | generateOpObject<float, uint32_t, topkV2::B32_BITE_SIZE, DTYPE_INDICES>(x, k, values, indices, globalWorkGm, tiling); |
| 356 | 398 | ||
| 357 | generateMergeTopKObject<float, float, DTYPE_INDICES>(x, values, indices, globalWorkGm, tiling); | 399 | generateMergeTopKObject<float, float, DTYPE_INDICES>(x, values, indices, globalWorkGm, tiling); |
| 400 | + | ||
| 401 | + generateMergeTopKMoreCoreObject<float, float, DTYPE_INDICES>(x, values, indices, globalWorkGm, tiling); | ||
| 402 | + | ||
| 403 | + generateMergeTopKIntraCoreObject<float, float, DTYPE_INDICES>(x, values, indices, globalWorkGm, tiling); | ||
| 358 | 404 | ||
| 359 | 405 | ||
| 360 | 406 | ||
| @@ -380,4 +426,4 @@ extern "C" __global__ __aicore__ void top_k_v2(GM_ADDR x, GM_ADDR k, GM_ADDR val | |||
| 380 | 426 | ||
| 381 | 427 | ||
| 382 | } | 428 | } |
| 383 | -#endif // TOP_K_V2_APT_H | 429 | +#endif // TOP_K_V2_APT_H |
| @@ -52,7 +52,7 @@ TEST_F(TopKV2Tiling, test_tiling_small_merge_sort) { | |||
| 52 | }, | 52 | }, |
| 53 | &compileInfo); | 53 | &compileInfo); |
| 54 | uint64_t expectTilingKey = 13003; | 54 | uint64_t expectTilingKey = 13003; |
| 55 | - string expectTilingData = "4294967297 42949672961 4294967306 274877906976 0 4294967297 0 0 1 32 8 1 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "; | 55 | + string expectTilingData = "4294967297 42949672961 4294967306 274877906976 0 4294967297 0 0 1 32 8 1 8 1 0 0 0 0 0 0 0 0 0 0 8589934592 0 0 0 "; |
| 56 | std::vector<size_t> expectWorkspaces = {16787584}; | 56 | std::vector<size_t> expectWorkspaces = {16787584}; |
| 57 | ExecuteTestCase( | 57 | ExecuteTestCase( |
| 58 | tilingContextPara, ge::GRAPH_SUCCESS, expectTilingKey, expectTilingData, expectWorkspaces); | 58 | tilingContextPara, ge::GRAPH_SUCCESS, expectTilingKey, expectTilingData, expectWorkspaces); |
这些为何不用GE的接口获取字节大小