233 lines
9.0 KiB
Common Lisp
233 lines
9.0 KiB
Common Lisp
#ifdef MNN_SUPPORT_FP16
|
|
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
|
#endif
|
|
|
|
#define EXP exp
|
|
#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; \
|
|
}
|
|
|
|
|
|
__kernel void softmax_in1_buf(GLOBAL_SIZE_3_DIMS
|
|
__global const FLOAT *input,
|
|
__global FLOAT *output,
|
|
__private const int inside,
|
|
__private const int outside,
|
|
__private const int dim) {
|
|
|
|
const int x = get_global_id(0);
|
|
const int y = get_global_id(1); // inside = 1
|
|
const int z = get_global_id(2); // outside
|
|
DEAL_NON_UNIFORM_DIM3(x, y, z);
|
|
|
|
const int offset = z * dim + y;
|
|
const int dim4 = (dim + 3) / 4;
|
|
const int loop_end = max(0, dim4 - 1);
|
|
#if SOFTMAX_LOCAL_SIZE >= 4
|
|
int lid = get_local_id(0);
|
|
COMPUTE_FLOAT local sum_mnn[SOFTMAX_LOCAL_SIZE];
|
|
COMPUTE_FLOAT local max_mnn[SOFTMAX_LOCAL_SIZE];
|
|
|
|
// compute maxvalue
|
|
COMPUTE_FLOAT4 maxValue = (COMPUTE_FLOAT4)-FLT_MAX;
|
|
for (int i = lid; i < loop_end; i+=SOFTMAX_LOCAL_SIZE) {
|
|
maxValue = fmax(maxValue, CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)));
|
|
}
|
|
|
|
max_mnn[lid] = fmax(fmax(fmax(maxValue.x, maxValue.y), maxValue.z), maxValue.w);
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
max_mnn[lid] = fmax(max_mnn[lid], max_mnn[lid + i]);
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
maxValue.x = max_mnn[0];
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
maxValue.x = fmax(maxValue.x, (COMPUTE_FLOAT)(input[offset+i]));
|
|
}
|
|
|
|
// compute sumvalue
|
|
COMPUTE_FLOAT4 sumValue = (COMPUTE_FLOAT4)0;
|
|
for (int i = lid; i < loop_end; i+=SOFTMAX_LOCAL_SIZE) {
|
|
sumValue += exp(CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)) - (COMPUTE_FLOAT4)maxValue.x);
|
|
}
|
|
sum_mnn[lid] = sumValue.x + sumValue.y + sumValue.z + sumValue.w;
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
sum_mnn[lid] = sum_mnn[lid] + sum_mnn[lid + i];
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
sumValue.x = sum_mnn[0];
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
sumValue.x += exp((COMPUTE_FLOAT)(input[offset+i]) - maxValue.x);
|
|
}
|
|
|
|
// store result
|
|
for(int i = lid; i < loop_end; i+=SOFTMAX_LOCAL_SIZE){
|
|
vstore4(CONVERT_FLOAT4(exp(CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)) - (COMPUTE_FLOAT4)maxValue.x) / (COMPUTE_FLOAT4)sumValue.x), 0, output + offset + i * 4);
|
|
}
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
output[offset + i] = (FLOAT)exp((COMPUTE_FLOAT)(input[offset + i]) - maxValue.x) / sumValue.x;
|
|
}
|
|
#else
|
|
// compute maxvalue
|
|
COMPUTE_FLOAT4 maxValue = (COMPUTE_FLOAT4)-FLT_MAX;
|
|
for (int i = 0; i < loop_end; i++) {
|
|
maxValue = fmax(maxValue, CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)));
|
|
}
|
|
maxValue.x = fmax(fmax(fmax(maxValue.x, maxValue.y), maxValue.z), maxValue.w);
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
maxValue.x = fmax(maxValue.x, (COMPUTE_FLOAT)(input[offset+i]));
|
|
}
|
|
|
|
// compute sumvalue
|
|
COMPUTE_FLOAT4 sumValue = (COMPUTE_FLOAT4)0;
|
|
for (int i = 0; i < loop_end; i++) {
|
|
sumValue += exp(CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)) - (COMPUTE_FLOAT4)maxValue.x);
|
|
}
|
|
sumValue.x = sumValue.x + sumValue.y + sumValue.z + sumValue.w;
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
sumValue.x += exp((COMPUTE_FLOAT)(input[offset+i]) - maxValue.x);
|
|
}
|
|
|
|
// store result
|
|
for(int i = 0; i < loop_end; i++){
|
|
vstore4(CONVERT_FLOAT4(exp(CONVERT_COMPUTE_FLOAT4(vload4(i, input+offset)) - (COMPUTE_FLOAT4)maxValue.x) / (COMPUTE_FLOAT4)sumValue.x), 0, output + offset + i * 4);
|
|
}
|
|
for(int i = loop_end << 2; i < dim; ++i){
|
|
output[offset + i] = (FLOAT)exp((COMPUTE_FLOAT)(input[offset + i]) - maxValue.x) / sumValue.x;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
__kernel void softmax_buf(GLOBAL_SIZE_3_DIMS
|
|
__global const FLOAT *input,
|
|
__global FLOAT *output,
|
|
__private const int inside,
|
|
__private const int outside,
|
|
__private const int dim) {
|
|
|
|
const int x = get_global_id(0);
|
|
const int y = get_global_id(1); // inside
|
|
const int z = get_global_id(2); // outside
|
|
DEAL_NON_UNIFORM_DIM3(x, y, z);
|
|
|
|
const int offset = z * dim * inside + y;
|
|
#if SOFTMAX_LOCAL_SIZE >= 4
|
|
int lid = get_local_id(0);
|
|
COMPUTE_FLOAT local sum_mnn[SOFTMAX_LOCAL_SIZE];
|
|
COMPUTE_FLOAT local max_mnn[SOFTMAX_LOCAL_SIZE];
|
|
|
|
COMPUTE_FLOAT maxValue = (COMPUTE_FLOAT)-FLT_MAX;
|
|
for (int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE) {
|
|
maxValue = fmax(maxValue, (COMPUTE_FLOAT)(input[offset+i*inside]));
|
|
}
|
|
|
|
max_mnn[lid] = maxValue;
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
max_mnn[lid] = fmax(max_mnn[lid], max_mnn[lid + i]);
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
maxValue = max_mnn[0];
|
|
|
|
COMPUTE_FLOAT sumValue = (COMPUTE_FLOAT)0;
|
|
for (int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE) {
|
|
sumValue += exp((COMPUTE_FLOAT)(input[offset+i*inside]) - maxValue);
|
|
}
|
|
sum_mnn[lid] = sumValue;
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
sum_mnn[lid] = sum_mnn[lid] + sum_mnn[lid + i];
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
sumValue = sum_mnn[0];
|
|
for(int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE){
|
|
output[offset + i * inside] = (FLOAT)exp((COMPUTE_FLOAT)(input[offset + i * inside]) - maxValue) / sumValue;
|
|
}
|
|
#else
|
|
COMPUTE_FLOAT maxValue = (COMPUTE_FLOAT)-FLT_MAX;
|
|
for (int i = 0; i < dim; i++) {
|
|
maxValue = fmax(maxValue, (COMPUTE_FLOAT)(input[offset+i*inside]));
|
|
}
|
|
|
|
COMPUTE_FLOAT sumValue = (COMPUTE_FLOAT)0;
|
|
for (int i = 0; i < dim; i++) {
|
|
sumValue += exp((COMPUTE_FLOAT)(input[offset+i*inside]) - maxValue);
|
|
}
|
|
for(int i = 0; i < dim; i++){
|
|
output[offset + i * inside] = (FLOAT)exp((COMPUTE_FLOAT)(input[offset+i*inside]) - maxValue) / sumValue;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
__kernel void softmax_v4_buf(GLOBAL_SIZE_3_DIMS
|
|
__global const FLOAT *input,
|
|
__global FLOAT *output,
|
|
__private const int inside,
|
|
__private const int outside,
|
|
__private const int dim) {
|
|
|
|
const int x = get_global_id(0);
|
|
const int y = get_global_id(1); // inside
|
|
const int z = get_global_id(2); // outside
|
|
DEAL_NON_UNIFORM_DIM3(x, y, z);
|
|
|
|
const int offset = z * dim * inside + (y << 2);
|
|
#if SOFTMAX_LOCAL_SIZE >= 4
|
|
int lid = get_local_id(0);
|
|
COMPUTE_FLOAT4 local sum_mnn[SOFTMAX_LOCAL_SIZE];
|
|
COMPUTE_FLOAT4 local max_mnn[SOFTMAX_LOCAL_SIZE];
|
|
|
|
COMPUTE_FLOAT4 maxValue = (COMPUTE_FLOAT4)-FLT_MAX;
|
|
for (int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE) {
|
|
maxValue = fmax(maxValue, CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)));
|
|
}
|
|
|
|
max_mnn[lid] = maxValue;
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
max_mnn[lid] = fmax(max_mnn[lid], max_mnn[lid + i]);
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
maxValue = max_mnn[0];
|
|
|
|
COMPUTE_FLOAT4 sumValue = (COMPUTE_FLOAT4)0;
|
|
for (int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE) {
|
|
sumValue += exp(CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)) - maxValue);
|
|
}
|
|
sum_mnn[lid] = sumValue;
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
for(int i = SOFTMAX_LOCAL_SIZE/2; i > 0; i /= 2){
|
|
if (lid < i)
|
|
sum_mnn[lid] = sum_mnn[lid] + sum_mnn[lid + i];
|
|
barrier(CLK_LOCAL_MEM_FENCE);
|
|
}
|
|
sumValue = sum_mnn[0];
|
|
for(int i = lid; i < dim; i+=SOFTMAX_LOCAL_SIZE){
|
|
vstore4(CONVERT_FLOAT4(exp(CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)) - maxValue) / sumValue), 0, output+offset+i*inside);
|
|
}
|
|
#else
|
|
COMPUTE_FLOAT4 maxValue = (COMPUTE_FLOAT4)-FLT_MAX;
|
|
for (int i = 0; i < dim; i++) {
|
|
maxValue = fmax(maxValue, CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)));
|
|
}
|
|
|
|
COMPUTE_FLOAT4 sumValue = (COMPUTE_FLOAT4)0;
|
|
for (int i = 0; i < dim; i++) {
|
|
sumValue += exp(CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)) - maxValue);
|
|
}
|
|
for(int i = 0; i < dim; i++){
|
|
vstore4(CONVERT_FLOAT4(exp(CONVERT_COMPUTE_FLOAT4(vload4(0, input+offset+i*inside)) - maxValue) / sumValue), 0, output+offset+i*inside);
|
|
}
|
|
#endif
|
|
}
|