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

253 lines
9.8 KiB
Common Lisp

#ifdef MNN_SUPPORT_FP16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif
__constant sampler_t SAMPLER = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;
#ifdef LOCAL_SIZE
__kernel void layernorm_w(__private int global_dim0, __private int global_dim1, __private int global_dim2,
__read_only image2d_t input,
__write_only image2d_t output,
__private const int width,
__private const int height,
__private const int channel,
#ifdef GAMMA_BETA
__global const FLOAT *gamma,
__global const FLOAT *beta,
#endif
__private float epsilon){
int3 pos = (int3)(get_global_id(0), get_global_id(1), get_global_id(2));
float4 local sum_mnn[LOCAL_SIZE];
#ifndef RMSNORM
float4 local sum_mean_mnn[LOCAL_SIZE];
#endif
if (pos.x < global_dim0 && pos.y < global_dim1 && pos.z < global_dim2) {
const int h = pos.y % height;
const int c = pos.y / height;
const int b = pos.z;
const int lid = get_local_id(0);
const int bh_offset = mad24(b, height, h);
float4 in_sum = 0;
#ifdef RMSNORM
float4 mean = 0;
#else
for(int i = lid; i < width; i+=LOCAL_SIZE){
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + i, bh_offset)));
in_sum += in;
}
sum_mean_mnn[lid] = in_sum;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = LOCAL_SIZE/2; i > 0; i /= 2){
if (lid < i)
sum_mean_mnn[lid] = sum_mean_mnn[lid] + sum_mean_mnn[lid + i];
barrier(CLK_LOCAL_MEM_FENCE);
}
float4 mean = sum_mean_mnn[0] / (float4)width;
#endif
in_sum = 0;
for(int i = lid; i < width; i+=LOCAL_SIZE){
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + i, bh_offset)));
in_sum += (in - mean) * (in - mean);
}
sum_mnn[lid] = in_sum;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = 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);
}
float4 square_sum = sum_mnn[0] / (float4)width;
float4 value = (float4)1.0f / (float4)sqrt(square_sum + (float4)epsilon);
for(int i = lid; i < width; i+=LOCAL_SIZE){
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + i, bh_offset)));
#ifdef GAMMA_BETA
float4 out = (in - mean) * value * (float4)gamma[i] + (float4)beta[i];
#else
float4 out = (in - mean) * value;
#endif
WI_F(output, (int2)(c * width + i, bh_offset), CONVERT_FLOAT4(out));
}
}
}
__kernel void layernorm_hw(__private int global_dim0, __private int global_dim1, __private int global_dim2,
__read_only image2d_t input,
__write_only image2d_t output,
__private const int width,
__private const int height,
__private const int channel,
#ifdef GAMMA_BETA
__global const FLOAT *gamma,
__global const FLOAT *beta,
#endif
__private float epsilon){
int3 pos = (int3)(get_global_id(0), get_global_id(1), get_global_id(2));
float4 local sum_mnn[LOCAL_SIZE];
#ifndef RMSNORM
float4 local sum_mean_mnn[LOCAL_SIZE];
#endif
if (pos.x < global_dim0 && pos.y < global_dim1 && pos.z < global_dim2) {
const int c = pos.y;
const int b = pos.z;
const int height_width = height * width;
const int lid = get_local_id(0);
float4 in_sum = 0;
#ifdef RMSNORM
float4 mean = 0;
#else
for(int i = lid; i < height_width; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
in_sum += in;
}
sum_mean_mnn[lid] = in_sum;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = LOCAL_SIZE/2; i > 0; i /= 2){
if (lid < i)
sum_mean_mnn[lid] = sum_mean_mnn[lid] + sum_mean_mnn[lid + i];
barrier(CLK_LOCAL_MEM_FENCE);
}
float4 mean = sum_mean_mnn[0] / (float4)height_width;
#endif
in_sum = 0;
for(int i = lid; i < height_width; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
in_sum += (in - mean) * (in - mean);
}
sum_mnn[lid] = in_sum;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = 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);
}
float4 square_sum = sum_mnn[0] / (float4)height_width;
float4 value = (float4)1.0f / (float4)sqrt(square_sum + (float4)epsilon);
for(int i = lid; i < height_width; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
#ifdef GAMMA_BETA
float4 out = (in - mean) * value * (float4)gamma[i] + (float4)beta[i];
#else
float4 out = (in - mean) * value;
#endif
WI_F(output, (int2)(c * width + w, b * height + h), CONVERT_FLOAT4(out));
}
}
}
__kernel void layernorm_chw(__private int global_dim0, __private int global_dim1, __private int global_dim2,
__read_only image2d_t input,
__write_only image2d_t output,
__private const int width,
__private const int height,
__private const int channel,
#ifdef GAMMA_BETA
__global const FLOAT *gamma,
__global const FLOAT *beta,
#endif
__private float epsilon){
int3 pos = (int3)(get_global_id(0), get_global_id(1), get_global_id(2));
float local sum_mnn[LOCAL_SIZE];
#ifndef RMSNORM
float4 local sum_mean_mnn[LOCAL_SIZE];
#endif
if (pos.x < global_dim0 && pos.y < global_dim1 && pos.z < global_dim2) {
const int b = pos.z;
const int sum_size = width * height * channel;
const int reduce_size = width * height;
const int lid = get_local_id(0);
const int channel4 = (channel + 3) / 4;
const int channel_remain = channel - (channel4 - 1) * 4;
float4 in_sum = 0;
float4 in_sum_left = 0;
float *in_sum_left_ptr = (float*)(&in_sum_left);
#ifdef RMSNORM
float4 mean = 0;
#else
for(int c = 0; c < channel4 - 1; ++c){
for(int i = lid; i < reduce_size; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
in_sum += in;
}
}
for(int i = lid; i < reduce_size; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)((channel4 - 1) * width + w, b * height + h)));
in_sum_left += in;
}
in_sum.x = in_sum.x + in_sum.y + in_sum.z + in_sum.w;
for(int i = 1; i < channel_remain; ++i){
in_sum_left_ptr[0] += in_sum_left_ptr[i];
}
sum_mean_mnn[lid] = in_sum.x + in_sum_left.x;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = LOCAL_SIZE/2; i > 0; i /= 2){
if (lid < i)
sum_mean_mnn[lid] = sum_mean_mnn[lid] + sum_mean_mnn[lid + i];
barrier(CLK_LOCAL_MEM_FENCE);
}
float4 mean = sum_mean_mnn[0] / (float4)sum_size;
#endif
in_sum = 0;
in_sum_left = 0;
for(int c = 0; c < channel4 - 1; ++c){
for(int i = lid; i < reduce_size; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
in_sum += (in - mean) * (in - mean);
}
}
for(int i = lid; i < reduce_size; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)((channel4 - 1) * width + w, b * height + h)));
in_sum_left += (in - mean) * (in - mean);
}
in_sum.x = in_sum.x + in_sum.y + in_sum.z + in_sum.w;
for(int i = 1; i < channel_remain; ++i){
in_sum_left_ptr[0] += in_sum_left_ptr[i];
}
sum_mnn[lid] = in_sum.x + in_sum_left.x;
barrier(CLK_LOCAL_MEM_FENCE);
for(int i = 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);
}
float4 square_sum = sum_mnn[0] / (float4)sum_size;
float4 value = (float4)1.0f / (float4)sqrt(square_sum + (float4)epsilon);
for(int c = 0; c < channel4; ++c){
for(int i = lid; i < reduce_size; i+=LOCAL_SIZE){
int w = i % width;
int h = i / width;
float4 in = convert_float4(RI_F(input, SAMPLER, (int2)(c * width + w, b * height + h)));
#ifdef GAMMA_BETA
float4 out = (in - mean) * value * (float4)gamma[c * reduce_size + i] + (float4)beta[c * reduce_size + i];
#else
float4 out = (in - mean) * value;
#endif
WI_F(output, (int2)(c * width + w, b * height + h), CONVERT_FLOAT4(out));
}
}
}
}
#endif