#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; \ } __kernel void pooling_c4_c4(GLOBAL_SIZE_3_DIMS __global const FLOAT *input, __private const int2 input_shape, __private const int2 output_shape, __private const int2 pad_shape, __global FLOAT *output, __global FLOAT *rediceOutput, __private const int channel, __private const int batch, __private const int in_channel_block, __private const int out_channel_block, __private const int input_pad_left, __private const int input_pad_right, __private const int output_pad_left, __private const int output_pad_right) { const int ow_idx = get_global_id(0); const int b_oh_idx = get_global_id(1); const int c_idx = get_global_id(2); DEAL_NON_UNIFORM_DIM3(ow_idx, b_oh_idx, c_idx); const int b_idx = b_oh_idx / output_shape.x; const int oh_idx = b_oh_idx % output_shape.x; const int iw_start = mad24(ow_idx, STRIDE_X, -pad_shape.y); const int ih_start = mad24(oh_idx, STRIDE_Y, -pad_shape.x); #ifdef POOL_AVG COMPUTE_FLOAT4 result = (COMPUTE_FLOAT4)(0); const int inp_offset = (((b_idx+c_idx*batch)*input_shape.x+ih_start)*input_shape.y+iw_start+input_pad_left)*4; #ifdef COUNT_INCLUDE_PADDING int total_count = (min(ih_start + KERNEL_Y, input_shape.x + pad_shape.x) - ih_start) * (min(iw_start + KERNEL_X, input_shape.y + pad_shape.y) - iw_start); #else int total_count = 0; #endif for(int kh=0; kh= input_shape.x) { continue; } for(int kw=0; kw= input_shape.y) { continue; } COMPUTE_FLOAT4 inp_data = CONVERT_COMPUTE_FLOAT4(vload4(0, input+inp_offset+(kh*input_shape.y+kw)*4)); result += inp_data; #ifndef COUNT_INCLUDE_PADDING total_count++; #endif } } result = result / (COMPUTE_FLOAT4)(1.0*total_count); #else COMPUTE_FLOAT4 result = (COMPUTE_FLOAT4)(-FLT_MAX); #if RETURN_REDICE int4 redice = (int4)0; #endif const int inp_offset = (((b_idx+c_idx*batch)*input_shape.x+ih_start)*input_shape.y+iw_start+input_pad_left)*4; for(int kh=0; kh= input_shape.x) { continue; } for(int kw=0; kw= input_shape.y) { continue; } COMPUTE_FLOAT4 inp_data = CONVERT_COMPUTE_FLOAT4(vload4(0, input+inp_offset+(kh*input_shape.y+kw)*4)); #if RETURN_REDICE redice = inp_data > result ? (int4)((ih_start + kh) * input_shape.y + iw_start + kw) : redice; #endif result = fmax(result, inp_data); } } #endif const int out_offset = (((b_idx + c_idx*batch)*output_shape.x + oh_idx)* output_shape.y + ow_idx + output_pad_left)*4; vstore4(CONVERT_FLOAT4(result), 0, output+out_offset); #if RETURN_REDICE vstore4(CONVERT_FLOAT4(redice), 0, rediceOutput+(((b_idx + c_idx*batch)*output_shape.x + oh_idx)* output_shape.y + ow_idx)*4); #endif } __kernel void pooling_c4_c16(GLOBAL_SIZE_3_DIMS __global const FLOAT *input, __private const int2 input_shape, __private const int2 output_shape, __private const int2 pad_shape, __global FLOAT *output, __global FLOAT *rediceOutput, __private const int channel, __private const int batch, __private const int in_channel_block, __private const int out_channel_block, __private const int input_pad_left, __private const int input_pad_right, __private const int output_pad_left, __private const int output_pad_right) { const int ow_idx = get_global_id(0); const int b_oh_idx = get_global_id(1); const int c_idx = get_global_id(2); DEAL_NON_UNIFORM_DIM3(ow_idx, b_oh_idx, c_idx); const int b_idx = b_oh_idx / output_shape.x; const int oh_idx = b_oh_idx % output_shape.x; const int iw_start = mad24(ow_idx, STRIDE_X, -pad_shape.y); const int ih_start = mad24(oh_idx, STRIDE_Y, -pad_shape.x); const int dst_width = output_shape.y + output_pad_left + output_pad_right; #ifdef POOL_AVG COMPUTE_FLOAT4 result = (COMPUTE_FLOAT4)(0); const int inp_offset = (((b_idx+c_idx*batch)*input_shape.x+ih_start)*input_shape.y+iw_start+input_pad_left)*4; #ifdef COUNT_INCLUDE_PADDING int total_count = (min(ih_start + KERNEL_Y, input_shape.x + pad_shape.x) - ih_start) * (min(iw_start + KERNEL_X, input_shape.y + pad_shape.y) - iw_start); #else int total_count = 0; #endif for(int kh=0; kh= input_shape.x) { continue; } for(int kw=0; kw= input_shape.y) { continue; } COMPUTE_FLOAT4 inp_data = CONVERT_COMPUTE_FLOAT4(vload4(0, input+inp_offset+(kh*input_shape.y+kw)*4)); result += inp_data; #ifndef COUNT_INCLUDE_PADDING total_count++; #endif } } result = result / (COMPUTE_FLOAT4)(1.0*total_count); #else COMPUTE_FLOAT4 result = (COMPUTE_FLOAT4)(-FLT_MAX); #if RETURN_REDICE int4 redice = (int4)0; #endif const int inp_offset = (((b_idx+c_idx*batch)*input_shape.x+ih_start)*input_shape.y+iw_start+input_pad_left)*4; for(int kh=0; kh= input_shape.x) { continue; } for(int kw=0; kw= input_shape.y) { continue; } COMPUTE_FLOAT4 inp_data = CONVERT_COMPUTE_FLOAT4(vload4(0, input+inp_offset+(kh*input_shape.y+kw)*4)); #if RETURN_REDICE redice = inp_data > result ? (int4)((ih_start + kh) * input_shape.y + iw_start + kw) : redice; #endif result = fmax(result, inp_data); } } #endif const int c_left = (c_idx % 4) * 4; const int out_offset = (((b_idx*out_channel_block + c_idx/4)*output_shape.x + oh_idx)* dst_width + ow_idx + output_pad_left)*16 + c_left; vstore4(CONVERT_FLOAT4(result), 0, output+out_offset); #if RETURN_REDICE vstore4(CONVERT_FLOAT4(redice), 0, rediceOutput+(((b_idx*out_channel_block + c_idx)*output_shape.x + oh_idx)* output_shape.y + ow_idx)*4); #endif if(ow_idx == 0){ int pad_offset = (((b_idx*out_channel_block + c_idx/4)*output_shape.x + oh_idx)* dst_width + 0)*16 + c_left; for(int i = 0; i < output_pad_left; ++i){ vstore4((FLOAT4)0, 0, output + pad_offset + i * 16); } pad_offset += (output_shape.y + output_pad_left) * 16; for(int i = 0; i < output_pad_right; ++i){ vstore4((FLOAT4)0, 0, output + pad_offset + i * 16); } } } __attribute__((intel_reqd_sub_group_size(16))) __kernel void pooling_c16_c16(GLOBAL_SIZE_3_DIMS __global const FLOAT *input, __private const int2 input_shape, __private const int2 output_shape, __private const int2 pad_shape, __global FLOAT *output, __global FLOAT *rediceOutput, __private const int channel, __private const int batch, __private const int in_channel_block, __private const int out_channel_block, __private const int input_pad_left, __private const int input_pad_right, __private const int output_pad_left, __private const int output_pad_right) { const int ow_idx = get_global_id(1) << 3; const int b_oh_idx = get_global_id(2); const int c_idx = get_group_id(0); const int sglid = get_sub_group_local_id(); const int b_idx = b_oh_idx / output_shape.x; const int oh_idx = b_oh_idx % output_shape.x; const int iw_start = mad24(ow_idx, STRIDE_X, -pad_shape.y); const int ih_start = mad24(oh_idx, STRIDE_Y, -pad_shape.x); const int src_width = input_shape.y + input_pad_left + input_pad_right; const int dst_width = output_shape.y + output_pad_left + output_pad_right; #ifdef POOL_AVG COMPUTE_FLOAT8 result = (COMPUTE_FLOAT8)(0); COMPUTE_FLOAT8 w_start = (COMPUTE_FLOAT8)(iw_start, iw_start + STRIDE_X, iw_start + STRIDE_X * 2, iw_start + STRIDE_X * 3, iw_start + STRIDE_X * 4, iw_start + STRIDE_X * 5, iw_start + STRIDE_X * 6, iw_start + STRIDE_X * 7); #ifdef COUNT_INCLUDE_PADDING COMPUTE_FLOAT8 w_size = fmin(w_start + KERNEL_X, input_shape.y + pad_shape.y) - w_start; COMPUTE_FLOAT8 total_count = (COMPUTE_FLOAT8)(min(ih_start + KERNEL_Y, input_shape.x + pad_shape.x) - ih_start) * w_size; #else w_start = fmax(w_start, (COMPUTE_FLOAT8)0); COMPUTE_FLOAT8 w_end = fmin(w_start + KERNEL_X, (COMPUTE_FLOAT8)input_shape.y); float h_start = fmax((float)ih_start, 0); float h_end = fmin(h_start + KERNEL_Y, (float)input_shape.x); COMPUTE_FLOAT8 total_count = (w_end - w_start) * (COMPUTE_FLOAT8)(h_end - h_start); #endif #else COMPUTE_FLOAT8 result = (COMPUTE_FLOAT8)(-FLT_MAX); #if RETURN_REDICE int8 redice = (int8)0; #endif #endif const int inp_offset = mul24(mad24(mad24(mad24(b_idx,in_channel_block,c_idx),input_shape.x,ih_start),src_width,iw_start+input_pad_left),16); for(int kh=0; kh= input_shape.x) { continue; } FLOAT line_cache[INPUT_LINE_SIZE]; for (int i = 0; i < INPUT_LINE_SIZE; i++) { if ((iw_start + i) >= 0 && (iw_start + i) < input_shape.y){ #ifdef MNN_SUPPORT_FP16 line_cache[i] = as_half(intel_sub_group_block_read_us((__global ushort*)(input + inp_offset + mul24(mad24(kh,src_width,i),16)))); #else line_cache[i] = as_float(intel_sub_group_block_read((__global uint*)(input + inp_offset + mul24(mad24(kh,src_width,i),16)))); #endif } else{ #ifdef POOL_AVG line_cache[i] = 0; #else line_cache[i] = (COMPUTE_FLOAT)(-FLT_MAX); #endif } } for(int kw=0; kw result ? (int8)((ih_start + kh) * input_shape.y + iw_start + kw) : redice; #endif result = fmax(result, src); #endif } } #ifdef POOL_AVG result = result / total_count; #endif if(ow_idx == 0){ int pad_offset = (((b_idx*out_channel_block + c_idx)*output_shape.x + oh_idx)* dst_width + 0)*16 + sglid; for(int i = 0; i < output_pad_left; ++i){ output[pad_offset+i*16] = 0; } pad_offset += (output_shape.y + output_pad_left) * 16; for(int i = 0; i < output_pad_right; ++i){ output[pad_offset+i*16] = 0; } } const int out_offset = (((b_idx*out_channel_block + c_idx)*output_shape.x + oh_idx)* dst_width + ow_idx + output_pad_left)*16; #if OUTPUT_LEFTOVERS if ((c_idx+1)*16 >= channel) { for (int i = 0; i < 8; i++) { if ((c_idx*16 + sglid < channel) && (ow_idx + i) < output_shape.y) output[out_offset + i * 16 + sglid] = result[i]; } } else #endif { if (ow_idx + 8 <= output_shape.y) { #ifdef MNN_SUPPORT_FP16 intel_sub_group_block_write_us8((__global ushort*)(output + out_offset), as_ushort8(CONVERT_FLOAT8(result))); #else intel_sub_group_block_write8((__global uint*)(output + out_offset), as_uint8(CONVERT_FLOAT8(result))); #endif }else{ for (int i = 0; i < output_shape.y % 8; i++) { output[out_offset + i * 16 + sglid] = result[i]; } } } #ifdef RETURN_REDICE const uint lid_x = sglid % 4; const uint lid_y = sglid / 4; const int width_height = output_shape.y * output_shape.x * 4; const int redice_offset = (((b_idx*out_channel_block + c_idx * 4)*output_shape.x + oh_idx)* output_shape.y + ow_idx)*4; #if OUTPUT_LEFTOVERS if ((c_idx+1)*16 >= channel) { for (int i = 0; i < 8; i++) { if ((c_idx*16 + lid_y * 4 + lid_x < channel) && (ow_idx + i) < output_shape.y) rediceOutput[redice_offset + lid_y * width_height + i * 4 + lid_x] = redice[i]; } } else #endif { for (int i = 0; i < 8 && (ow_idx + i) < output_shape.y; i++) { rediceOutput[redice_offset + lid_y * width_height + i * 4 + lid_x] = redice[i]; } } #endif } __attribute__((intel_reqd_sub_group_size(16))) __kernel void pooling_c16_c4(GLOBAL_SIZE_3_DIMS __global const FLOAT *input, __private const int2 input_shape, __private const int2 output_shape, __private const int2 pad_shape, __global FLOAT *output, __global FLOAT *rediceOutput, __private const int channel, __private const int batch, __private const int in_channel_block, __private const int out_channel_block, __private const int input_pad_left, __private const int input_pad_right, __private const int output_pad_left, __private const int output_pad_right) { const int ow_idx = get_global_id(1) << 3; const int b_oh_idx = get_global_id(2); const int c_idx = get_group_id(0); const int sglid = get_sub_group_local_id(); const int b_idx = b_oh_idx / output_shape.x; const int oh_idx = b_oh_idx % output_shape.x; const int iw_start = mad24(ow_idx, STRIDE_X, -pad_shape.y); const int ih_start = mad24(oh_idx, STRIDE_Y, -pad_shape.x); const int src_width = input_shape.y + input_pad_left + input_pad_right; #ifdef POOL_AVG COMPUTE_FLOAT8 result = (COMPUTE_FLOAT8)(0); COMPUTE_FLOAT8 w_start = (COMPUTE_FLOAT8)(iw_start, iw_start + STRIDE_X, iw_start + STRIDE_X * 2, iw_start + STRIDE_X * 3, iw_start + STRIDE_X * 4, iw_start + STRIDE_X * 5, iw_start + STRIDE_X * 6, iw_start + STRIDE_X * 7); #ifdef COUNT_INCLUDE_PADDING COMPUTE_FLOAT8 w_size = fmin(w_start + KERNEL_X, input_shape.y + pad_shape.y) - w_start; COMPUTE_FLOAT8 total_count = (COMPUTE_FLOAT8)(min(ih_start + KERNEL_Y, input_shape.x + pad_shape.x) - ih_start) * w_size; #else w_start = fmax(w_start, (COMPUTE_FLOAT8)0); COMPUTE_FLOAT8 w_end = fmin(w_start + KERNEL_X, (COMPUTE_FLOAT8)input_shape.y); float h_start = fmax((float)ih_start, 0); float h_end = fmin(h_start + KERNEL_Y, (float)input_shape.x); COMPUTE_FLOAT8 total_count = (w_end - w_start) * (COMPUTE_FLOAT8)(h_end - h_start); #endif #else COMPUTE_FLOAT8 result = (COMPUTE_FLOAT8)(-FLT_MAX); #if RETURN_REDICE int8 redice = (int8)0; #endif #endif const int inp_offset = mul24(mad24(mad24(mad24(b_idx,in_channel_block,c_idx),input_shape.x,ih_start),src_width,iw_start+input_pad_left),16); for(int kh=0; kh= input_shape.x) { continue; } FLOAT line_cache[INPUT_LINE_SIZE]; for (int i = 0; i < INPUT_LINE_SIZE; i++) { if ((iw_start + i) >= 0 && (iw_start + i) < input_shape.y){ #ifdef MNN_SUPPORT_FP16 line_cache[i] = as_half(intel_sub_group_block_read_us((__global ushort*)(input + inp_offset + mul24(mad24(kh,src_width,i),16)))); #else line_cache[i] = as_float(intel_sub_group_block_read((__global uint*)(input + inp_offset + mul24(mad24(kh,src_width,i),16)))); #endif } else{ #ifdef POOL_AVG line_cache[i] = 0; #else line_cache[i] = (FLOAT)(-FLT_MAX); #endif } } for(int kw=0; kw result ? (int8)((ih_start + kh) * input_shape.y + iw_start + kw) : redice; #endif result = fmax(result, src); #endif } } #ifdef POOL_AVG result = result / total_count; #endif const uint lid_x = sglid % 4; const uint lid_y = sglid / 4; const int out_offset = (((b_idx + c_idx * 4 * batch)*output_shape.x + oh_idx)* output_shape.y + ow_idx + output_pad_left)*4; const int batch_width_height = batch * output_shape.y * output_shape.x * 4; #if RETURN_REDICE const int redice_offset = (((b_idx + c_idx * 4 * batch)*output_shape.x + oh_idx)* output_shape.y + ow_idx)*4; #endif #if OUTPUT_LEFTOVERS if ((c_idx+1)*16 >= channel) { for (int i = 0; i < 8; i++) { if ((c_idx*16 + lid_y * 4 + lid_x < channel) && (ow_idx + i) < output_shape.y) output[out_offset + lid_y * batch_width_height + i * 4 + lid_x] = result[i]; #if RETURN_REDICE rediceOutput[redice_offset + lid_y * batch_width_height + i * 4 + lid_x] = redice[i]; #endif } } else #endif { for (int i = 0; i < 8 && (ow_idx + i) < output_shape.y; i++) { output[out_offset + lid_y * batch_width_height + i * 4 + lid_x] = result[i]; #if RETURN_REDICE rediceOutput[redice_offset + lid_y * batch_width_height + i * 4 + lid_x] = redice[i]; #endif } } }