Files
2026-07-13 13:33:03 +08:00

171 lines
4.9 KiB
Common Lisp

#ifdef MNN_SUPPORT_FP16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif
#define GLOBAL_SIZE_3_DIMS \
__private const int global_size_dim0, __private const int global_size_dim1, __private const int global_size_dim2,
#define DEAL_NON_UNIFORM_DIM3(input1, input2, input3) \
if (input1 >= global_size_dim0 || input2 >= global_size_dim1 || input3 >= global_size_dim2) { \
return; \
}
#define THREAD_NUMBER 128
#define LOCAL_K 8
#define CANDIDATE_NUMBER (THREAD_NUMBER * LOCAL_K)
#ifdef IS_INT
typedef int DTYPE;
#else
typedef FLOAT DTYPE;
#endif
inline bool afterAsc(DTYPE aValue, int aIndex, DTYPE bValue, int bIndex) {
if (aValue > bValue) {
return true;
}
if (aValue < bValue) {
return false;
}
return aIndex > bIndex;
}
inline bool better(DTYPE aValue, int aIndex, DTYPE bValue, int bIndex) {
if (bIndex < 0) {
return true;
}
if (aIndex < 0) {
return false;
}
#ifdef SORT_DESC
if (aValue > bValue) {
return true;
}
if (aValue < bValue) {
return false;
}
#else
if (aValue < bValue) {
return true;
}
if (aValue > bValue) {
return false;
}
#endif
return aIndex < bIndex;
}
__kernel void topkv2_buf(GLOBAL_SIZE_3_DIMS
__global DTYPE *outValue,
__global int *outIndex,
__global const DTYPE *inValue,
__private const int rowSize,
__private const int k,
__private const int numRows) {
const int gid0 = get_global_id(0);
const int gid1 = get_global_id(1);
const int gid2 = get_global_id(2);
DEAL_NON_UNIFORM_DIM3(gid0, gid1, gid2);
const int tid = get_local_id(0);
const int row = get_group_id(1);
if (tid >= THREAD_NUMBER || row >= numRows) {
return;
}
#ifdef IS_INT
const DTYPE initWorst = (DTYPE)(2147483647);
const DTYPE initBestWorst = (DTYPE)(-2147483648);
#else
const DTYPE initWorst = (DTYPE)(FLT_MAX);
const DTYPE initBestWorst = (DTYPE)(-FLT_MAX);
#endif
DTYPE localValue[LOCAL_K];
int localIndex[LOCAL_K];
#ifdef SORT_DESC
for (uint i = 0; i < LOCAL_K; ++i) {
localValue[i] = initBestWorst;
localIndex[i] = -1;
}
#else
for (uint i = 0; i < LOCAL_K; ++i) {
localValue[i] = initWorst;
localIndex[i] = -1;
}
#endif
const __global DTYPE *rowIn = inValue + row * rowSize;
for (int i = tid; i < rowSize; i += THREAD_NUMBER) {
const DTYPE value = rowIn[i];
if (!better(value, i, localValue[LOCAL_K - 1], localIndex[LOCAL_K - 1])) {
continue;
}
uint insertPos = LOCAL_K;
for (uint j = 0; j < LOCAL_K; ++j) {
if (better(value, i, localValue[j], localIndex[j])) {
insertPos = j;
break;
}
}
if (insertPos >= LOCAL_K) {
continue;
}
for (uint j = LOCAL_K - 1; j > insertPos; --j) {
localValue[j] = localValue[j - 1];
localIndex[j] = localIndex[j - 1];
}
localValue[insertPos] = value;
localIndex[insertPos] = i;
}
__local DTYPE sharedValue[CANDIDATE_NUMBER];
__local int sharedIndex[CANDIDATE_NUMBER];
const uint base = tid * LOCAL_K;
for (uint i = 0; i < LOCAL_K; ++i) {
sharedValue[base + i] = localValue[i];
sharedIndex[base + i] = localIndex[i];
}
barrier(CLK_LOCAL_MEM_FENCE);
for (uint size = 2; size <= CANDIDATE_NUMBER; size <<= 1) {
for (uint stride = size >> 1; stride > 0; stride >>= 1) {
for (uint idx = tid; idx < CANDIDATE_NUMBER; idx += THREAD_NUMBER) {
const uint ixj = idx ^ stride;
if (ixj <= idx) {
continue;
}
bool up = ((idx & size) == 0);
#ifdef SORT_DESC
up = !up;
#endif
const bool after = afterAsc(sharedValue[idx], sharedIndex[idx], sharedValue[ixj], sharedIndex[ixj]);
if (up == after) {
const DTYPE tValue = sharedValue[idx];
sharedValue[idx] = sharedValue[ixj];
sharedValue[ixj] = tValue;
const int tIndex = sharedIndex[idx];
sharedIndex[idx] = sharedIndex[ixj];
sharedIndex[ixj] = tIndex;
}
}
barrier(CLK_LOCAL_MEM_FENCE);
}
}
if (tid == 0) {
__global DTYPE *rowOut = outValue + row * k;
__global int *rowIdx = outIndex + row * k;
const int realK = min(k, rowSize);
for (int i = 0; i < realK; ++i) {
rowOut[i] = sharedValue[i];
rowIdx[i] = sharedIndex[i];
}
}
}