#ifdef MNN_SUPPORT_FP16 #pragma OPENCL EXTENSION cl_khr_fp16 : enable #endif #define GLOBAL_SIZE_DIM2 \ __private int global_size_dim0, __private int global_size_dim1, #define UNIFORM_BOUNDRY_CHECK(index0, index1) \ if(index0 >= global_size_dim0 || index1 >= global_size_dim1) { \ return; \ } #pragma OPENCL EXTENSION cl_intel_subgroups : enable __attribute__((intel_reqd_sub_group_size(16))) __kernel void winoTransSrcBuf2_3_1_c16_c16(GLOBAL_SIZE_DIM2 __global const FLOAT* uInput, // 0 __global FLOAT* uOutput, __private const int unitWidth, __private const int unitHeight, // 3 __private const int padX, __private const int padY, __private const int srcWidth, // 6 __private const int srcHeight, __private const int srcChannelC4, __private const int srcChannelC16, __private const int dstHeight, __private const int batchOffset, __private const int batch, __private const int input_pad_left, __private const int input_pad_right) { int2 pos = (int2)(get_global_id(0), get_global_id(1)); UNIFORM_BOUNDRY_CHECK(pos.x, pos.y); const int unitWidth_idx = pos.x % unitWidth; const int unitHeight_idx = pos.x / unitWidth; const int sglid = get_sub_group_local_id(); const int pos_y = get_group_id(1); int2 realPos = (int2)(unitWidth_idx, unitHeight_idx); int src_pitch = srcWidth + input_pad_left + input_pad_right; { int sxStart = (realPos.x) * 2 - padX; int syStart = (realPos.y) * 2 - padY; FLOAT4 S[4]; int inp_offset = (((batchOffset * srcChannelC16 + pos_y) * srcHeight + syStart) * src_pitch + sxStart + input_pad_left) * 16; for(int i = 0; i < 4; ++i){ int sy = i + syStart; if(sy < 0 || sy >= srcHeight){ S[i] = (FLOAT4)0; }else{ #ifdef MNN_SUPPORT_FP16 S[i] = as_half4(intel_sub_group_block_read_us4((__global ushort*)(uInput + inp_offset))); #else S[i] = as_float4(intel_sub_group_block_read4((__global uint*)(uInput + inp_offset))); #endif } inp_offset += 16*src_pitch; } FLOAT m00 = +S[0].s0 - S[2].s0; FLOAT m10 = +S[0].s1 - S[2].s1; FLOAT m20 = +S[0].s2 - S[2].s2; FLOAT m30 = +S[0].s3 - S[2].s3; FLOAT m01 = +(FLOAT)0.5f * S[1].s0 + (FLOAT)0.5f * S[2].s0; FLOAT m11 = +(FLOAT)0.5f * S[1].s1 + (FLOAT)0.5f * S[2].s1; FLOAT m21 = +(FLOAT)0.5f * S[1].s2 + (FLOAT)0.5f * S[2].s2; FLOAT m31 = +(FLOAT)0.5f * S[1].s3 + (FLOAT)0.5f * S[2].s3; FLOAT m02 = -(FLOAT)0.5f * S[1].s0 + (FLOAT)0.5f * S[2].s0; FLOAT m12 = -(FLOAT)0.5f * S[1].s1 + (FLOAT)0.5f * S[2].s1; FLOAT m22 = -(FLOAT)0.5f * S[1].s2 + (FLOAT)0.5f * S[2].s2; FLOAT m32 = -(FLOAT)0.5f * S[1].s3 + (FLOAT)0.5f * S[2].s3; FLOAT m03 = -S[1].s0 + S[3].s0; FLOAT m13 = -S[1].s1 + S[3].s1; FLOAT m23 = -S[1].s2 + S[3].s2; FLOAT m33 = -S[1].s3 + S[3].s3; //NC4HW4 [alpha*alpha, srcChannelC16, dstHeight, 16] //index: [0, pos.y / 16, pos.x, 0] int out_offset = (pos_y * dstHeight + pos.x) * 16 + sglid; int batch_offset = srcChannelC16*dstHeight*16; uOutput[out_offset+0*batch_offset] = +m00 - m20; uOutput[out_offset+1*batch_offset] = +(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20; uOutput[out_offset+2*batch_offset] = -(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20; uOutput[out_offset+3*batch_offset] = -m10 + m30; uOutput[out_offset+4*batch_offset] = +m01 - m21; uOutput[out_offset+5*batch_offset] = +(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21; uOutput[out_offset+6*batch_offset] = -(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21; uOutput[out_offset+7*batch_offset] = -m11 + m31; uOutput[out_offset+8*batch_offset] = +m02 - m22; uOutput[out_offset+9*batch_offset] = +(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22; uOutput[out_offset+10*batch_offset] = -(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22; uOutput[out_offset+11*batch_offset] = -m12 + m32; uOutput[out_offset+12*batch_offset] = +m03 - m23; uOutput[out_offset+13*batch_offset] = +(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23; uOutput[out_offset+14*batch_offset] = -(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23; uOutput[out_offset+15*batch_offset] = -m13 + m33; } } __attribute__((intel_reqd_sub_group_size(16))) __kernel void winoTransDstBuf2_3_1_c16_c16(GLOBAL_SIZE_DIM2 __global const FLOAT* uInput, __global const FLOAT* uBias, __global FLOAT* uOutput, __private const int unitWidth, //wUnit __private const int unitHeight, //hUnit __private const int dstWidth, __private const int dstHeight, __private const int dstChannelC4,__private const int dstChannelC16,__private const int srcWidth, __private const int batchOffset, __private const int batch, __private const int output_pad_left, __private const int output_pad_right) { int2 pos = (int2)(get_global_id(0), get_global_id(1)); UNIFORM_BOUNDRY_CHECK(pos.x, pos.y); const int unitWidth_idx = pos.x % unitWidth; const int unitHeight_idx = pos.x / unitWidth; const int sglid = get_sub_group_local_id(); const int pos_y = get_group_id(1); int2 realPos = (int2)(unitWidth_idx, unitHeight_idx); FLOAT bias = uBias[pos.y]; { int oyStart = realPos.y * 2; int oxStart = realPos.x * 2; //NC4HW4 [alpha2, dstChannelC16, wUnit*hUnit, 16] //index: [0, pos.y/4, pos.x, pos.y%4] const int inp_offset = (pos_y * srcWidth + pos.x) * 16 + sglid; const int ic_offset = 16*srcWidth*dstChannelC16; FLOAT S00 = uInput[inp_offset+ic_offset*0]; FLOAT S10 = uInput[inp_offset+ic_offset*1]; FLOAT S20 = uInput[inp_offset+ic_offset*2]; FLOAT S30 = uInput[inp_offset+ic_offset*3]; FLOAT S01 = uInput[inp_offset+ic_offset*4]; FLOAT S11 = uInput[inp_offset+ic_offset*5]; FLOAT S21 = uInput[inp_offset+ic_offset*6]; FLOAT S31 = uInput[inp_offset+ic_offset*7]; FLOAT S02 = uInput[inp_offset+ic_offset*8]; FLOAT S12 = uInput[inp_offset+ic_offset*9]; FLOAT S22 = uInput[inp_offset+ic_offset*10]; FLOAT S32 = uInput[inp_offset+ic_offset*11]; FLOAT S03 = uInput[inp_offset+ic_offset*12]; FLOAT S13 = uInput[inp_offset+ic_offset*13]; FLOAT S23 = uInput[inp_offset+ic_offset*14]; FLOAT S33 = uInput[inp_offset+ic_offset*15]; FLOAT m00 = +S00 + S01 + S02; FLOAT m10 = +S10 + S11 + S12; FLOAT m20 = +S20 + S21 + S22; FLOAT m30 = +S30 + S31 + S32; FLOAT m01 = +S01 - S02 + S03; FLOAT m11 = +S11 - S12 + S13; FLOAT m21 = +S21 - S22 + S23; FLOAT m31 = +S31 - S32 + S33; //NC4HW4 [batch, dstChannelC4, dstHeight, dstWidth] //index: [batchOffset, pos.y, oyStart, oxStart] int dst_pitch = dstWidth + output_pad_left + output_pad_right; int out_offset = (((batchOffset * dstChannelC16+ pos_y) * dstHeight + oyStart) * dst_pitch + oxStart + output_pad_left)*16 + sglid; { FLOAT2 res = (FLOAT2)(bias + m00 + m10 + m20, bias + m10 - m20 + m30); #ifdef RELU res = max(res, (FLOAT2)0); #endif #ifdef RELU6 res = clamp(res, (FLOAT2)0, (FLOAT2)6); #endif #if OUTPUT_LEFTOVERS uOutput[out_offset] = res.x; if(oxStart + 1< dstWidth){ uOutput[out_offset + 16] = res.y; } #else #ifdef MNN_SUPPORT_FP16 intel_sub_group_block_write_us2((__global ushort*)(uOutput + out_offset), as_ushort2(res)); #else intel_sub_group_block_write2((__global uint*)(uOutput + out_offset), as_uint2(res)); #endif #endif //OUTPUT_LEFTOVERS } { int oy = oyStart + 1; if (oy < dstHeight) { FLOAT2 res = (FLOAT2)(bias + m01 + m11 + m21, bias + m11 - m21 + m31); #ifdef RELU res = max(res, (FLOAT2)0); #endif #ifdef RELU6 res = clamp(res, (FLOAT2)0, (FLOAT2)6); #endif #if OUTPUT_LEFTOVERS uOutput[out_offset+16*dst_pitch] = res.x; if(oxStart + 1< dstWidth){ uOutput[out_offset + 16 + 16*dst_pitch] = res.y; } #else #ifdef MNN_SUPPORT_FP16 intel_sub_group_block_write_us2((__global ushort*)(uOutput + out_offset+16*dst_pitch), as_ushort2(res)); #else intel_sub_group_block_write2((__global uint*)(uOutput + out_offset+16*dst_pitch), as_uint2(res)); #endif #endif //OUTPUT_LEFTOVERS } } if(unitWidth_idx == 0){ int pad_offset = (((batchOffset * dstChannelC16+ pos_y) * dstHeight + oyStart) * dst_pitch)*16 + sglid; for(int i = 0; i < output_pad_left; ++i){ uOutput[pad_offset + i * 16] = 0; uOutput[pad_offset + (i + dst_pitch) * 16] = 0; } } if(unitWidth_idx == unitWidth - 1){ int pad_offset = (((batchOffset * dstChannelC16+ pos_y) * dstHeight + oyStart) * dst_pitch + output_pad_left + dstWidth)*16 + sglid; for(int i = 0; i < output_pad_right; ++i){ uOutput[pad_offset + i * 16] = 0; uOutput[pad_offset + (i + dst_pitch) * 16] = 0; } } } } __kernel void winoTransSrcBuf2_3_1_c4_c16(GLOBAL_SIZE_DIM2 __global const FLOAT* uInput, // 0 __global FLOAT* uOutput, __private const int unitWidth, __private const int unitHeight, // 3 __private const int padX, __private const int padY, __private const int srcWidth, // 6 __private const int srcHeight, __private const int srcChannelC4, __private const int srcChannelC16, __private const int dstHeight, __private const int batchOffset, __private const int batch, __private const int input_pad_left, __private const int input_pad_right) { int2 pos = (int2)(get_global_id(0), get_global_id(1)); UNIFORM_BOUNDRY_CHECK(pos.x, pos.y); int unitWidth_idx = pos.x % unitWidth; int unitHeight_idx = pos.x / unitWidth; int2 realPos = (int2)(unitWidth_idx, unitHeight_idx); { int sxStart = (realPos.x) * 2 - padX; int syStart = (realPos.y) * 2 - padY; FLOAT4 S00; FLOAT4 S10; FLOAT4 S20; FLOAT4 S30; FLOAT4 S01; FLOAT4 S11; FLOAT4 S21; FLOAT4 S31; FLOAT4 S02; FLOAT4 S12; FLOAT4 S22; FLOAT4 S32; FLOAT4 S03; FLOAT4 S13; FLOAT4 S23; FLOAT4 S33; int inp_offset = (((batchOffset + pos.y * batch) * srcHeight + syStart) * srcWidth + sxStart) * 4; { int sx = 0 + sxStart; int sy = 0 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S00 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset); } { int sx = 1 + sxStart; int sy = 0 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S10 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4); } { int sx = 2 + sxStart; int sy = 0 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S20 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8); } { int sx = 3 + sxStart; int sy = 0 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S30 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12); } { int sx = 0 + sxStart; int sy = 1 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S01 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth); } { int sx = 1 + sxStart; int sy = 1 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S11 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+4); } { int sx = 2 + sxStart; int sy = 1 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S21 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+8); } { int sx = 3 + sxStart; int sy = 1 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S31 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+12); } { int sx = 0 + sxStart; int sy = 2 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S02 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth); } { int sx = 1 + sxStart; int sy = 2 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S12 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+4); } { int sx = 2 + sxStart; int sy = 2 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S22 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+8); } { int sx = 3 + sxStart; int sy = 2 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S32 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+12); } { int sx = 0 + sxStart; int sy = 3 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S03 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth); } { int sx = 1 + sxStart; int sy = 3 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S13 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+4); } { int sx = 2 + sxStart; int sy = 3 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S23 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+8); } { int sx = 3 + sxStart; int sy = 3 + syStart; bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight); S33 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+12); } FLOAT4 m00 = +S00 - S02; FLOAT4 m10 = +S10 - S12; FLOAT4 m20 = +S20 - S22; FLOAT4 m30 = +S30 - S32; FLOAT4 m01 = +(FLOAT)0.5f * S01 + (FLOAT)0.5f * S02; FLOAT4 m11 = +(FLOAT)0.5f * S11 + (FLOAT)0.5f * S12; FLOAT4 m21 = +(FLOAT)0.5f * S21 + (FLOAT)0.5f * S22; FLOAT4 m31 = +(FLOAT)0.5f * S31 + (FLOAT)0.5f * S32; FLOAT4 m02 = -(FLOAT)0.5f * S01 + (FLOAT)0.5f * S02; FLOAT4 m12 = -(FLOAT)0.5f * S11 + (FLOAT)0.5f * S12; FLOAT4 m22 = -(FLOAT)0.5f * S21 + (FLOAT)0.5f * S22; FLOAT4 m32 = -(FLOAT)0.5f * S31 + (FLOAT)0.5f * S32; FLOAT4 m03 = -S01 + S03; FLOAT4 m13 = -S11 + S13; FLOAT4 m23 = -S21 + S23; FLOAT4 m33 = -S31 + S33; //NC4HW4 [alpha*alpha, srcChannelC16, dstHeight, 16] //index: [0, pos.y / 4, pos.x, pos.y % 4] int out_offset = ((pos.y / 4) * dstHeight + pos.x) * 16 + (pos.y % 4) * 4; int batch_offset = srcChannelC16*dstHeight*16; vstore4(+m00 - m20, 0, uOutput+out_offset+0*batch_offset); vstore4(+(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20, 0, uOutput+out_offset+1*batch_offset); vstore4(-(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20, 0, uOutput+out_offset+2*batch_offset); vstore4(-m10 + m30, 0, uOutput+out_offset+3*batch_offset); vstore4(+m01 - m21, 0, uOutput+out_offset+4*batch_offset); vstore4(+(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21, 0, uOutput+out_offset+5*batch_offset); vstore4(-(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21, 0, uOutput+out_offset+6*batch_offset); vstore4(-m11 + m31, 0, uOutput+out_offset+7*batch_offset); vstore4(+m02 - m22, 0, uOutput+out_offset+8*batch_offset); vstore4(+(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22, 0, uOutput+out_offset+9*batch_offset); vstore4(-(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22, 0, uOutput+out_offset+10*batch_offset); vstore4(-m12 + m32, 0, uOutput+out_offset+11*batch_offset); vstore4(+m03 - m23, 0, uOutput+out_offset+12*batch_offset); vstore4(+(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23, 0, uOutput+out_offset+13*batch_offset); vstore4(-(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23, 0, uOutput+out_offset+14*batch_offset); vstore4(-m13 + m33, 0, uOutput+out_offset+15*batch_offset); } } __kernel void winoTransDstBuf2_3_1_c16_c4(GLOBAL_SIZE_DIM2 __global const FLOAT* uInput, __global const FLOAT* uBias, __global FLOAT* uOutput, __private const int unitWidth, //wUnit __private const int unitHeight, //hUnit __private const int dstWidth, __private const int dstHeight, __private const int dstChannelC4,__private const int dstChannelC16,__private const int srcWidth, __private const int batchOffset, __private const int batch, __private const int output_pad_left, __private const int output_pad_right) { int2 pos = (int2)(get_global_id(0), get_global_id(1)); UNIFORM_BOUNDRY_CHECK(pos.x, pos.y); int unitWidth_idx = pos.x % unitWidth; int unitHeight_idx = pos.x / unitWidth; int2 realPos = (int2)(unitWidth_idx, unitHeight_idx); FLOAT4 bias = vload4(0, uBias+pos.y*4); { int oyStart = realPos.y * 2; int oxStart = realPos.x * 2; //NC4HW4 [alpha2, dstChannelC16, wUnit*hUnit, 16] //index: [0, pos.y/4, pos.x, pos.y%4] const int inp_offset = ((pos.y / 4) * srcWidth + pos.x) * 16 + (pos.y % 4) * 4; const int ic_offset = 16*srcWidth*dstChannelC16; FLOAT4 S00 = vload4(0, uInput+inp_offset+ic_offset*0); FLOAT4 S10 = vload4(0, uInput+inp_offset+ic_offset*1); FLOAT4 S20 = vload4(0, uInput+inp_offset+ic_offset*2); FLOAT4 S30 = vload4(0, uInput+inp_offset+ic_offset*3); FLOAT4 S01 = vload4(0, uInput+inp_offset+ic_offset*4); FLOAT4 S11 = vload4(0, uInput+inp_offset+ic_offset*5); FLOAT4 S21 = vload4(0, uInput+inp_offset+ic_offset*6); FLOAT4 S31 = vload4(0, uInput+inp_offset+ic_offset*7); FLOAT4 S02 = vload4(0, uInput+inp_offset+ic_offset*8); FLOAT4 S12 = vload4(0, uInput+inp_offset+ic_offset*9); FLOAT4 S22 = vload4(0, uInput+inp_offset+ic_offset*10); FLOAT4 S32 = vload4(0, uInput+inp_offset+ic_offset*11); FLOAT4 S03 = vload4(0, uInput+inp_offset+ic_offset*12); FLOAT4 S13 = vload4(0, uInput+inp_offset+ic_offset*13); FLOAT4 S23 = vload4(0, uInput+inp_offset+ic_offset*14); FLOAT4 S33 = vload4(0, uInput+inp_offset+ic_offset*15); FLOAT4 m00 = +S00 + S01 + S02; FLOAT4 m10 = +S10 + S11 + S12; FLOAT4 m20 = +S20 + S21 + S22; FLOAT4 m30 = +S30 + S31 + S32; FLOAT4 m01 = +S01 - S02 + S03; FLOAT4 m11 = +S11 - S12 + S13; FLOAT4 m21 = +S21 - S22 + S23; FLOAT4 m31 = +S31 - S32 + S33; //NC4HW4 [batch, dstChannelC4, dstHeight, dstWidth] //index: [batchOffset, pos.y, oyStart, oxStart] int out_offset = (((batchOffset+ pos.y * batch) * dstHeight + oyStart) * dstWidth + oxStart)*4; { int ox = oxStart + 0; int oy = oyStart + 0; if (ox < dstWidth && oy < dstHeight) { FLOAT4 res = bias + m00 + m10 + m20; #ifdef RELU res = max(res, (FLOAT4)(0)); #endif #ifdef RELU6 res = clamp(res, (FLOAT4)(0), (FLOAT4)(6)); #endif vstore4(res, 0, uOutput+out_offset); } } { int ox = oxStart + 1; int oy = oyStart + 0; if (ox < dstWidth && oy < dstHeight) { FLOAT4 res = bias + m10 - m20 + m30; #ifdef RELU res = max(res, (FLOAT4)(0)); #endif #ifdef RELU6 res = clamp(res, (FLOAT4)(0), (FLOAT4)(6)); #endif vstore4(res, 0, uOutput+out_offset+4); } } { int ox = oxStart + 0; int oy = oyStart + 1; if (ox < dstWidth && oy < dstHeight) { FLOAT4 res = bias + m01 + m11 + m21; #ifdef RELU res = max(res, (FLOAT4)(0)); #endif #ifdef RELU6 res = clamp(res, (FLOAT4)(0), (FLOAT4)(6)); #endif vstore4(res, 0, uOutput+out_offset+4*dstWidth); } } { int ox = oxStart + 1; int oy = oyStart + 1; if (ox < dstWidth && oy < dstHeight) { FLOAT4 res = bias + m11 - m21 + m31; #ifdef RELU res = max(res, (FLOAT4)(0)); #endif #ifdef RELU6 res = clamp(res, (FLOAT4)(0), (FLOAT4)(6)); #endif vstore4(res, 0, uOutput+out_offset+4*dstWidth+4); } } } } __attribute__((intel_reqd_sub_group_size(16))) __kernel void gemm_buf_intel(__global const FLOAT* input0, __global const FLOAT* input1, __global FLOAT* output, __private const int width,//ROUND_UP(wUnit*hUnit, 8) __private const int height,//dstChannelC16 __private const int srcChannelC16, __private const int alpha2) { int3 pos = (int3)(get_global_id(0), get_group_id(1), get_global_id(2)); const int sglid = get_sub_group_local_id(); const int pos_x = pos.x << 3; const int pos_y = pos.y; FLOAT8 o = (FLOAT8)(0); const int kernel_base = mul24(mul24(mad24(pos.z, height, pos_y), srcChannelC16), 256); const int inp_base = mul24(mad24(mul24(pos.z, srcChannelC16), width, pos_x), 16); for(int k = 0; k < srcChannelC16; ++k){ #ifdef MNN_SUPPORT_FP16 FLOAT8 wei0 = as_half8(intel_sub_group_block_read_us8((__global ushort*)(input1 + kernel_base + k * 256))); FLOAT8 wei1 = as_half8(intel_sub_group_block_read_us8((__global ushort*)(input1 + kernel_base + k * 256 + 8 * 16))); FLOAT8 s = as_half8(intel_sub_group_block_read_us8((__global ushort*)(input0 + inp_base + k * width * 16))); o = mad(wei0.s0, as_half8(intel_sub_group_shuffle(as_ushort8(s), 0)), o); o = mad(wei0.s1, as_half8(intel_sub_group_shuffle(as_ushort8(s), 1)), o); o = mad(wei0.s2, as_half8(intel_sub_group_shuffle(as_ushort8(s), 2)), o); o = mad(wei0.s3, as_half8(intel_sub_group_shuffle(as_ushort8(s), 3)), o); o = mad(wei0.s4, as_half8(intel_sub_group_shuffle(as_ushort8(s), 4)), o); o = mad(wei0.s5, as_half8(intel_sub_group_shuffle(as_ushort8(s), 5)), o); o = mad(wei0.s6, as_half8(intel_sub_group_shuffle(as_ushort8(s), 6)), o); o = mad(wei0.s7, as_half8(intel_sub_group_shuffle(as_ushort8(s), 7)), o); o = mad(wei1.s0, as_half8(intel_sub_group_shuffle(as_ushort8(s), 8)), o); o = mad(wei1.s1, as_half8(intel_sub_group_shuffle(as_ushort8(s), 9)), o); o = mad(wei1.s2, as_half8(intel_sub_group_shuffle(as_ushort8(s), 10)), o); o = mad(wei1.s3, as_half8(intel_sub_group_shuffle(as_ushort8(s), 11)), o); o = mad(wei1.s4, as_half8(intel_sub_group_shuffle(as_ushort8(s), 12)), o); o = mad(wei1.s5, as_half8(intel_sub_group_shuffle(as_ushort8(s), 13)), o); o = mad(wei1.s6, as_half8(intel_sub_group_shuffle(as_ushort8(s), 14)), o); o = mad(wei1.s7, as_half8(intel_sub_group_shuffle(as_ushort8(s), 15)), o); #else FLOAT8 wei0 = as_float8(intel_sub_group_block_read8((__global uint*)(input1 + kernel_base + k * 256))); FLOAT8 wei1 = as_float8(intel_sub_group_block_read8((__global uint*)(input1 + kernel_base + k * 256 + 8 * 16))); FLOAT8 s = as_float8(intel_sub_group_block_read8((__global uint*)(input0 + inp_base + k * width * 16))); o = mad(wei0.s0, intel_sub_group_shuffle(s, 0), o); o = mad(wei0.s1, intel_sub_group_shuffle(s, 1), o); o = mad(wei0.s2, intel_sub_group_shuffle(s, 2), o); o = mad(wei0.s3, intel_sub_group_shuffle(s, 3), o); o = mad(wei0.s4, intel_sub_group_shuffle(s, 4), o); o = mad(wei0.s5, intel_sub_group_shuffle(s, 5), o); o = mad(wei0.s6, intel_sub_group_shuffle(s, 6), o); o = mad(wei0.s7, intel_sub_group_shuffle(s, 7), o); o = mad(wei1.s0, intel_sub_group_shuffle(s, 8), o); o = mad(wei1.s1, intel_sub_group_shuffle(s, 9), o); o = mad(wei1.s2, intel_sub_group_shuffle(s, 10), o); o = mad(wei1.s3, intel_sub_group_shuffle(s, 11), o); o = mad(wei1.s4, intel_sub_group_shuffle(s, 12), o); o = mad(wei1.s5, intel_sub_group_shuffle(s, 13), o); o = mad(wei1.s6, intel_sub_group_shuffle(s, 14), o); o = mad(wei1.s7, intel_sub_group_shuffle(s, 15), o); #endif } int out_offset = mul24(mad24(mad24(pos.z, height, pos_y), width, pos_x), 16); #ifdef MNN_SUPPORT_FP16 intel_sub_group_block_write_us8((__global ushort*)(output + out_offset), as_ushort8(o)); #else intel_sub_group_block_write8((__global uint*)(output + out_offset), as_uint8(o)); #endif }