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

919 lines
46 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "opencl_source_map.hpp"
namespace MNN {
#ifndef MNN_OPENCL_BUFFER_CLOSED
const char* attention_buf =
"#ifdef MNN_SUPPORT_FP16\n"
"#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n"
"#endif\n"
"#define GLOBAL_SIZE_3_DIMS "" __private const int global_size_dim0,__private const int global_size_dim1,__private const int global_size_dim2,\n"
"#define DEAL_NON_UNIFORM_DIM3(input1, input2, input3) "" if (input1 >= global_size_dim0 || input2 >= global_size_dim1 || input3 >= global_size_dim2) { "" return; "" }\n"
"#define GLOBAL_SIZE_2_DIMS "" __private const int global_size_dim0,__private const int global_size_dim1,\n"
"#define DEAL_NON_UNIFORM_DIM2(input1, input2) "" if (input1 >= global_size_dim0 || input2 >= global_size_dim1) { "" return; "" }\n"
"#define DEAL_OUTER_SEQLEN_NOT_ALIGN(length) "" if(4 * sl + 3 >= length) {"" temp_3 = (FLOAT4)0;"" }"" if(4 * sl + 2 >= length) {"" temp_2 = (FLOAT4)0;"" }"" if(4 * sl + 1 >= length) {"" temp_1 = (FLOAT4)0;"" }\n"
"#define DEAL_INNER_HEADDIM_NOT_ALIGN(length) "" if(hd * 4 + 3 >= length) {"" temp_0.w = (FLOAT)0;"" temp_1.w = (FLOAT)0;"" temp_2.w = (FLOAT)0;"" temp_3.w = (FLOAT)0;"" }"" if(hd * 4 + 2 >= length) {"" temp_0.z = (FLOAT)0;"" temp_1.z = (FLOAT)0;"" temp_2.z = (FLOAT)0;"" temp_3.z = (FLOAT)0;"" }"" if(hd * 4 + 1 >= length) {"" temp_0.y = (FLOAT)0;"" temp_1.y = (FLOAT)0;"" temp_2.y = (FLOAT)0;"" temp_3.y = (FLOAT)0;"" }\n"
"#ifdef VALUE_C4\n"
"static inline FLOAT load_c4_value(__global const FLOAT* value,\n"
" const int seq_storage,\n"
" const int token,\n"
" const int channel) {\n"
" return value[((channel >> 2)*seq_storage+token)*4+(channel & 3)];\n"
"}\n"
"static inline FLOAT4 load_c4_value4(__global const FLOAT* value,\n"
" const int seq_storage,\n"
" const int token,\n"
" const int channel,\n"
" const int head_dim_offset,\n"
" const int head_dim) {\n"
" return (FLOAT4)(\n"
" load_c4_value(value,seq_storage,token,channel),\n"
" (head_dim_offset+1 >= head_dim) ? (FLOAT)0 : load_c4_value(value,seq_storage,token,channel+1),\n"
" (head_dim_offset+2 >= head_dim) ? (FLOAT)0 : load_c4_value(value,seq_storage,token,channel+2),\n"
" (head_dim_offset+3 >= head_dim) ? (FLOAT)0 : load_c4_value(value,seq_storage,token,channel+3));\n"
"}\n"
"#endif\n"
"__kernel void rearrange_qkv(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *input_q,//[batch,seqLenQ/4,headNum,headDim,seqLenQ_4]\n"
" __global const FLOAT *input_k,// [batch,seqLenKV/4,headNum/group,headDim,seqLenKV_4]\n"
" __global const FLOAT *input_v,// [batch,seqLenKV/4,headNum/group,headDim,seqLenKV_4]\n"
" __global FLOAT *output_q,// [batch*headNum,ROUND_UP(headDim,mTileHDK),ROUND_UP(seqLenQ,mTileQ)]\n"
" __global FLOAT *output_k,// [batch*headNum/group,ROUND_UP(headDim,mTileHDK),ROUND_UP(seqLenKV,mTileKV)]\n"
" __global FLOAT *output_v,// [batch*headNum/group,ROUND_UP(seqLenKV,mTileKV),ROUND_UP(headDim,mTileHDN)]\n"
" #ifdef SAVE_KV\n"
" __global FLOAT *past_k,// [batch,headNum/group,headDim,seqLenKV_4]\n"
" __global FLOAT *past_v,// [batch,headNum/group,seqLenKV_4,headDim]\n"
" #endif\n"
" __private const int4 tile,// [mTileQ,mTileKV,mTileHDK,mTileHDN]\n"
" __private const int4 shape,// [seqLenQ,seqLenKV,headNum,headDim]\n"
" __private const int4 param,// [group,batch,max_len,past_len]\n"
" __private const int maxLenKV\n"
") {\n"
" const int sl=get_global_id(0); // seqLen/4 : max(seqLenPackQ/4,seqLenPackKV/4)\n"
" const int hd=get_global_id(1); // headDim/4 : max(headDimPackQK/4,headDimPackV/4)\n"
" const int z=get_global_id(2); // batch*headNum\n"
" DEAL_NON_UNIFORM_DIM3(sl,hd,z);\n"
" \n"
" const int seqLenQ=shape.x;\n"
" const int seqLenKV=shape.y;\n"
" const int headNum=shape.z;\n"
" const int headDim=shape.w;\n"
" const int group=param.x;\n"
" const int batch=param.y;\n"
" const int b=z % batch;\n"
" const int hn=z/batch;\n"
" \n"
" const int seqLenQ_4=(seqLenQ+3)/4;\n"
" //const int in_offset_q=(((b*seqLenQ_4+sl)*headNum+hn)*headDim+4*hd)*4;\n"
" const int in_offset_q=(((b*seqLenQ+sl*4)*headNum+hn)*headDim+4*hd);\n"
" const int seqLenPackQ=((seqLenQ+tile.x-1)/tile.x)*tile.x;\n"
" const int headDimPackQK=((headDim+tile.z-1)/tile.z)*tile.z;\n"
" const int out_offset_q=(((b*headNum+hn)*headDimPackQK+hd*4)*seqLenPackQ+sl*4);\n"
" \n"
" if(sl*4<seqLenPackQ && hd*4<headDimPackQK) {\n"
" if(sl*4 >= seqLenQ || hd*4 >= headDim) {\n"
" vstore4((FLOAT4)0,0,output_q+out_offset_q);\n"
" vstore4((FLOAT4)0,0,output_q+out_offset_q+seqLenPackQ);\n"
" vstore4((FLOAT4)0,0,output_q+out_offset_q+2*seqLenPackQ);\n"
" vstore4((FLOAT4)0,0,output_q+out_offset_q+3*seqLenPackQ);\n"
" } else {\n"
" FLOAT4 temp_0=vload4(0,input_q+in_offset_q);\n"
" FLOAT4 temp_1=(sl*4+1 >= seqLenQ) ? (FLOAT4)0 : vload4(0,input_q+in_offset_q+headNum*headDim);\n"
" FLOAT4 temp_2=(sl*4+2 >= seqLenQ) ? (FLOAT4)0 : vload4(0,input_q+in_offset_q+2*headNum*headDim);\n"
" FLOAT4 temp_3=(sl*4+3 >= seqLenQ) ? (FLOAT4)0 : vload4(0,input_q+in_offset_q+3*headNum*headDim);\n"
" #ifdef HEADDIM_LEAVE\n"
" DEAL_INNER_HEADDIM_NOT_ALIGN(headDim)\n"
" #endif\n"
" #ifdef SEQLEN_LEAVE\n"
" DEAL_OUTER_SEQLEN_NOT_ALIGN(seqLenQ)\n"
" #endif\n"
" vstore4((FLOAT4)(temp_0.s0,temp_1.s0,temp_2.s0,temp_3.s0),0,output_q+out_offset_q);\n"
" vstore4((FLOAT4)(temp_0.s1,temp_1.s1,temp_2.s1,temp_3.s1),0,output_q+out_offset_q+seqLenPackQ);\n"
" vstore4((FLOAT4)(temp_0.s2,temp_1.s2,temp_2.s2,temp_3.s2),0,output_q+out_offset_q+2*seqLenPackQ);\n"
" vstore4((FLOAT4)(temp_0.s3,temp_1.s3,temp_2.s3,temp_3.s3),0,output_q+out_offset_q+3*seqLenPackQ);\n"
" }\n"
" }\n"
" \n"
" if(hn >= headNum/group) {\n"
" return;\n"
" }\n"
" \n"
" const int seqLenPackKV=((seqLenKV+tile.y-1)/tile.y)*tile.y;\n"
" const int headDimPackV=((headDim+tile.w-1)/tile.w)*tile.w;\n"
" const int seqLenKV_4=(seqLenKV+3)/4;\n"
" const int in_offset_kv=(((b*seqLenKV+sl*4)*headNum/group+hn)*headDim+4*hd);\n"
" const int past_offset_k=(((b*headNum/group+hn)*headDim+hd*4)*maxLenKV+sl*4);\n"
" const int past_offset_v=(((b*headNum/group+hn)*maxLenKV+sl*4)*headDim+4*hd);\n"
" if(sl*4<seqLenPackKV && hd*4<headDimPackQK) {\n"
" const int out_offset_k=(((b*headNum/group+hn)*headDimPackQK+hd*4)*seqLenPackKV+sl*4);\n"
" if(sl*4 >= seqLenKV || hd*4 >= headDim) {\n"
" vstore4((FLOAT4)0,0,output_k+out_offset_k);\n"
" vstore4((FLOAT4)0,0,output_k+out_offset_k+seqLenPackKV);\n"
" vstore4((FLOAT4)0,0,output_k+out_offset_k+2*seqLenPackKV);\n"
" vstore4((FLOAT4)0,0,output_k+out_offset_k+3*seqLenPackKV);\n"
" } else {\n"
" FLOAT4 temp_0=vload4(0,input_k+in_offset_kv);\n"
" FLOAT4 temp_1=(sl*4+1 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_k+in_offset_kv+headNum*headDim/group);\n"
" FLOAT4 temp_2=(sl*4+2 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_k+in_offset_kv+2*headNum*headDim/group);\n"
" FLOAT4 temp_3=(sl*4+3 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_k+in_offset_kv+3*headNum*headDim/group);\n"
" #ifdef HEADDIM_LEAVE\n"
" DEAL_INNER_HEADDIM_NOT_ALIGN(headDim)\n"
" #endif\n"
" #ifdef SEQLEN_LEAVE\n"
" DEAL_OUTER_SEQLEN_NOT_ALIGN(seqLenKV)\n"
" #endif\n"
" FLOAT4 key0=(FLOAT4)(temp_0.s0,temp_1.s0,temp_2.s0,temp_3.s0);\n"
" FLOAT4 key1=(FLOAT4)(temp_0.s1,temp_1.s1,temp_2.s1,temp_3.s1);\n"
" FLOAT4 key2=(FLOAT4)(temp_0.s2,temp_1.s2,temp_2.s2,temp_3.s2);\n"
" FLOAT4 key3=(FLOAT4)(temp_0.s3,temp_1.s3,temp_2.s3,temp_3.s3);\n"
" vstore4(key0,0,output_k+out_offset_k);\n"
" vstore4(key1,0,output_k+out_offset_k+seqLenPackKV);\n"
" vstore4(key2,0,output_k+out_offset_k+2*seqLenPackKV);\n"
" vstore4(key3,0,output_k+out_offset_k+3*seqLenPackKV);\n"
" \n"
" // pastK\n"
" #ifdef SAVE_KV\n"
" vstore4(key0,0,past_k+past_offset_k);\n"
" vstore4(key1,0,past_k+past_offset_k+maxLenKV);\n"
" vstore4(key2,0,past_k+past_offset_k+2*maxLenKV);\n"
" vstore4(key3,0,past_k+past_offset_k+3*maxLenKV);\n"
" #endif\n"
" }\n"
" \n"
" }\n"
" \n"
" if(sl*4<seqLenPackKV && hd*4<headDimPackV) {\n"
" const int out_offset_v=(((b*headNum/group+hn)*seqLenPackKV+sl*4)*headDimPackV+hd*4);\n"
" if(sl*4 >= seqLenKV || hd*4 >= headDim) {\n"
" vstore4((FLOAT4)0,0,output_v+out_offset_v);\n"
" vstore4((FLOAT4)0,0,output_v+out_offset_v+headDimPackV);\n"
" vstore4((FLOAT4)0,0,output_v+out_offset_v+2*headDimPackV);\n"
" vstore4((FLOAT4)0,0,output_v+out_offset_v+3*headDimPackV);\n"
" } else {\n"
" #ifdef VALUE_C4\n"
" const int value_seq_storage=batch*seqLenKV;\n"
" const int value_channel=hn*headDim+4*hd;\n"
" const int value_token=b*seqLenKV+sl*4;\n"
" FLOAT4 temp_0=load_c4_value4(input_v,value_seq_storage,value_token,value_channel,4*hd,headDim);\n"
" FLOAT4 temp_1=(sl*4+1 >= seqLenKV) ? (FLOAT4)0 :\n"
" load_c4_value4(input_v,value_seq_storage,value_token+1,value_channel,4*hd,headDim);\n"
" FLOAT4 temp_2=(sl*4+2 >= seqLenKV) ? (FLOAT4)0 :\n"
" load_c4_value4(input_v,value_seq_storage,value_token+2,value_channel,4*hd,headDim);\n"
" FLOAT4 temp_3=(sl*4+3 >= seqLenKV) ? (FLOAT4)0 :\n"
" load_c4_value4(input_v,value_seq_storage,value_token+3,value_channel,4*hd,headDim);\n"
" #else\n"
" FLOAT4 temp_0=vload4(0,input_v+in_offset_kv);\n"
" FLOAT4 temp_1=(sl*4+1 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_v+in_offset_kv+headNum*headDim/group);\n"
" FLOAT4 temp_2=(sl*4+2 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_v+in_offset_kv+2*headNum*headDim/group);\n"
" FLOAT4 temp_3=(sl*4+3 >= seqLenKV) ? (FLOAT4)0 : vload4(0,input_v+in_offset_kv+3*headNum*headDim/group);\n"
" #endif\n"
" #ifdef HEADDIM_LEAVE\n"
" DEAL_INNER_HEADDIM_NOT_ALIGN(headDim)\n"
" #endif\n"
" #ifdef SEQLEN_LEAVE\n"
" DEAL_OUTER_SEQLEN_NOT_ALIGN(seqLenKV)\n"
" #endif\n"
" vstore4(temp_0,0,output_v+out_offset_v);\n"
" vstore4(temp_1,0,output_v+out_offset_v+headDimPackV);\n"
" vstore4(temp_2,0,output_v+out_offset_v+2*headDimPackV);\n"
" vstore4(temp_3,0,output_v+out_offset_v+3*headDimPackV);\n"
" \n"
" // pastV\n"
" #ifdef SAVE_KV\n"
" vstore4(temp_0,0,past_v+past_offset_v);\n"
" vstore4(temp_1,0,past_v+past_offset_v+headDim);\n"
" vstore4(temp_2,0,past_v+past_offset_v+2*headDim);\n"
" vstore4(temp_3,0,past_v+past_offset_v+3*headDim);\n"
" #endif\n"
" }\n"
" \n"
" }\n"
"}\n"
"#ifndef MASK_DTYPE\n"
"#define MASK_DTYPE FLOAT\n"
"#define MASK_DTYPE4 FLOAT4\n"
"#endif\n"
"__kernel void rearrange_mask(GLOBAL_SIZE_3_DIMS\n"
" __global const MASK_DTYPE *input_mask,// [batch,1,seqLenQ,seqLenKV,4]\n"
" __global MASK_DTYPE *output_mask,// [batch,ROUND_UP(seqLenQ,mTileQ),ROUND_UP(seqLenKV,mTileKV)]\n"
" const int4 shape // [seqLenQ,seqLenKV,mTileQ,mTileKV]\n"
") {\n"
" const int sl=get_global_id(0); // seqLen_4\n"
" const int sl_kv=get_global_id(1); // seqLenKV_4\n"
" const int b=get_global_id(2); // Batch\n"
" DEAL_NON_UNIFORM_DIM3(sl,sl_kv,b);\n"
" \n"
" const int seq_len_pack=((shape.x+shape.z-1)/shape.z)*shape.z;\n"
" const int seq_len_kv_pack=((shape.y+shape.w-1)/shape.w)*shape.w;\n"
" int in_offset=((b*shape.x+sl*4)*shape.y+sl_kv*4);\n"
" int out_offset=(b*seq_len_pack+sl*4)*seq_len_kv_pack+sl_kv*4;\n"
" if(sl*4 >= shape.x || sl_kv*4 >= shape.y) {\n"
" vstore4((MASK_DTYPE4)0,0,output_mask+out_offset);\n"
" vstore4((MASK_DTYPE4)0,0,output_mask+out_offset+seq_len_kv_pack);\n"
" vstore4((MASK_DTYPE4)0,0,output_mask+out_offset+seq_len_kv_pack*2);\n"
" vstore4((MASK_DTYPE4)0,0,output_mask+out_offset+seq_len_kv_pack*3);\n"
" } else {\n"
" int y_down_align4=(shape.y/4*4);\n"
" MASK_DTYPE4 temp_0,temp_1,temp_2,temp_3;\n"
" \n"
" if(sl_kv*4<y_down_align4) {\n"
" temp_0=vload4(0,input_mask+in_offset);\n"
" temp_1=(sl*4+1 >= shape.x) ? (MASK_DTYPE4)0 : vload4(0,input_mask+in_offset+shape.y);\n"
" temp_2=(sl*4+2 >= shape.x) ? (MASK_DTYPE4)0 : vload4(0,input_mask+in_offset+shape.y*2);\n"
" temp_3=(sl*4+3 >= shape.x) ? (MASK_DTYPE4)0 : vload4(0,input_mask+in_offset+shape.y*3);\n"
" } else if(sl_kv*4+1 == shape.y){\n"
" temp_0=(MASK_DTYPE4)(input_mask[in_offset],0,0,0);\n"
" temp_1=(sl*4+1 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y],0,0,0);//vload4(0,input_mask+in_offset+shape.y);\n"
" temp_2=(sl*4+2 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*2],0,0,0);//vload4(0,input_mask+in_offset+shape.y*2);\n"
" temp_3=(sl*4+3 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*3],0,0,0);//vload4(0,input_mask+in_offset+shape.y*3);\n"
" } else if(sl_kv*4+2 == shape.y){\n"
" temp_0=(MASK_DTYPE4)(input_mask[in_offset],input_mask[in_offset+1],0,0);\n"
" temp_1=(sl*4+1 >= shape.x) ? (MASK_DTYPE4)0 : (FLOAT4)(input_mask[in_offset+shape.y],input_mask[in_offset+shape.y+1],0,0);//vload4(0,input_mask+in_offset+shape.y);\n"
" temp_2=(sl*4+2 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*2],input_mask[in_offset+shape.y*2+1],0,0);//vload4(0,input_mask+in_offset+shape.y*2);\n"
" temp_3=(sl*4+3 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*3],input_mask[in_offset+shape.y*3+1],0,0);//vload4(0,input_mask+in_offset+shape.y*3);\n"
" } else if(sl_kv*4+3 == shape.y){\n"
" temp_0=(MASK_DTYPE4)(input_mask[in_offset],input_mask[in_offset+1],input_mask[in_offset+2],0);\n"
" temp_1=(sl*4+1 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y],input_mask[in_offset+shape.y+1],input_mask[in_offset+shape.y+2],0);//vload4(0,input_mask+in_offset+shape.y);\n"
" temp_2=(sl*4+2 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*2],input_mask[in_offset+shape.y*2+1],input_mask[in_offset+shape.y*2+2],0);//vload4(0,input_mask+in_offset+shape.y*2);\n"
" temp_3=(sl*4+3 >= shape.x) ? (MASK_DTYPE4)0 : (MASK_DTYPE4)(input_mask[in_offset+shape.y*3],input_mask[in_offset+shape.y*3+1],input_mask[in_offset+shape.y*3+2],0);//vload4(0,input_mask+in_offset+shape.y*3);\n"
" }\n"
" vstore4(temp_0,0,output_mask+out_offset);\n"
" vstore4(temp_1,0,output_mask+out_offset+seq_len_kv_pack);\n"
" vstore4(temp_2,0,output_mask+out_offset+2*seq_len_kv_pack);\n"
" vstore4(temp_3,0,output_mask+out_offset+3*seq_len_kv_pack);\n"
" }\n"
"}\n"
"__kernel void qkv_transpose_output(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *input,// [Batch*mNumHead,ROUND_UP(mHeadDim,mTileHDN),ROUND_UP(seqLen,mTileQ)]\n"
" __global FLOAT *output,// [Batch,seqLen/4,mNumHead mHeadDim,4] (or NC4HW4 when ATTENTION_C4)\n"
" __private const int tile_q,\n"
" __private const int tile_hdn,\n"
" __private const int seq_len,\n"
" __private const int head_num,\n"
" __private const int head_dim,\n"
" __private const int batch\n"
") {\n"
" const int sl=get_global_id(0); // seqLen_4\n"
" const int hd=get_global_id(1); // mHeadDim_4\n"
" const int z=get_global_id(2); // Batch*mNumHead\n"
" DEAL_NON_UNIFORM_DIM3(sl,hd,z);\n"
" const int b=z/head_num;\n"
" const int hn=z % head_num;\n"
" const int seq_len_pack=((seq_len+tile_q-1)/tile_q)*tile_q;\n"
" const int head_dim_pack=((head_dim+tile_hdn-1)/tile_hdn)*tile_hdn;\n"
" const int offset_inp=((b*head_num+hn)*head_dim_pack+4*hd)*seq_len_pack+4*sl;\n"
" // Q\n"
" FLOAT4 temp_0=vload4(0,input+offset_inp);\n"
" FLOAT4 temp_1=vload4(0,input+offset_inp+seq_len_pack);\n"
" FLOAT4 temp_2=vload4(0,input+offset_inp+2*seq_len_pack);\n"
" FLOAT4 temp_3=vload4(0,input+offset_inp+3*seq_len_pack);\n"
"#ifdef ATTENTION_C4\n"
" // output is NC4HW4: [(head_num*head_dim)/4,batch*seq_len,4],channel=hn*head_dim+4*hd.\n"
" // Must match matmul_qkv_prefill's ATTENTION_C4 output layout so o_proj reads it correctly.\n"
" const int channel4=(hn*head_dim+4*hd) >> 2;\n"
" const int seq_storage=seq_len*batch;\n"
" const int output_offset=(channel4*seq_storage+(b*seq_len+sl*4))*4;\n"
" vstore4((FLOAT4)(temp_0.s0,temp_1.s0,temp_2.s0,temp_3.s0),0,output+output_offset);\n"
" if(4*sl+1 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s1,temp_1.s1,temp_2.s1,temp_3.s1),0,output+output_offset+4);\n"
" if(4*sl+2 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s2,temp_1.s2,temp_2.s2,temp_3.s2),0,output+output_offset+8);\n"
" if(4*sl+3 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s3,temp_1.s3,temp_2.s3,temp_3.s3),0,output+output_offset+12);\n"
"#else\n"
" const int offset_out=(((b*seq_len+sl*4)*head_num+hn)*head_dim+4*hd);\n"
" vstore4((FLOAT4)(temp_0.s0,temp_1.s0,temp_2.s0,temp_3.s0),0,output+offset_out);\n"
" if(4*sl+1 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s1,temp_1.s1,temp_2.s1,temp_3.s1),0,output+offset_out+head_num*head_dim);\n"
" if(4*sl+2 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s2,temp_1.s2,temp_2.s2,temp_3.s2),0,output+offset_out+2*head_num*head_dim);\n"
" if(4*sl+3 >= seq_len) return;\n"
" vstore4((FLOAT4)(temp_0.s3,temp_1.s3,temp_2.s3,temp_3.s3),0,output+offset_out+3*head_num*head_dim);\n"
"#endif\n"
"}\n"
"#ifndef NUMHEAD_GROUP_SIZE\n"
"#define NUMHEAD_GROUP_SIZE 1\n"
"#endif\n"
"__kernel void rearrange_q(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *query,// [batch query_seq_len head_num head_dim]\n"
" __global FLOAT *query_tmp,// [batch head_num head_dim_4 query_seq_len_4]\n"
" __private const int seq_len,\n"
" __private const int head_dim,\n"
" __private const int head_num) {\n"
" /*\n"
" the kernel assume head_dim is multiple of 4.\n"
" */\n"
" const int x=get_global_id(0); // query_seq_len/4\n"
" const int y=get_global_id(1); // head_dim/4\n"
" int z=get_global_id(2);\n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" \n"
" const int b=z/head_num;// batch\n"
" z=z % head_num;// head_num\n"
" \n"
" const int x4=x << 2;\n"
" const int y4=y << 2;\n"
" const int seq_len4=(seq_len+3)/4*4;;\n"
" const int stride=head_num*head_dim;\n"
" int query_offset=((b*seq_len+x4)*head_num+z)*head_dim+y4;\n"
" FLOAT4 query_vec0=vload4(0,query+query_offset); query_offset += stride;\n"
" FLOAT4 query_vec1=(x4+1 >= seq_len) ? (FLOAT4)0 : vload4(0,query+query_offset); query_offset += stride;\n"
" FLOAT4 query_vec2=(x4+2 >= seq_len) ? (FLOAT4)0 : vload4(0,query+query_offset); query_offset += stride;\n"
" FLOAT4 query_vec3=(x4+3 >= seq_len) ? (FLOAT4)0 : vload4(0,query+query_offset);\n"
" \n"
" const int queryout_offset=((b*head_num+z)*head_dim+y4)*seq_len4+x4;\n"
" vstore4((FLOAT4)(query_vec0.s0,query_vec1.s0,query_vec2.s0,query_vec3.s0),0,query_tmp+queryout_offset);\n"
" vstore4((FLOAT4)(query_vec0.s1,query_vec1.s1,query_vec2.s1,query_vec3.s1),0,query_tmp+queryout_offset+seq_len4);\n"
" vstore4((FLOAT4)(query_vec0.s2,query_vec1.s2,query_vec2.s2,query_vec3.s2),0,query_tmp+queryout_offset+seq_len4+seq_len4);\n"
" vstore4((FLOAT4)(query_vec0.s3,query_vec1.s3,query_vec2.s3,query_vec3.s3),0,query_tmp+queryout_offset+seq_len4+seq_len4+seq_len4);\n"
"}\n"
"__kernel void rearrange_k(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *key,// [batch key_seq_len kv_head_num head_dim]\n"
" __global FLOAT *past_key,// [batch kv_head_num head_dim max_length]\n"
" __private const int past_len,// prefill=0,decode=past_key len\n"
" __private const int max_len,\n"
" __private const int seq_len,\n"
" __private const int kv_head_num,\n"
" __private const int head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // seq_len decode=1\n"
" const int y=get_global_id(1); // head_dim\n"
" int z=get_global_id(2); //\n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" \n"
" const int b=z/kv_head_num;\n"
" z=z % kv_head_num;\n"
" const int y4=y << 2;\n"
" \n"
"#ifdef OPENCL_PREFILL_ATTENTION\n"
" const int x4=x << 2;\n"
" const int stride=kv_head_num*head_dim;\n"
" int key_offset=((b*seq_len+x4)*kv_head_num+z)*head_dim+y4;\n"
" FLOAT4 key_vec0=vload4(0,key+key_offset); key_offset += stride;\n"
" FLOAT4 key_vec1=(x4+1 >= seq_len) ? (FLOAT4)0 : vload4(0,key+key_offset); key_offset += stride;\n"
" FLOAT4 key_vec2=(x4+2 >= seq_len) ? (FLOAT4)0 : vload4(0,key+key_offset); key_offset += stride;\n"
" FLOAT4 key_vec3=(x4+3 >= seq_len) ? (FLOAT4)0 : vload4(0,key+key_offset);\n"
" const int output_offset=((b*kv_head_num+z)*head_dim+y4)*max_len+past_len+x4;\n"
" vstore4((FLOAT4)(key_vec0.s0,key_vec1.s0,key_vec2.s0,key_vec3.s0),0,past_key+output_offset);\n"
" vstore4((FLOAT4)(key_vec0.s1,key_vec1.s1,key_vec2.s1,key_vec3.s1),0,past_key+output_offset+max_len);\n"
" vstore4((FLOAT4)(key_vec0.s2,key_vec1.s2,key_vec2.s2,key_vec3.s2),0,past_key+output_offset+max_len+max_len);\n"
" vstore4((FLOAT4)(key_vec0.s3,key_vec1.s3,key_vec2.s3,key_vec3.s3),0,past_key+output_offset+max_len+max_len+max_len);\n"
"#else\n"
" FLOAT4 key_vec=vload4(0,key+(b*kv_head_num+z)*head_dim+y4);\n"
" const int output_offset=((b*kv_head_num+z)*head_dim+y4)*max_len+past_len;\n"
" past_key[output_offset]=key_vec.s0;\n"
" past_key[output_offset+max_len]=key_vec.s1;\n"
" past_key[output_offset+max_len+max_len]=key_vec.s2;\n"
" past_key[output_offset+max_len+max_len+max_len]=key_vec.s3;\n"
"#endif\n"
"}\n"
"__kernel void rearrange_v(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *value,// [batch value_seq_len kv_head_num head_dim]\n"
" __global FLOAT *past_value,// [batch kv_head_num max_length head_dim]\n"
" __private const int past_len,\n"
" __private const int max_len,\n"
" __private const int seq_len,\n"
" __private const int kv_head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // head_dim\n"
" const int y=get_global_id(1); // seq_len decode=1\n"
" int z=get_global_id(2); // kv_head_num\n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" \n"
" const int b=z/kv_head_num;\n"
" z=z % kv_head_num;\n"
" const int x4=x << 2;\n"
" \n"
"#ifdef OPENCL_PREFILL_ATTENTION\n"
" const int y4=y << 2;\n"
" const int stride=kv_head_num*head_dim;\n"
" #ifdef VALUE_C4\n"
" const int value_seq_storage=(global_size_dim2/kv_head_num)*seq_len;\n"
" const int value_channel=z*head_dim+x4;\n"
" const int value_token=b*seq_len+y4;\n"
" FLOAT4 value_vec0=load_c4_value4(value,value_seq_storage,value_token,value_channel,x4,head_dim);\n"
" FLOAT4 value_vec1=(y4+1 >= seq_len) ? (FLOAT4)0 :\n"
" load_c4_value4(value,value_seq_storage,value_token+1,value_channel,x4,head_dim);\n"
" FLOAT4 value_vec2=(y4+2 >= seq_len) ? (FLOAT4)0 :\n"
" load_c4_value4(value,value_seq_storage,value_token+2,value_channel,x4,head_dim);\n"
" FLOAT4 value_vec3=(y4+3 >= seq_len) ? (FLOAT4)0 :\n"
" load_c4_value4(value,value_seq_storage,value_token+3,value_channel,x4,head_dim);\n"
" #else\n"
" int value_offset=((b*seq_len+y4)*kv_head_num+z)*head_dim+x4;\n"
" FLOAT4 value_vec0=vload4(0,value+value_offset); value_offset += stride;\n"
" FLOAT4 value_vec1=(y4+1 >= seq_len) ? (FLOAT4)0 : vload4(0,value+value_offset); value_offset += stride;\n"
" FLOAT4 value_vec2=(y4+2 >= seq_len) ? (FLOAT4)0 : vload4(0,value+value_offset); value_offset += stride;\n"
" FLOAT4 value_vec3=(y4+3 >= seq_len) ? (FLOAT4)0 : vload4(0,value+value_offset);\n"
" #endif\n"
" const int output_offset=((b*kv_head_num+z)*max_len+past_len+y4)*head_dim+x4;\n"
" vstore4(value_vec0,0,past_value+output_offset);\n"
" vstore4(value_vec1,0,past_value+output_offset+head_dim);\n"
" vstore4(value_vec2,0,past_value+output_offset+head_dim+head_dim);\n"
" vstore4(value_vec3,0,past_value+output_offset+head_dim+head_dim+head_dim);\n"
"#else\n"
" #ifdef VALUE_C4\n"
" const int value_seq_storage=(global_size_dim2/kv_head_num)*seq_len;\n"
" const int value_channel=z*head_dim+x4;\n"
" const int value_token=b*seq_len;\n"
" FLOAT4 value_vec=load_c4_value4(value,value_seq_storage,value_token,value_channel,x4,head_dim);\n"
" #else\n"
" FLOAT4 value_vec=vload4(0,value+(b*kv_head_num+z)*head_dim+x4);\n"
" #endif\n"
" const int output_offset=((b*kv_head_num+z)*max_len+past_len)*head_dim+x4;\n"
" vstore4(value_vec,0,past_value+output_offset);\n"
"#endif\n"
"}\n"
"__kernel void rearrange_mask_shortprefill(GLOBAL_SIZE_3_DIMS\n"
" #ifdef ADD_MASK\n"
" __global const FLOAT* mask,\n"
" __global FLOAT* maskout,\n"
" #else\n"
" __global const int* mask,// [1 1 query_seq_len mask_key_seq_len4]\n"
" __global int* maskout,// [1 1 mask_key_seq_len4 query_seq_len4]\n"
" #endif\n"
" __private const int query_seq_len,\n"
" __private const int mask_key_seq_len){\n"
" const int x=get_global_id(0); // query_seq_len4\n"
" const int y=get_global_id(1); // mask_key_seq_len4\n"
" const int z=get_global_id(2); // batch\n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" \n"
" const int x4=x << 2;\n"
" const int y4=y << 2;\n"
" float4 mask_tmp0,mask_tmp1,mask_tmp2,mask_tmp3;\n"
" float4 mask0,mask1,mask2,mask3;\n"
" int mask_offset=x4*mask_key_seq_len+y4;\n"
" if(x4+3<query_seq_len && y4+3<mask_key_seq_len){\n"
" mask_tmp0=convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp1=convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp2=convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp3=convert_float4(vload4(0,mask+mask_offset));\n"
" } else{\n"
" if(y4+3<mask_key_seq_len){\n"
" mask_tmp0=convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp1=(x4+1 >= query_seq_len) ? (float4)0 : convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp2=(x4+2 >= query_seq_len) ? (float4)0 : convert_float4(vload4(0,mask+mask_offset)); mask_offset += mask_key_seq_len;\n"
" mask_tmp3=(x4+3 >= query_seq_len) ? (float4)0 : convert_float4(vload4(0,mask+mask_offset));\n"
" } else if(y4+1 == mask_key_seq_len){\n"
" mask_tmp0=(float4)(mask[mask_offset],0,0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp1=(x4+1 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],0,0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp2=(x4+2 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],0,0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp3=(x4+3 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],0,0,0);\n"
" }else if(y4+2 == mask_key_seq_len){\n"
" mask_tmp0=(float4)(mask[mask_offset],mask[mask_offset+1],0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp1=(x4+1 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp2=(x4+2 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],0,0); mask_offset += mask_key_seq_len;\n"
" mask_tmp3=(x4+3 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],0,0);\n"
" }else if(y4+3 == mask_key_seq_len){\n"
" mask_tmp0=(float4)(mask[mask_offset],mask[mask_offset+1],mask[mask_offset+2],0); mask_offset += mask_key_seq_len;\n"
" mask_tmp1=(x4+1 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],mask[mask_offset+2],0); mask_offset += mask_key_seq_len;\n"
" mask_tmp2=(x4+2 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],mask[mask_offset+2],0); mask_offset += mask_key_seq_len;\n"
" mask_tmp3=(x4+3 >= query_seq_len) ? (float4)0 : (float4)(mask[mask_offset],mask[mask_offset+1],mask[mask_offset+2],0);\n"
" }\n"
" }\n"
" mask0=(float4)(mask_tmp0.s0,mask_tmp1.s0,mask_tmp2.s0,mask_tmp3.s0);\n"
" mask1=(float4)(mask_tmp0.s1,mask_tmp1.s1,mask_tmp2.s1,mask_tmp3.s1);\n"
" mask2=(float4)(mask_tmp0.s2,mask_tmp1.s2,mask_tmp2.s2,mask_tmp3.s2);\n"
" mask3=(float4)(mask_tmp0.s3,mask_tmp1.s3,mask_tmp2.s3,mask_tmp3.s3);\n"
" \n"
" int query_seq_len4=((query_seq_len+3)/4)*4;\n"
" int output_offset=y4*query_seq_len4+x4;\n"
" #ifdef ADD_MASK\n"
" vstore4(CONVERT_FLOAT4(mask0),0,maskout+output_offset);\n"
" vstore4(CONVERT_FLOAT4(mask1),0,maskout+output_offset+query_seq_len4);\n"
" vstore4(CONVERT_FLOAT4(mask2),0,maskout+output_offset+query_seq_len4+query_seq_len4);\n"
" vstore4(CONVERT_FLOAT4(mask3),0,maskout+output_offset+query_seq_len4+query_seq_len4+query_seq_len4);\n"
" #else\n"
" vstore4(convert_int4(mask0),0,maskout+output_offset);\n"
" vstore4(convert_int4(mask1),0,maskout+output_offset+query_seq_len4);\n"
" vstore4(convert_int4(mask2),0,maskout+output_offset+query_seq_len4+query_seq_len4);\n"
" vstore4(convert_int4(mask3),0,maskout+output_offset+query_seq_len4+query_seq_len4+query_seq_len4);\n"
" #endif\n"
"}\n"
"__kernel void matmul_qk_div_mask_prefill(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *query,// [batch head_num head_dim_4 query_seq_len_4]\n"
" __global const FLOAT *past_key,// [batch kv_head_num head_dim_4 kv_max_length]\n"
" #ifdef ADD_MASK\n"
" __global const FLOAT* mask,\n"
" #elif defined(SET_MASK)\n"
" __global const int* mask,// [1 1 query_seq_len mask_key_seq_len]\n"
" #else\n"
" __global const FLOAT* mask,\n"
" #endif\n"
" __global FLOAT *qk,// [batch head_num kv_seq_length query_seq_len_4]\n"
" __private const float scale,\n"
" __private const int query_seq_len,\n"
" __private const int mask_key_seq_len,\n"
" __private const int key_seq_len,\n"
" __private const int max_len,\n"
" __private const int head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // query_seq_len\n"
" const int y=get_global_id(1); // kv_seq_length\n"
" const int z=get_global_id(2); // head_num*batch\n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" \n"
" const int x4=x << 2;\n"
" const int y4=y << 2;\n"
" \n"
" const int query_seq_len4=(query_seq_len+3)/4*4;;\n"
" const int query_offset=z*head_dim*query_seq_len4+x4;\n"
" const int past_offset=(z/NUMHEAD_GROUP_SIZE)*head_dim*max_len+y4;\n"
" float4 out0=0,out1=0,out2=0,out3=0;\n"
" \n"
" for(int i=0; i<head_dim/4; ++i){\n"
" int i4=i << 2;\n"
" float4 query_vec0=convert_float4(vload4(0,query+query_offset+i4*query_seq_len4));\n"
" float4 query_vec1=convert_float4(vload4(0,query+query_offset+(i4+1)*query_seq_len4));\n"
" float4 query_vec2=convert_float4(vload4(0,query+query_offset+(i4+2)*query_seq_len4));\n"
" float4 query_vec3=convert_float4(vload4(0,query+query_offset+(i4+3)*query_seq_len4));\n"
" \n"
" float4 past_vec0=convert_float4(vload4(0,past_key+past_offset+i4*max_len));\n"
" float4 past_vec1=convert_float4(vload4(0,past_key+past_offset+(i4+1)*max_len));\n"
" float4 past_vec2=convert_float4(vload4(0,past_key+past_offset+(i4+2)*max_len));\n"
" float4 past_vec3=convert_float4(vload4(0,past_key+past_offset+(i4+3)*max_len));\n"
" out0=mad((float4)past_vec0.s0,query_vec0,out0);\n"
" out0=mad((float4)past_vec1.s0,query_vec1,out0);\n"
" out0=mad((float4)past_vec2.s0,query_vec2,out0);\n"
" out0=mad((float4)past_vec3.s0,query_vec3,out0);\n"
" \n"
" out1=mad((float4)past_vec0.s1,query_vec0,out1);\n"
" out1=mad((float4)past_vec1.s1,query_vec1,out1);\n"
" out1=mad((float4)past_vec2.s1,query_vec2,out1);\n"
" out1=mad((float4)past_vec3.s1,query_vec3,out1);\n"
" \n"
" out2=mad((float4)past_vec0.s2,query_vec0,out2);\n"
" out2=mad((float4)past_vec1.s2,query_vec1,out2);\n"
" out2=mad((float4)past_vec2.s2,query_vec2,out2);\n"
" out2=mad((float4)past_vec3.s2,query_vec3,out2);\n"
" \n"
" out3=mad((float4)past_vec0.s3,query_vec0,out3);\n"
" out3=mad((float4)past_vec1.s3,query_vec1,out3);\n"
" out3=mad((float4)past_vec2.s3,query_vec2,out3);\n"
" out3=mad((float4)past_vec3.s3,query_vec3,out3);\n"
" }\n"
" out0 *= (float4)scale;\n"
" out1 *= (float4)scale;\n"
" out2 *= (float4)scale;\n"
" out3 *= (float4)scale;\n"
" {\n"
" #if defined(ADD_MASK) || defined(SET_MASK)\n"
" int query_seq_len4=((query_seq_len+3)/4)*4;\n"
" int mask_clp=y4+mask_key_seq_len-key_seq_len;\n"
" int mask_offset=mask_clp*query_seq_len4+x4;\n"
" float4 mask0=mask_clp >= 0 && mask_clp<mask_key_seq_len ? convert_float4(vload4(0,mask+mask_offset)) : 0; mask_offset += query_seq_len4;\n"
" float4 mask1=mask_clp+1 >= 0 && mask_clp+1<mask_key_seq_len? convert_float4(vload4(0,mask+mask_offset)) : 0; mask_offset += query_seq_len4;\n"
" float4 mask2=mask_clp+2 >= 0 && mask_clp+2<mask_key_seq_len? convert_float4(vload4(0,mask+mask_offset)) : 0; mask_offset += query_seq_len4;\n"
" float4 mask3=mask_clp+3 >= 0 && mask_clp+3<mask_key_seq_len? convert_float4(vload4(0,mask+mask_offset)) : 0;\n"
" #endif\n"
" \n"
" #ifdef ADD_MASK\n"
" out0 += mask0;\n"
" out1 += mask1;\n"
" out2 += mask2;\n"
" out3 += mask3;\n"
" #elif defined(SET_MASK)\n"
" out0=(mask0 == (float4)0) ? (float4)(-FLT_MAX) : out0;\n"
" out1=(mask1 == (float4)0) ? (float4)(-FLT_MAX) : out1;\n"
" out2=(mask2 == (float4)0) ? (float4)(-FLT_MAX) : out2;\n"
" out3=(mask3 == (float4)0) ? (float4)(-FLT_MAX) : out3;\n"
" #elif defined(DEFAULT_MASK)\n"
" {\n"
" int kv_valid_offset=key_seq_len-query_seq_len;\n"
" int k0=y4+0;\n"
" int k1=y4+1;\n"
" int k2=y4+2;\n"
" int k3=y4+3;\n"
" int q0=x4+0;\n"
" int q1=x4+1;\n"
" int q2=x4+2;\n"
" int q3=x4+3;\n"
" if (k0>kv_valid_offset+q0) { out0.s0=-FLT_MAX; }\n"
" if (k1>kv_valid_offset+q0) { out1.s0=-FLT_MAX; }\n"
" if (k2>kv_valid_offset+q0) { out2.s0=-FLT_MAX; }\n"
" if (k3>kv_valid_offset+q0) { out3.s0=-FLT_MAX; }\n"
" if (k0>kv_valid_offset+q1) { out0.s1=-FLT_MAX; }\n"
" if (k1>kv_valid_offset+q1) { out1.s1=-FLT_MAX; }\n"
" if (k2>kv_valid_offset+q1) { out2.s1=-FLT_MAX; }\n"
" if (k3>kv_valid_offset+q1) { out3.s1=-FLT_MAX; }\n"
" if (k0>kv_valid_offset+q2) { out0.s2=-FLT_MAX; }\n"
" if (k1>kv_valid_offset+q2) { out1.s2=-FLT_MAX; }\n"
" if (k2>kv_valid_offset+q2) { out2.s2=-FLT_MAX; }\n"
" if (k3>kv_valid_offset+q2) { out3.s2=-FLT_MAX; }\n"
" if (k0>kv_valid_offset+q3) { out0.s3=-FLT_MAX; }\n"
" if (k1>kv_valid_offset+q3) { out1.s3=-FLT_MAX; }\n"
" if (k2>kv_valid_offset+q3) { out2.s3=-FLT_MAX; }\n"
" if (k3>kv_valid_offset+q3) { out3.s3=-FLT_MAX; }\n"
" }\n"
" #endif\n"
" }\n"
" \n"
" const int qk_offset=(z*key_seq_len+y4)*query_seq_len4+x4;\n"
" vstore4(CONVERT_FLOAT4(out0),0,qk+qk_offset);\n"
" if(y4+1 >= key_seq_len) return;\n"
" vstore4(CONVERT_FLOAT4(out1),0,qk+qk_offset+query_seq_len4);\n"
" if(y4+2 >= key_seq_len) return;\n"
" vstore4(CONVERT_FLOAT4(out2),0,qk+qk_offset+query_seq_len4+query_seq_len4);\n"
" if(y4+3 >= key_seq_len) return;\n"
" vstore4(CONVERT_FLOAT4(out3),0,qk+qk_offset+query_seq_len4+query_seq_len4+query_seq_len4);\n"
"}\n"
"__kernel void matmul_qk_decode(GLOBAL_SIZE_2_DIMS\n"
" __global const FLOAT *query,// key [1 head_num head_dim]\n"
" __global const FLOAT *past_key,// [1 head_num head_dim max_length]\n"
" __global FLOAT *qk,// [1 head_num key_seq_len 1]\n"
" __private const float scale,\n"
" __private const int seq_len,\n"
" __private const int max_len,\n"
" __private const int head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // key_seq_len\n"
" const int y=get_global_id(1); // head_num\n"
" DEAL_NON_UNIFORM_DIM2(x,y);\n"
" const int x4=x << 2;\n"
" \n"
" const int query_offset=y*head_dim;\n"
" const int past_offset=(y/NUMHEAD_GROUP_SIZE)*head_dim*max_len+x4;\n"
" float4 out0=0;\n"
" \n"
" for(int i=0; i<head_dim/4; ++i){\n"
" int i4=i << 2;\n"
" float4 query_vec=convert_float4(vload4(0,query+query_offset+i4));\n"
" \n"
" float4 past_vec0=convert_float4(vload4(0,past_key+past_offset+i4*max_len));\n"
" float4 past_vec1=convert_float4(vload4(0,past_key+past_offset+(i4+1)*max_len));\n"
" float4 past_vec2=convert_float4(vload4(0,past_key+past_offset+(i4+2)*max_len));\n"
" float4 past_vec3=convert_float4(vload4(0,past_key+past_offset+(i4+3)*max_len));\n"
" \n"
" out0=mad((float4)query_vec.s0,past_vec0,out0);\n"
" out0=mad((float4)query_vec.s1,past_vec1,out0);\n"
" out0=mad((float4)query_vec.s2,past_vec2,out0);\n"
" out0=mad((float4)query_vec.s3,past_vec3,out0);\n"
" }\n"
" out0 *= (float4)scale;\n"
" const int qk_offset=y*seq_len+x4;\n"
" if(x4+3<seq_len){\n"
" vstore4(CONVERT_FLOAT4(out0),0,qk+qk_offset);\n"
" }else {\n"
" int remain=seq_len-x4;\n"
" if(remain == 3){\n"
" vstore3(CONVERT_FLOAT3((float3)(out0.s012)),0,qk+qk_offset);\n"
" } else if(remain == 2){\n"
" vstore2(CONVERT_FLOAT2((float2)(out0.s01)),0,qk+qk_offset);\n"
" }else if(remain == 1){\n"
" qk[qk_offset]=out0.s0;\n"
" }\n"
" }\n"
"}\n"
"__kernel void matmul_qkv_prefill(GLOBAL_SIZE_3_DIMS\n"
" __global const FLOAT *qk,// qk prefill [batch head_num kv_seq_length query_seq_len]\n"
" __global const FLOAT *past_value,// [batch kv_head_num max_len head_dim]\n"
" __global FLOAT *output,// [batch query_seq_len head_num head_dim]\n"
" __private const int query_seq_len,\n"
" __private const int kv_seq_len,\n"
" __private const int max_len,\n"
" __private const int head_num,\n"
" __private const int kv_head_num,\n"
" __private const int head_dim,\n"
" __private const int batch) {\n"
" \n"
" const int x=get_global_id(0); // head_dim\n"
" const int y=get_global_id(1); // query_seq_len\n"
" int z=get_global_id(2); // head_num*batch\n"
" \n"
" DEAL_NON_UNIFORM_DIM3(x,y,z);\n"
" const int b=z/head_num;\n"
" z=z % head_num;\n"
" const int x8=x << 3;\n"
" const int y4=y << 2;\n"
" \n"
" const int query_seq_len4=(query_seq_len+3)/4*4;\n"
" const int qk_offset=(b*head_num+z)*kv_seq_len*query_seq_len4+y4;\n"
" const int past_offset=((b*kv_head_num+z/NUMHEAD_GROUP_SIZE)*max_len)*head_dim+x8;\n"
" const int loop_end=max(kv_seq_len/4-1,0);\n"
" COMPUTE_FLOAT8 out0=0,out1=0,out2=0,out3=0;\n"
" \n"
" for(int i=0; i<loop_end; ++i){\n"
" int i4=i << 2;\n"
" COMPUTE_FLOAT4 qk_vec0=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+i4*query_seq_len4));\n"
" COMPUTE_FLOAT4 qk_vec1=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+(i4+1)*query_seq_len4));\n"
" COMPUTE_FLOAT4 qk_vec2=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+(i4+2)*query_seq_len4));\n"
" COMPUTE_FLOAT4 qk_vec3=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+(i4+3)*query_seq_len4));\n"
" \n"
" COMPUTE_FLOAT8 past_vec0=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i4*head_dim));\n"
" COMPUTE_FLOAT8 past_vec1=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+1)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec2=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+2)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec3=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+3)*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT8)qk_vec0.s0,past_vec0,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec1.s0,past_vec1,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec2.s0,past_vec2,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec3.s0,past_vec3,out0);\n"
" \n"
" out1=mad((COMPUTE_FLOAT8)qk_vec0.s1,past_vec0,out1);\n"
" out1=mad((COMPUTE_FLOAT8)qk_vec1.s1,past_vec1,out1);\n"
" out1=mad((COMPUTE_FLOAT8)qk_vec2.s1,past_vec2,out1);\n"
" out1=mad((COMPUTE_FLOAT8)qk_vec3.s1,past_vec3,out1);\n"
" \n"
" out2=mad((COMPUTE_FLOAT8)qk_vec0.s2,past_vec0,out2);\n"
" out2=mad((COMPUTE_FLOAT8)qk_vec1.s2,past_vec1,out2);\n"
" out2=mad((COMPUTE_FLOAT8)qk_vec2.s2,past_vec2,out2);\n"
" out2=mad((COMPUTE_FLOAT8)qk_vec3.s2,past_vec3,out2);\n"
" \n"
" out3=mad((COMPUTE_FLOAT8)qk_vec0.s3,past_vec0,out3);\n"
" out3=mad((COMPUTE_FLOAT8)qk_vec1.s3,past_vec1,out3);\n"
" out3=mad((COMPUTE_FLOAT8)qk_vec2.s3,past_vec2,out3);\n"
" out3=mad((COMPUTE_FLOAT8)qk_vec3.s3,past_vec3,out3);\n"
" }\n"
" for(int i=(loop_end << 2); i<kv_seq_len; ++i){\n"
" COMPUTE_FLOAT4 qk_vec=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+i*query_seq_len4));\n"
" COMPUTE_FLOAT8 past_vec=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s0,past_vec,out0);\n"
" out1=mad((COMPUTE_FLOAT8)qk_vec.s1,past_vec,out1);\n"
" out2=mad((COMPUTE_FLOAT8)qk_vec.s2,past_vec,out2);\n"
" out3=mad((COMPUTE_FLOAT8)qk_vec.s3,past_vec,out3);\n"
" }\n"
" \n"
"#ifdef ATTENTION_C4\n"
" int output_offset=(z*head_dim+x8)*query_seq_len*batch+(b*query_seq_len+y4)*4;\n"
" const int stride=query_seq_len*batch*4;\n"
" vstore4(CONVERT_FLOAT4(out0.lo),0,output+output_offset);\n"
" vstore4(CONVERT_FLOAT4(out0.hi),0,output+output_offset+stride);\n"
" if(y4+1 >= query_seq_len) return;\n"
" output_offset += 4;\n"
" vstore4(CONVERT_FLOAT4(out1.lo),0,output+output_offset);\n"
" vstore4(CONVERT_FLOAT4(out1.hi),0,output+output_offset+stride);\n"
" if(y4+2 >= query_seq_len) return;\n"
" output_offset += 4;\n"
" vstore4(CONVERT_FLOAT4(out2.lo),0,output+output_offset);\n"
" vstore4(CONVERT_FLOAT4(out2.hi),0,output+output_offset+stride);\n"
" if(y4+3 >= query_seq_len) return;\n"
" output_offset += 4;\n"
" vstore4(CONVERT_FLOAT4(out3.lo),0,output+output_offset);\n"
" vstore4(CONVERT_FLOAT4(out3.hi),0,output+output_offset+stride);\n"
"#else\n"
" const int output_offset=((b*query_seq_len+y4)*head_num+z)*head_dim+x8;\n"
" const int stride=head_num*head_dim;\n"
" vstore8(CONVERT_FLOAT8(out0),0,output+output_offset);\n"
" if(y4+1 >= query_seq_len) return;\n"
" vstore8(CONVERT_FLOAT8(out1),0,output+output_offset+stride);\n"
" if(y4+2 >= query_seq_len) return;\n"
" vstore8(CONVERT_FLOAT8(out2),0,output+output_offset+stride+stride);\n"
" if(y4+3 >= query_seq_len) return;\n"
" vstore8(CONVERT_FLOAT8(out3),0,output+output_offset+stride+stride+stride);\n"
"#endif\n"
"}\n"
"__kernel void matmul_qkv_decode_b8(GLOBAL_SIZE_2_DIMS\n"
" __global const FLOAT *qk,// qk [1 head_num qk_seq_len 1]\n"
" __global const FLOAT *past_value,// [1 head_num max_len head_dim]\n"
" __global FLOAT *output,// [1 1 head_num head_dim]\n"
" __private const int qk_seq_len,\n"
" __private const int max_len,\n"
" __private const int head_num,\n"
" __private const int kv_head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // head_dim\n"
" const int y=get_global_id(1); // head_num\n"
" \n"
" DEAL_NON_UNIFORM_DIM2(x,y);\n"
" const int x8=x << 3;\n"
" \n"
" const int qk_offset=y*qk_seq_len;\n"
" const int past_offset=((y/NUMHEAD_GROUP_SIZE)*max_len)*head_dim+x8;\n"
" COMPUTE_FLOAT8 out0=0;\n"
" #ifdef LOOP_UNROLL_4\n"
" const int loop_end=max((qk_seq_len+3)/4-1,0);\n"
" for(int i=0; i<loop_end; ++i){\n"
" int i4=i << 2;\n"
" COMPUTE_FLOAT4 qk_vec=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+i4));\n"
" \n"
" COMPUTE_FLOAT8 past_vec0=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i4*head_dim));\n"
" COMPUTE_FLOAT8 past_vec1=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+1)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec2=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+2)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec3=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i4+3)*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s0,past_vec0,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s1,past_vec1,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s2,past_vec2,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s3,past_vec3,out0);\n"
" }\n"
" for(int i=(loop_end << 2); i<qk_seq_len; ++i){\n"
" COMPUTE_FLOAT qk_vec=qk[qk_offset+i];\n"
" COMPUTE_FLOAT8 past_vec=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i*head_dim));\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec,past_vec,out0);\n"
" }\n"
" #elif (defined LOOP_UNROLL_8)\n"
" const int loop_end=max((qk_seq_len+7)/8-1,0);\n"
" for(int i=0; i<loop_end; ++i){\n"
" int i8=i << 3;\n"
" COMPUTE_FLOAT8 qk_vec=CONVERT_COMPUTE_FLOAT8(vload8(0,qk+qk_offset+i8));\n"
" \n"
" COMPUTE_FLOAT8 past_vec0=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i8*head_dim));\n"
" COMPUTE_FLOAT8 past_vec1=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+1)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec2=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+2)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec3=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+3)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec4=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+4)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec5=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+5)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec6=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+6)*head_dim));\n"
" COMPUTE_FLOAT8 past_vec7=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+(i8+7)*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s0,past_vec0,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s1,past_vec1,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s2,past_vec2,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s3,past_vec3,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s4,past_vec4,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s5,past_vec5,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s6,past_vec6,out0);\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec.s7,past_vec7,out0);\n"
" }\n"
" for(int i=(loop_end << 3); i<qk_seq_len; ++i){\n"
" COMPUTE_FLOAT qk_vec=qk[qk_offset+i];\n"
" COMPUTE_FLOAT8 past_vec=CONVERT_COMPUTE_FLOAT8(vload8(0,past_value+past_offset+i*head_dim));\n"
" out0=mad((COMPUTE_FLOAT8)qk_vec,past_vec,out0);\n"
" }\n"
" #endif\n"
" \n"
" const int output_offset=y*head_dim+x8;\n"
" vstore8(CONVERT_FLOAT8(out0),0,output+output_offset);\n"
"}\n"
"__kernel void matmul_qkv_decode_b4(GLOBAL_SIZE_2_DIMS\n"
" __global const FLOAT *qk,// qk [1 head_num qk_seq_len 1]\n"
" __global const FLOAT *past_value,// [1 head_num max_len head_dim]\n"
" __global FLOAT *output,// [1 1 head_num head_dim]\n"
" __private const int qk_seq_len,\n"
" __private const int max_len,\n"
" __private const int head_num,\n"
" __private const int kv_head_num,\n"
" __private const int head_dim) {\n"
" \n"
" const int x=get_global_id(0); // head_dim\n"
" const int y=get_global_id(1); // head_num\n"
" \n"
" DEAL_NON_UNIFORM_DIM2(x,y);\n"
" const int x4=x << 2;\n"
" \n"
" const int qk_offset=y*qk_seq_len;\n"
" const int past_offset=((y/NUMHEAD_GROUP_SIZE)*max_len)*head_dim+x4;\n"
" COMPUTE_FLOAT4 out0=0;\n"
" #ifdef LOOP_UNROLL_4\n"
" const int loop_end=max((qk_seq_len+3)/4-1,0);\n"
" for(int i=0; i<loop_end; ++i){\n"
" int i4=i << 2;\n"
" COMPUTE_FLOAT4 qk_vec=CONVERT_COMPUTE_FLOAT4(vload4(0,qk+qk_offset+i4));\n"
" \n"
" COMPUTE_FLOAT4 past_vec0=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+i4*head_dim));\n"
" COMPUTE_FLOAT4 past_vec1=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i4+1)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec2=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i4+2)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec3=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i4+3)*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s0,past_vec0,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s1,past_vec1,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s2,past_vec2,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s3,past_vec3,out0);\n"
" }\n"
" for(int i=(loop_end << 2); i<qk_seq_len; ++i){\n"
" COMPUTE_FLOAT qk_vec=qk[qk_offset+i];\n"
" COMPUTE_FLOAT4 past_vec=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+i*head_dim));\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec,past_vec,out0);\n"
" }\n"
" #elif (defined LOOP_UNROLL_8)\n"
" const int loop_end=max((qk_seq_len+7)/8-1,0);\n"
" for(int i=0; i<loop_end; ++i){\n"
" int i8=i << 3;\n"
" COMPUTE_FLOAT8 qk_vec=CONVERT_COMPUTE_FLOAT8(vload8(0,qk+qk_offset+i8));\n"
" \n"
" COMPUTE_FLOAT4 past_vec0=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+i8*head_dim));\n"
" COMPUTE_FLOAT4 past_vec1=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+1)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec2=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+2)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec3=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+3)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec4=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+4)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec5=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+5)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec6=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+6)*head_dim));\n"
" COMPUTE_FLOAT4 past_vec7=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+(i8+7)*head_dim));\n"
" \n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s0,past_vec0,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s1,past_vec1,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s2,past_vec2,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s3,past_vec3,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s4,past_vec4,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s5,past_vec5,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s6,past_vec6,out0);\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec.s7,past_vec7,out0);\n"
" }\n"
" for(int i=(loop_end << 3); i<qk_seq_len; ++i){\n"
" COMPUTE_FLOAT qk_vec=qk[qk_offset+i];\n"
" COMPUTE_FLOAT4 past_vec=CONVERT_COMPUTE_FLOAT4(vload4(0,past_value+past_offset+i*head_dim));\n"
" out0=mad((COMPUTE_FLOAT4)qk_vec,past_vec,out0);\n"
" }\n"
" #endif\n"
" \n"
" const int output_offset=y*head_dim+x4;\n"
" vstore4(CONVERT_FLOAT4(out0),0,output+output_offset);\n"
"}\n"
;
#endif
}