* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "kernel_operator.h"
#include "mixkernels/toppsample/tiling/tiling_data.h"
#include "mixkernels/utils/common/kernel/kernel_utils.h"
namespace {
static constexpr int32_t BUFFER_NUM = 1;
static constexpr uint32_t DATA_BYTE = 2;
static constexpr uint32_t MAX_CORE_NUM = 512;
static constexpr uint32_t BLK_SIZE = 32;
static constexpr uint32_t DEFAULT_STRIDE = 8;
static constexpr uint32_t FP32_PER_REPEAT = 64;
static constexpr uint32_t FP16_PER_BLOCK = 16;
static constexpr uint32_t NUM_4 = 4;
using AscendC::HardEvent;
template <bool MULTI, typename T> class KernelToppsample {
public:
__aicore__ inline KernelToppsample() {}
__aicore__ inline void Init(GM_ADDR cumsumed_probs, GM_ADDR topp, GM_ADDR select_index, GM_ADDR select_range,
AtbOps::ToppsampleTilingData &tiling_data)
{
realLastDim_ = tiling_data.realLastDim;
firstDim_ = tiling_data.firstDim;
expandLastDim_ = tiling_data.expandLastDim;
tilingUb_ = tiling_data.randValList;
numSamplesMax_ = tiling_data.numSamplesMax;
perCoreRunNum_ = tiling_data.perCoreRunNum;
nlElePerCorePerRun_ = tiling_data.nlElePerCorePerRun;
lElePerCoreLastRun_ = tiling_data.lElePerCoreLastRun;
tempUbEleAligened_ = tiling_data.tempUbEleAligened;
realCore_ = AscendC::GetBlockNum();
blockIdx_ = AscendC::GetBlockIdx();
nlCoreRun_ = (firstDim_ + realCore_ - 1) / realCore_;
lCoreRun_ = firstDim_ - (realCore_ - 1) * nlCoreRun_;
dynamicRound_ = (blockIdx_ == realCore_ - 1) ? lCoreRun_ : nlCoreRun_;
maxBatch_ = (firstDim_ + FP16_PER_BLOCK - 1) / FP16_PER_BLOCK * FP16_PER_BLOCK;
xGm_.SetGlobalBuffer((__gm__ T *)cumsumed_probs);
yGm_.SetGlobalBuffer((__gm__ T *)topp);
zGm_.SetGlobalBuffer((__gm__ int32_t *)select_index);
selectRangeGm_.SetGlobalBuffer((__gm__ int32_t *)select_range);
pipe_.InitBuffer(inputBuf_, tempUbEleAligened_ * DATA_BYTE);
pipe_.InitBuffer(tempBuf_, tempUbEleAligened_ * DATA_BYTE * DATA_BYTE);
pipe_.InitBuffer(fp32Buf_, tempUbEleAligened_ * DATA_BYTE * DATA_BYTE);
pipe_.InitBuffer(yBuf_, maxBatch_ * DATA_BYTE);
pipe_.InitBuffer(yF32Buf_, maxBatch_ * DATA_BYTE * DATA_BYTE);
pipe_.InitBuffer(int8Buf_, tempUbEleAligened_ / DEFAULT_STRIDE);
pipe_.InitBuffer(blockBuf_, BLK_SIZE);
pipe_.InitBuffer(int32Buf_, MAX_CORE_NUM * DATA_BYTE * DATA_BYTE);
pipe_.InitBuffer(vecIn_, 1, NUM_4 * MAX_CORE_NUM * sizeof(int32_t));
pipe_.InitBuffer(selectRangeBlkBuf_, MAX_CORE_NUM * DATA_BYTE * DATA_BYTE);
}
__aicore__ inline void PickUpRand()
{
AscendC::LocalTensor<T> buf = yBuf_.Get<T>();
DataCopy(buf, yGm_, maxBatch_);
}
__aicore__ inline void FirstPick(uint32_t cid, uint32_t offset)
{
AscendC::LocalTensor<T> buf = inputBuf_.Get<T>();
AscendC::LocalTensor<float> fp32Buf = fp32Buf_.Get<float>();
flag_ = 0;
tempRandVal_ = removeVal_ * (*(tilingUb_ + offset));
for (int j = 0; j < perCoreRunNum_; j++) {
uint32_t RunNum = (j == perCoreRunNum_ - 1) ? lElePerCoreLastRun_ : nlElePerCorePerRun_;
uint64_t offsetXgm = (uint64_t)blockIdx_ * nlCoreRun_ * realLastDim_ + (uint64_t)cid * realLastDim_ +
(uint64_t)j * tempUbEleAligened_;
uint32_t RunNumF16Align = (RunNum + FP16_PER_BLOCK - 1) / FP16_PER_BLOCK * FP16_PER_BLOCK;
AscendC::PipeBarrier<PIPE_MTE2>();
DataCopy(buf, xGm_[offsetXgm], RunNumF16Align);
AscendC::PipeBarrier<PIPE_MTE2>();
AscendC::SetFlag<HardEvent::MTE2_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE2_V>(EVENT_ID0);
Cast(fp32Buf, buf, AscendC::RoundMode::CAST_NONE, RunNumF16Align);
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
if (fp32Buf.GetValue(RunNum - 1) < tempRandVal_) {
continue;
} else if (flag_ == 0) {
flag_ = 1;
idxReturn_ = j;
}
if (fp32Buf.GetValue(RunNum - 1) < removeVal_) {
continue;
} else {
idxForward_ = j;
AscendC::SetFlag<HardEvent::MTE2_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE2_V>(EVENT_ID0);
break;
}
}
}
__aicore__ inline void Process(__gm__ uint8_t *sync)
{
AscendC::LocalTensor<T> buf = inputBuf_.Get<T>();
AscendC::LocalTensor<float> fp32Buf = fp32Buf_.Get<float>();
AscendC::LocalTensor<T> toppBuf_ = yBuf_.Get<T>();
AscendC::LocalTensor<float> toppBufF32_ = yF32Buf_.Get<float>();
AscendC::LocalTensor<int32_t> int32BlkBuf = int32Buf_.Get<int32_t>();
AscendC::LocalTensor<int32_t> selectRangeBlkBuf = selectRangeBlkBuf_.Get<int32_t>();
PickUpRand();
AscendC::SetFlag<HardEvent::MTE2_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE2_V>(EVENT_ID0);
Duplicate(int32BlkBuf, (int32_t)0, MAX_CORE_NUM);
Duplicate(selectRangeBlkBuf, (int32_t)0, MAX_CORE_NUM);
AscendC::LocalTensor<uint32_t> uint32Buf_ = int8Buf_.Get<uint32_t>();
Duplicate(uint32Buf_, uint32_t(0), tempUbEleAligened_ / BLK_SIZE);
Cast(toppBufF32_, toppBuf_, AscendC::RoundMode::CAST_NONE, maxBatch_);
for (int cid = 0; cid < dynamicRound_; cid++) {
absIdx_ = 0;
uint32_t batchOffset = (blockIdx_ * nlCoreRun_ + cid) % MAX_CORE_NUM;
if constexpr (MULTI) {
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
removeVal_ = toppBufF32_.GetValue((blockIdx_ * nlCoreRun_ + cid));
} else {
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
removeVal_ = toppBufF32_.GetValue(0);
}
tempRandVal_ = removeVal_ * (*(tilingUb_ + batchOffset));
FirstPick(cid, batchOffset);
uint32_t RunNum = (idxForward_ == perCoreRunNum_ - 1) ? lElePerCoreLastRun_ : nlElePerCorePerRun_;
Compute(RunNum, removeVal_, cid, 0);
Cast(fp32Buf, buf, AscendC::RoundMode::CAST_NONE, RunNum);
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
float finalVal = FigureOutValue(cid);
float cutOff = finalVal * (*(tilingUb_ + batchOffset));
finalPick(cutOff, cid);
}
AscendC::SetFlag<HardEvent::S_MTE3>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::S_MTE3>(EVENT_ID0);
CoreSyncOut(sync);
}
private:
__aicore__ inline void CopyIn(uint32_t coreIdx, uint32_t loopIdx, uint32_t copyEleNum)
{
AscendC::LocalTensor<T> buf = inputBuf_.Get<T>();
uint32_t copyEleNumAligned_ = (copyEleNum + FP16_PER_BLOCK - 1) / FP16_PER_BLOCK * FP16_PER_BLOCK;
uint64_t xGmOffsetSec = (uint64_t)blockIdx_ * nlCoreRun_ * realLastDim_ + (uint64_t)coreIdx * realLastDim_ +
(uint64_t)loopIdx * tempUbEleAligened_;
DataCopy(buf, xGm_[xGmOffsetSec], copyEleNumAligned_);
AscendC::SetFlag<HardEvent::MTE2_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE2_S>(EVENT_ID0);
}
__aicore__ inline void Compute(uint32_t copyEleNum, float compareVal, uint32_t cid, uint32_t flag)
{
AscendC::LocalTensor<T> buf = inputBuf_.Get<T>();
AscendC::LocalTensor<half> tempBuf = tempBuf_.Get<half>();
AscendC::LocalTensor<uint8_t> uint8Buf = int8Buf_.Get<uint8_t>();
AscendC::LocalTensor<float> blkBuf = blockBuf_.Get<float>();
AscendC::LocalTensor<float> fp32Buf = fp32Buf_.Get<float>();
AscendC::LocalTensor<half> fp16Buf = fp32Buf_.Get<half>();
AscendC::LocalTensor<float> fp32TempBuf = tempBuf_.Get<float>();
uint32_t copyEleNumAlignF16_ = (copyEleNum + FP16_PER_BLOCK - 1) / FP16_PER_BLOCK * FP16_PER_BLOCK;
uint32_t copyEleNumAlignF32_ = (copyEleNum + FP32_PER_REPEAT - 1) / FP32_PER_REPEAT * FP32_PER_REPEAT;
for (uint32_t dupVal = copyEleNum; dupVal < copyEleNumAlignF16_; dupVal++) {
buf.SetValue(dupVal, T(1));
}
AscendC::SetFlag<HardEvent::S_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::S_V>(EVENT_ID0);
Cast(fp32TempBuf, buf, AscendC::RoundMode::CAST_NONE, copyEleNumAlignF16_);
AscendC::PipeBarrier<PIPE_V>();
Duplicate(fp32Buf, compareVal, tempUbEleAligened_);
AscendC::PipeBarrier<PIPE_V>();
if (flag == 0) {
Compare(uint8Buf, fp32TempBuf, fp32Buf, AscendC::CMPMODE::LT, copyEleNumAlignF32_);
} else {
Compare(uint8Buf, fp32TempBuf, fp32Buf, AscendC::CMPMODE::LE,
copyEleNumAlignF32_);
}
AscendC::PipeBarrier<PIPE_V>();
Duplicate(fp16Buf, (half)1, tempUbEleAligened_);
AscendC::PipeBarrier<PIPE_V>();
Select(tempBuf, uint8Buf, fp16Buf, (half)0, AscendC::SELMODE::VSEL_TENSOR_SCALAR_MODE,
copyEleNumAlignF16_);
AscendC::PipeBarrier<PIPE_V>();
Cast(fp32Buf, tempBuf, AscendC::RoundMode::CAST_NONE, copyEleNum);
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
for (uint32_t dupVal = copyEleNum; dupVal < copyEleNumAlignF32_; dupVal++) {
fp32Buf.SetValue(dupVal, (float)0);
}
AscendC::SetFlag<HardEvent::S_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::S_V>(EVENT_ID0);
ReduceSum(blkBuf, fp32Buf, fp32TempBuf, copyEleNumAlignF32_);
AscendC::PipeBarrier<PIPE_V>();
}
__aicore__ inline float FigureOutValue(uint32_t cid)
{
AscendC::LocalTensor<float> blkBuf = blockBuf_.Get<float>();
AscendC::LocalTensor<float> fp32Buf = fp32Buf_.Get<float>();
AscendC::LocalTensor<int32_t> selectRangeBlkBuf = selectRangeBlkBuf_.Get<int32_t>();
float sec2Last = blkBuf.GetValue(0);
auto relativeSelectRange = static_cast<int32_t>(sec2Last);
lastVal_ = relativeSelectRange - 1;
relativeSelectRange += idxForward_ * tempUbEleAligened_;
selectRangeBlkBuf.SetValue(cid, relativeSelectRange);
if (lastVal_ < 0) {
return fp32Buf.GetValue(0);
}
return fp32Buf.GetValue((uint32_t)lastVal_);
}
__aicore__ inline void finalPick(float cutOff, uint32_t cid)
{
AscendC::LocalTensor<float> blkBuf = blockBuf_.Get<float>();
AscendC::LocalTensor<int32_t> int32BlkBuf = int32Buf_.Get<int32_t>();
for (int j = idxReturn_; j >= 0; j--) {
uint32_t RunNum = (j == perCoreRunNum_ - 1) ? lElePerCoreLastRun_ : nlElePerCorePerRun_;
CopyIn(cid, j, RunNum);
AscendC::SetFlag<HardEvent::MTE2_V>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE2_V>(EVENT_ID0);
Compute(RunNum, cutOff, cid, 1);
AscendC::SetFlag<HardEvent::V_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::V_S>(EVENT_ID0);
lastValTemp = blkBuf.GetValue(0);
if (lastValTemp > (float)0.0) {
absIdx_ = j;
break;
}
}
lastVal_ = (int32_t)lastValTemp + (int32_t)absIdx_ * (int32_t)tempUbEleAligened_;
if (lastVal_ > 0) {
int32BlkBuf.SetValue(cid, lastVal_);
}
}
__aicore__ inline void CopyOut()
{
AscendC::LocalTensor<int32_t> int32BlkBuf = int32Buf_.Get<int32_t>();
AscendC::LocalTensor<int32_t> selectRangeBlkBuf = selectRangeBlkBuf_.Get<int32_t>();
uint32_t dynamicRoundAlign_ = DEFAULT_STRIDE * ((dynamicRound_ + DEFAULT_STRIDE - 1) / DEFAULT_STRIDE);
uint32_t zSpace = (firstDim_ * sizeof(int32_t) + BLK_SIZE - 1) / BLK_SIZE * BLK_SIZE;
if (blockIdx_ != realCore_ - 1 && (blockIdx_ * nlCoreRun_ + dynamicRoundAlign_) * sizeof(int32_t) <= zSpace) {
DataCopy(zGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_], int32BlkBuf, dynamicRoundAlign_);
DataCopy(selectRangeGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_], selectRangeBlkBuf,
dynamicRoundAlign_);
}
else {
uint32_t dynamicRoundFloor_ = dynamicRound_ / DEFAULT_STRIDE * DEFAULT_STRIDE;
if (dynamicRoundFloor_ > 0) {
DataCopy(zGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_], int32BlkBuf, dynamicRound_);
DataCopy(selectRangeGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_], selectRangeBlkBuf,
dynamicRound_);
}
AscendC::SetFlag<HardEvent::MTE3_S>(EVENT_ID0);
AscendC::WaitFlag<HardEvent::MTE3_S>(EVENT_ID0);
for (int i = dynamicRoundFloor_; i < dynamicRound_; i++) {
zGm_(static_cast<uint64_t>(blockIdx_) * nlCoreRun_ + i) = int32BlkBuf.GetValue(i);
selectRangeGm_(static_cast<uint64_t>(blockIdx_) * nlCoreRun_ + i) = selectRangeBlkBuf.GetValue(i);
}
AscendC::DataCacheCleanAndInvalid<int32_t, AscendC::CacheLine::SINGLE_CACHE_LINE>(zGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_]);
AscendC::DataCacheCleanAndInvalid<int32_t, AscendC::CacheLine::SINGLE_CACHE_LINE>(selectRangeGm_[static_cast<uint64_t>(blockIdx_) * nlCoreRun_]);
}
}
__aicore__ inline void CoreSyncOut(__gm__ uint8_t *sync)
{
syncGm_.SetGlobalBuffer((__gm__ int32_t *)(sync), BLK_SIZE * MAX_CORE_NUM * firstDim_);
if (realCore_ != 1) {
if (blockIdx_ == realCore_ - 1) {
auto syncBuf = vecIn_.AllocTensor<int32_t>();
AscendC::IBWait(syncGm_, syncBuf, realCore_ - 2, 0);
CopyOut();
vecIn_.FreeTensor(syncBuf);
} else if (blockIdx_ == 0) {
auto syncBuf = vecIn_.AllocTensor<int32_t>();
CopyOut();
AscendC::IBSet(syncGm_, syncBuf, 0, 0);
vecIn_.FreeTensor(syncBuf);
} else {
auto syncBuf = vecIn_.AllocTensor<int32_t>();
AscendC::IBWait(syncGm_, syncBuf, blockIdx_ - 1, 0);
CopyOut();
AscendC::IBSet(syncGm_, syncBuf, blockIdx_, 0);
vecIn_.FreeTensor(syncBuf);
}
} else {
CopyOut();
}
}
private:
AscendC::TPipe pipe_;
AscendC::TQue<AscendC::QuePosition::VECIN, BUFFER_NUM> vecIn_;
AscendC::TBuf<AscendC::TPosition::VECCALC> inputBuf_, yF32Buf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> tempBuf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> fp32Buf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> int8Buf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> blockBuf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> yBuf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> int32Buf_;
AscendC::TBuf<AscendC::TPosition::VECCALC> selectRangeBlkBuf_;
AscendC::GlobalTensor<T> xGm_;
AscendC::GlobalTensor<T> yGm_;
AscendC::GlobalTensor<int32_t> syncGm_;
AscendC::GlobalTensor<int32_t> zGm_;
AscendC::GlobalTensor<int32_t> selectRangeGm_;
uint32_t realLastDim_{0};
uint32_t expandLastDim_{0};
uint32_t numSamplesMax_{0};
uint32_t firstDim_{0};
uint32_t maxBatch_{0};
float maxNum_{0};
float tempValue_{0};
uint32_t perCoreRunNum_{0};
uint32_t nlElePerCorePerRun_{0};
uint32_t lElePerCoreLastRun_{0};
uint32_t tempUbEleAligened_{19456};
uint32_t realLastDimTemp_{0};
float *tilingUb_{nullptr};
int32_t *resOut_{nullptr};
float removeVal_{0};
float tempRandVal_{0};
uint32_t idxReturn_{0};
uint32_t idxForward_{0};
uint32_t loopReturn_{0};
uint32_t flag_{0};
int32_t lastVal_{0};
uint32_t absIdx_{0};
uint32_t nlCoreRun_{1};
uint32_t lCoreRun_{1};
uint32_t dynamicRound_{1};
uint32_t realCore_{1};
uint32_t blockIdx_{0};
uint32_t realLastDimAlignF32_{64};
uint32_t realLastDimAlignF16_{128};
float lastValTemp;
};
}
inline __aicore__ void InitTilingData(const __gm__ uint8_t *p_tilingdata, AtbOps::ToppsampleTilingData *tilingdata)
{
#if defined(__CCE_KT_TEST__) || (defined(__CCE_AICORE__) && __CCE_AICORE__ == 220)
tilingdata->realLastDim = (*(const __gm__ uint32_t *)(p_tilingdata + 0));
tilingdata->expandLastDim = (*(const __gm__ uint32_t *)(p_tilingdata + 4));
tilingdata->firstDim = (*(const __gm__ uint32_t *)(p_tilingdata + 8));
tilingdata->numSamplesMax = (*(const __gm__ uint32_t *)(p_tilingdata + 12));
tilingdata->perCoreRunNum = (*(const __gm__ int32_t *)(p_tilingdata + 16));
tilingdata->nlElePerCorePerRun = (*(const __gm__ uint32_t *)(p_tilingdata + 20));
tilingdata->lElePerCoreLastRun = (*(const __gm__ uint32_t *)(p_tilingdata + 24));
tilingdata->tempUbEleAligened = (*(const __gm__ uint32_t *)(p_tilingdata + 28));
for (uint32_t i = 0; i < tilingdata->numSamplesMax; i++) {
tilingdata->randValList[i] = (*(const __gm__ float *)(p_tilingdata + 32 + i * sizeof(float)));
}
#else
AscendC::TPipe pipe_;
__ubuf__ uint8_t *tilingdata_in_ub = nullptr;
CopyGmTilingToUb(tilingdata_in_ub, p_tilingdata, sizeof(AtbOps::ToppsampleTilingData), &pipe_);
AscendC::PipeBarrier<PIPE_ALL>();
tilingdata->realLastDim = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 0));
tilingdata->expandLastDim = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 4));
tilingdata->firstDim = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 8));
tilingdata->numSamplesMax = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 12));
tilingdata->perCoreRunNum = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 16));
tilingdata->nlElePerCorePerRun = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 20));
tilingdata->lElePerCoreLastRun = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 24));
tilingdata->tempUbEleAligened = (*(__ubuf__ uint32_t *)(tilingdata_in_ub + 28));
for (uint32_t i = 0; i < tilingdata->numSamplesMax; i++) {
tilingdata->randValList[i] = (*(__ubuf__ float *)(tilingdata_in_ub + 32 + i * sizeof(float)));
}
AscendC::PipeBarrier<PIPE_ALL>();
#endif
}
extern "C" __global__ __aicore__ void toppsample(GM_ADDR cumsumed_probs, GM_ADDR topp, GM_ADDR select_index,
GM_ADDR select_range, GM_ADDR workspace, GM_ADDR tiling)
{
AtbOps::ToppsampleTilingData tiling_data;
InitTilingData((tiling), &(tiling_data));
if (TILING_KEY_IS(1)) {
KernelToppsample<false, half> op;
op.Init(cumsumed_probs, topp, select_index, select_range, tiling_data);
op.Process(workspace);
} else if (TILING_KEY_IS(0)) {
KernelToppsample<true, half> op;
op.Init(cumsumed_probs, topp, select_index, select_range, tiling_data);
op.Process(workspace);
}
#if defined(__CCE_KT_TEST__) || (defined(__CCE_AICORE__) && __CCE_AICORE__ == 220)
if (TILING_KEY_IS(3)) {
KernelToppsample<false, bfloat16_t> op;
op.Init(cumsumed_probs, topp, select_index, select_range, tiling_data);
op.Process(workspace);
} else if (TILING_KEY_IS(2)) {
KernelToppsample<true, bfloat16_t> op;
op.Init(cumsumed_probs, topp, select_index, select_range, tiling_data);
op.Process(workspace);
}
#endif
}