243 lines
13 KiB
Common Lisp
243 lines
13 KiB
Common Lisp
#ifdef MNN_SUPPORT_FP16
|
|
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
|
#endif
|
|
|
|
#define GLOBAL_SIZE_2_DIMS __private const int global_size_dim0, __private const int global_size_dim1,
|
|
#define DEAL_NON_UNIFORM_DIM2(input1, input2) \
|
|
if (input1 >= global_size_dim0 || input2 >= global_size_dim1) { \
|
|
return; \
|
|
}
|
|
|
|
// convert data from buffer(nhwc) to buffer(nc16hw16) float input
|
|
__kernel void nhwc_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global const INPUT_TYPE *input_ptr,
|
|
__private const int height,
|
|
__private const int width, __private const int channels,
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int input_pad_left, __private const int input_pad_right,
|
|
__private const int output_pad_left, __private const int output_pad_right) {
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int batch_idx = image_height_idx / height;
|
|
const int height_idx = image_height_idx % height;
|
|
const int width_idx = image_width_idx % width;
|
|
const int channel_16_idx = (image_width_idx / width) << 4;
|
|
const int buffer_offset = ((batch_idx * height + height_idx) * width + width_idx) * channels + channel_16_idx;
|
|
|
|
const int remain_channel = min(channels - channel_16_idx, 16);
|
|
INPUT_TYPE16 values = 0;
|
|
INPUT_TYPE* values_ptr = (INPUT_TYPE*)(&values);
|
|
|
|
__global const INPUT_TYPE *input_current_ptr = input_ptr + buffer_offset;
|
|
|
|
for(int i = 0; i < remain_channel; ++i){
|
|
values_ptr[i] = *(input_current_ptr + i);
|
|
}
|
|
const int out_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (output_pad_left + width + output_pad_right) + width_idx + output_pad_left)*16;
|
|
vstore16(CONVERT_OUTPUT16(values), 0, output+out_offset);
|
|
if(width_idx == 0){
|
|
int pad_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (output_pad_left + width + output_pad_right))*16;
|
|
for(int i = 0; i < output_pad_left; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset+i*16);
|
|
}
|
|
pad_offset += (output_pad_right + width) * 16;
|
|
for(int i = 0; i < output_pad_right; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset+i*16);
|
|
}
|
|
}
|
|
}
|
|
|
|
// convert data from buffer(nchw) to buffer(nc16hw16)
|
|
__kernel void nchw_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global const INPUT_TYPE *input_ptr,
|
|
__private const int height, __private const int width, __private const int channels,
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int input_pad_left, __private const int input_pad_right,
|
|
__private const int output_pad_left, __private const int output_pad_right) {
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int src_width = width + input_pad_left + input_pad_right;
|
|
const int dst_width = width + output_pad_left + output_pad_right;
|
|
const int batch_idx = image_height_idx / height;
|
|
const int height_idx = image_height_idx % height;
|
|
const int width_idx = image_width_idx % width;
|
|
const int channel_16_idx = image_width_idx / width << 4;
|
|
const int buffer_offset = ((batch_idx * channels + channel_16_idx) * height + height_idx) * src_width + width_idx + input_pad_left;
|
|
|
|
const int remain_channel = min(channels - channel_16_idx, 16);
|
|
const int height_width_size = height * width;
|
|
INPUT_TYPE16 output_values = 0;
|
|
INPUT_TYPE *output_values_ptr = (INPUT_TYPE*)(&output_values);
|
|
for(int i = 0; i < remain_channel; ++i){
|
|
output_values_ptr[i] = *(input_ptr + buffer_offset + height_width_size * i);
|
|
}
|
|
|
|
if(width_idx == 0){
|
|
int pad_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * dst_width + 0)*16;
|
|
for(int i = 0; i < output_pad_left; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
|
|
}
|
|
pad_offset += 16 * (width + output_pad_left);
|
|
for(int i = 0; i < output_pad_right; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
|
|
}
|
|
}
|
|
const int out_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * dst_width + width_idx + output_pad_left)*16;
|
|
vstore16(CONVERT_OUTPUT16(output_values), 0, output+out_offset);
|
|
}
|
|
|
|
// convert data from image(b h, ic/16 w ic16) to buffer(nhwc)
|
|
__kernel void nc16hw16_buffer_to_nhwc_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int height, __private const int width,
|
|
__private const int channels,
|
|
__global INPUT_TYPE *input_ptr,
|
|
__private const int input_pad_left, __private const int input_pad_right,
|
|
__private const int output_pad_left, __private const int output_pad_right) {
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int batch_idx = image_height_idx / height;
|
|
const int height_idx = image_height_idx % height;
|
|
const int width_idx = image_width_idx % width;
|
|
const int channel_16_idx = (image_width_idx / width) << 4;
|
|
const int buffer_offset = ((batch_idx * height + height_idx) * width + width_idx) * channels + channel_16_idx;
|
|
|
|
const int in_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (input_pad_left + width + input_pad_right) + width_idx + input_pad_left)*16;
|
|
|
|
INPUT_TYPE16 values = vload16(0, input_ptr+in_offset);
|
|
INPUT_TYPE* values_ptr = (INPUT_TYPE*)(&values);
|
|
const int remain_channel = min(channels - channel_16_idx, 16);
|
|
for(int i = 0; i < remain_channel; ++i){
|
|
output[buffer_offset + i] = (OUTPUT_TYPE)values_ptr[i];
|
|
}
|
|
}
|
|
|
|
// convert data from buffer(nc16hw16) to buffer(nchw)
|
|
__kernel void nc16hw16_buffer_to_nchw_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int height, __private const int width,
|
|
__private const int channels,
|
|
__global INPUT_TYPE *input_ptr,
|
|
__private const int input_pad_left, __private const int input_pad_right,
|
|
__private const int output_pad_left, __private const int output_pad_right) {
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int src_width = width + input_pad_left + input_pad_right;
|
|
const int batch_idx = image_height_idx / height;
|
|
const int height_idx = image_height_idx % height;
|
|
const int width_idx = image_width_idx % width;
|
|
int channel_16_idx = (image_width_idx / width) << 4;
|
|
int buffer_offset = ((batch_idx * channels + channel_16_idx) * height + height_idx) * width + width_idx;
|
|
|
|
const int in_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * src_width + width_idx + input_pad_left)*16;
|
|
INPUT_TYPE16 values = vload16(0, input_ptr+in_offset);
|
|
INPUT_TYPE *values_ptr = (INPUT_TYPE*)(&values);
|
|
|
|
const int height_width_size = height * width;
|
|
|
|
const int remain_channel = min(channels - channel_16_idx, 16);
|
|
for(int i = 0; i < remain_channel; ++i){
|
|
output[buffer_offset + i * height_width_size] = (OUTPUT_TYPE)values_ptr[i];
|
|
}
|
|
}
|
|
|
|
__kernel void nc4hw4_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global const INPUT_TYPE *input_ptr,
|
|
__private const int2 output_shape,
|
|
__private const int2 src_stride,
|
|
__private const int2 dst_stride,
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int input_pad_left,
|
|
__private const int input_pad_right,
|
|
__private const int output_pad_left,
|
|
__private const int output_pad_right,
|
|
__private const int channelc4
|
|
) {
|
|
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int batch_idx = image_height_idx / output_shape.x;
|
|
const int height_idx = image_height_idx % output_shape.x;
|
|
const int width_idx = image_width_idx % output_shape.y;
|
|
const int channel_block_idx = image_width_idx / output_shape.y;
|
|
const int in_channel_block_idx = channel_block_idx << 2;
|
|
const int dst_width = output_pad_left + output_shape.y + output_pad_right;
|
|
int2 src_bc_offset = src_stride * (int2)(batch_idx, in_channel_block_idx);
|
|
int2 dst_bc_offset = dst_stride * (int2)(batch_idx, channel_block_idx);
|
|
int src_buffer_offset =
|
|
(((src_bc_offset.x + src_bc_offset.y) * output_shape.x + height_idx) * output_shape.y + width_idx) * 4;
|
|
int dst_buffer_offset =
|
|
(((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * dst_width + width_idx + output_pad_left) * 16;
|
|
int width_height_size4 = output_shape.x * output_shape.y * 4;
|
|
INPUT_TYPE4 values0 = vload4(0, input_ptr + src_buffer_offset);
|
|
INPUT_TYPE4 values1 = in_channel_block_idx + 1 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4);
|
|
INPUT_TYPE4 values2 = in_channel_block_idx + 2 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4 * 2);
|
|
INPUT_TYPE4 values3 = in_channel_block_idx + 3 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4 * 3);
|
|
|
|
vstore16(CONVERT_OUTPUT16((INPUT_TYPE16)(values0.s0123, values1.s0123, values2.s0123, values3.s0123)), 0, output+dst_buffer_offset);
|
|
if(width_idx == 0){
|
|
int pad_offset = (((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * dst_width) * 16;
|
|
for(int i = 0; i < output_pad_left; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
|
|
}
|
|
pad_offset += 16 * (output_shape.y + output_pad_left);
|
|
for(int i = 0; i < output_pad_right; ++i){
|
|
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
|
|
}
|
|
}
|
|
}
|
|
|
|
__kernel void nc16hw16_buffer_to_nc4hw4_buffer(GLOBAL_SIZE_2_DIMS
|
|
__global const INPUT_TYPE *input_ptr,
|
|
__private const int2 output_shape,
|
|
__private const int2 src_stride,
|
|
__private const int2 dst_stride,
|
|
__global OUTPUT_TYPE *output,
|
|
__private const int input_pad_left,__private const int input_pad_right,
|
|
__private const int output_pad_left,__private const int output_pad_right,
|
|
__private const int channelc4
|
|
) {
|
|
|
|
int image_width_idx = get_global_id(0);
|
|
int image_height_idx = get_global_id(1);
|
|
|
|
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
|
|
|
|
const int batch_idx = image_height_idx / output_shape.x;
|
|
const int height_idx = image_height_idx % output_shape.x;
|
|
const int width_idx = image_width_idx % output_shape.y;
|
|
const int channel_block_idx = image_width_idx / output_shape.y;
|
|
const int out_channel_block_idx = channel_block_idx << 2;
|
|
int2 src_bc_offset = src_stride * (int2)(batch_idx, channel_block_idx);
|
|
int2 dst_bc_offset = dst_stride * (int2)(batch_idx, out_channel_block_idx);
|
|
int width_height_size4 = output_shape.x * output_shape.y * 4;
|
|
int src_buffer_offset =
|
|
(((src_bc_offset.x + src_bc_offset.y) * output_shape.x + height_idx) * (input_pad_left + output_shape.y + input_pad_right) + width_idx + input_pad_left) * 16;
|
|
int dst_buffer_offset =
|
|
(((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * output_shape.y + width_idx) * 4;
|
|
INPUT_TYPE16 values = vload16(0, input_ptr + src_buffer_offset);
|
|
|
|
vstore4(CONVERT_OUTPUT4(values.s0123), 0, output+dst_buffer_offset);
|
|
if(out_channel_block_idx + 1 >= channelc4) return;
|
|
vstore4(CONVERT_OUTPUT4(values.s4567), 0, output+dst_buffer_offset + width_height_size4);
|
|
if(out_channel_block_idx + 2 >= channelc4) return;
|
|
vstore4(CONVERT_OUTPUT4(values.s89ab), 0, output+dst_buffer_offset + 2 * width_height_size4);
|
|
if(out_channel_block_idx + 3 >= channelc4) return;
|
|
vstore4(CONVERT_OUTPUT4(values.scdef), 0, output+dst_buffer_offset + 3 * width_height_size4);
|
|
}
|