char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
e95dae18d
char/aliceai-t5-moe
1#pragma OPENCL EXTENSION cl_khr_subgroups : enable 2 3#ifdef cl_intel_required_subgroup_size 4#pragma OPENCL EXTENSION cl_intel_required_subgroup_size : enable 5#define INTEL_GPU 1 6#define REQD_SUBGROUP_SIZE_16 __attribute__((intel_reqd_sub_group_size(16))) 7#define REQD_SUBGROUP_SIZE_32 __attribute__((intel_reqd_sub_group_size(32))) 8#elif defined(cl_qcom_reqd_sub_group_size) 9#pragma OPENCL EXTENSION cl_qcom_reqd_sub_group_size : enable 10#define ADRENO_GPU 1 11#define REQD_SUBGROUP_SIZE_64 __attribute__((qcom_reqd_sub_group_size("half" ))) 12#define REQD_SUBGROUP_SIZE_128 __attribute__((qcom_reqd_sub_group_size("full" ))) 13#endif 14 15#ifndef S_V 16#define S_V 128 17#endif 18#ifndef KDA 19#define KDA 0 20#endif 21#ifndef SUBGROUP_SIZE 22#define SUBGROUP_SIZE 64 23#endif 24#ifndef LANES_PER_COLUMN 25#define LANES_PER_COLUMN 8 26#endif 27#ifndef COLS_PER_LANE_GROUP 28#define COLS_PER_LANE_GROUP 1 29#endif 30#ifndef SUBGROUPS_PER_WG 31#define SUBGROUPS_PER_WG 1 32#endif 33#ifndef USE_QCOM_SUBGROUP_SHUFFLE 34#define USE_QCOM_SUBGROUP_SHUFFLE 0 35#endif 36 37#define WG_SIZE (SUBGROUP_SIZE * SUBGROUPS_PER_WG) 38#define LANE_GROUPS_PER_SG (SUBGROUP_SIZE / LANES_PER_COLUMN) 39#define COLS_PER_SG (LANE_GROUPS_PER_SG * COLS_PER_LANE_GROUP) 40#define COLS_PER_WG (SUBGROUPS_PER_WG * COLS_PER_SG) 41#define ROWS_PER_LANE (S_V / LANES_PER_COLUMN) 42 43#if USE_QCOM_SUBGROUP_SHUFFLE 44#pragma OPENCL EXTENSION cl_qcom_subgroup_shuffle : enable 45#endif 46 47// XOR-based parallel sum 48// This does a reduction across groups of LANES_PER_COLUMN 49static inline float reduce_add_shmem(float partial, __local float * temp, uint lane) { 50#if USE_QCOM_SUBGROUP_SHUFFLE 51 #pragma unroll 52 for (uint s = LANES_PER_COLUMN / 2u; s > 0u; s >>= 1u) { 53 partial += qcom_sub_group_shuffle_xor(partial, s, CLK_SUB_GROUP_SHUFFLE_WIDTH_WAVE_SIZE_QCOM, partial); 54 } 55 return partial; 56#else 57 temp[lane] = partial; 58 sub_group_barrier(CLK_LOCAL_MEM_FENCE); 59 #pragma unroll 60 for (uint s = LANES_PER_COLUMN / 2u; s > 0u; s >>= 1u) { 61 float other = temp[lane ^ s]; 62 sub_group_barrier(CLK_LOCAL_MEM_FENCE); 63 temp[lane] += other; 64 sub_group_barrier(CLK_LOCAL_MEM_FENCE); 65 } 66 const float result = temp[lane]; 67 sub_group_barrier(CLK_LOCAL_MEM_FENCE); 68 return result; 69#endif 70} 71 72#define REDUCE_PARTIAL(partial, temp_ptr, lid)\ 73 ((LANES_PER_COLUMN == 1u) ? (partial) : reduce_add_shmem((partial), (temp_ptr), (lid))) 74 75// force compiler to optimize kernel for a specific fixed work-group size 76__attribute__((reqd_work_group_size(WG_SIZE, 1, 1))) 77#ifdef INTEL_GPU 78REQD_SUBGROUP_SIZE_32 79#elif defined (ADRENO_GPU) 80REQD_SUBGROUP_SIZE_64 81#endif 82kernel void kernel_gated_delta_net( 83 global const char * q_buf, ulong off_q, 84 global const char * k_buf, ulong off_k, 85 global const char * v_buf, ulong off_v, 86 global const char * g_buf, ulong off_g, 87 global const char * beta_buf, ulong off_beta, 88 global const char * state_buf, ulong off_state, 89 global char * dst_buf, ulong off_dst, 90 uint H_v, 91 uint n_tokens, 92 uint n_seqs, 93 uint s_off, 94 uint sq1, uint sq2, uint sq3, 95 uint sv1, uint sv2, uint sv3, 96 uint sb1, uint sb2, uint sb3, 97 uint H_k, 98 uint rq3, 99 float scale, 100 uint K) { 101 102 global const float * data_q = (global const float *)(q_buf + off_q); 103 global const float * data_k = (global const float *)(k_buf + off_k); 104 global const float * data_v = (global const float *)(v_buf + off_v); 105 global const float * data_g = (global const float *)(g_buf + off_g); 106 global const float * data_beta = (global const float *)(beta_buf + off_beta); 107 global const float * data_state = (global const float *)(state_buf + off_state); 108 global float * data_dst = (global float *)(dst_buf + off_dst); 109 110 const uint head_id = get_group_id(0); 111 const uint seq_id = get_group_id(1); 112 const uint tid = (uint)get_local_id(0); 113 114 const uint sg_id = get_sub_group_id(); // subgroup id 115 const uint sg_lid = get_sub_group_local_id(); // subgroup lane id 116 117 const uint lane = sg_lid % LANES_PER_COLUMN; 118 const uint lane_group = sg_lid / LANES_PER_COLUMN; 119 const uint wg_col_base = get_group_id(2) * COLS_PER_WG; 120 const uint sg_col_base = wg_col_base + sg_id * COLS_PER_SG; 121 122 const uint iq1 = head_id % H_k; // head index for Q and K 123 const uint iq3 = seq_id / rq3; // seq index for Q and K 124 125 const uint state_size = S_V * S_V; 126 // input state holds s0 only [S_v, S_v, H, n_seqs]: per-seq stride is H*D. 127 const uint state_base = (seq_id * H_v + head_id) * state_size; 128 const uint q_off_base = iq3 * sq3 + iq1 * sq1; 129 const uint v_off_base = seq_id * sv3 + head_id * sv1; 130 const uint gb_off_base = seq_id * sb3 + head_id * sb1; 131 const uint state_out_base = (seq_id * H_v + head_id) * state_size; 132 const uint state_size_per_snap = state_size * H_v * n_seqs; 133 134 __local float reduce_temp[WG_SIZE]; 135 __local float * temp_ptr = reduce_temp + sg_id * SUBGROUP_SIZE; 136 137 float s_shard[COLS_PER_LANE_GROUP][ROWS_PER_LANE]; 138 #pragma unroll 139 for (uint cg = 0; cg < COLS_PER_LANE_GROUP; cg++) { 140 const uint col = sg_col_base + cg * LANE_GROUPS_PER_SG + lane_group; 141 #pragma unroll 142 for (uint r = 0; r < ROWS_PER_LANE; r++) { 143 s_shard[cg][r] = data_state[state_base + col * S_V + r * LANES_PER_COLUMN + lane]; 144 } 145 } 146 147 // snapshot slot mapping: slot 0 = most recent state, slot s = s tokens back. 148 // When n_tokens < K only slots 0..n_tokens-1 are written; older slots are caller-owned. 149 uint attn_off = (seq_id * n_tokens * H_v + head_id) * S_V; 150 151 for (uint t = 0; t < n_tokens; t++) { 152 const uint q_off = q_off_base + t * sq2; 153 const uint k_off = q_off; 154 const uint v_off = v_off_base + t * sv2; 155 const uint gb_off = gb_off_base + t * sb2; 156 const float beta_val = data_beta[gb_off]; 157 158 float k_reg[ROWS_PER_LANE]; 159 float q_reg[ROWS_PER_LANE]; 160#if KDA 161 float g_exp[ROWS_PER_LANE]; 162 #pragma unroll 163 for (uint r = 0; r < ROWS_PER_LANE; r++) { 164 const uint i = r * LANES_PER_COLUMN + lane; 165 k_reg[r] = data_k[k_off + i]; 166 q_reg[r] = data_q[q_off + i]; 167 g_exp[r] = exp(data_g[gb_off * S_V + i]); 168 } 169#else 170 const float g_val = exp(data_g[gb_off]); 171 172 #pragma unroll 173 for (uint r = 0; r < ROWS_PER_LANE; r++) { 174 const uint i = r * LANES_PER_COLUMN + lane; 175 k_reg[r] = data_k[k_off + i]; 176 q_reg[r] = data_q[q_off + i]; 177 } 178#endif 179 180 #pragma unroll 181 for (uint cg = 0; cg < COLS_PER_LANE_GROUP; cg++) { 182 const uint col = sg_col_base + cg * LANE_GROUPS_PER_SG + lane_group; 183 float v_val = data_v[v_off + col]; 184 185 float kv_shard = 0.0f; 186 #pragma unroll 187 for (uint r = 0; r < ROWS_PER_LANE; r++) { 188#if KDA 189 float gs = g_exp[r] * s_shard[cg][r]; 190 kv_shard += gs * k_reg[r]; 191#else 192 kv_shard += s_shard[cg][r] * k_reg[r]; 193#endif 194 } 195 196#if !KDA 197 kv_shard *= g_val; // Applied once instead of ROWS_PER_LANE times 198#endif 199 200 const float kv_col = REDUCE_PARTIAL(kv_shard, temp_ptr, sg_lid); 201 202 const float delta_col = (v_val - kv_col) * beta_val; 203 204 float attn_partial = 0.0f; 205 #pragma unroll 206 for (uint r = 0; r < ROWS_PER_LANE; r++) { 207#if KDA 208 float gs = g_exp[r] * s_shard[cg][r]; 209#else 210 float gs = g_val * s_shard[cg][r]; 211#endif 212 s_shard[cg][r] = gs + k_reg[r] * delta_col; 213 attn_partial += s_shard[cg][r] * q_reg[r]; 214 } 215 const float attn_col = REDUCE_PARTIAL(attn_partial, temp_ptr, sg_lid); 216 217 if (lane == 0) { 218 data_dst[attn_off + col] = attn_col * scale; 219 } 220 } 221 attn_off += S_V * H_v; 222 223 if (K > 1u) { 224 const int target_slot = (int)n_tokens - 1 - (int)t; 225 if (target_slot >= 0 && target_slot < (int)K) { 226 #pragma unroll 227 for (uint cg = 0; cg < COLS_PER_LANE_GROUP; cg++) { 228 const uint col = sg_col_base + cg * LANE_GROUPS_PER_SG + lane_group; 229 const uint slot_base = s_off + (uint)target_slot * state_size_per_snap + state_out_base; 230 #pragma unroll 231 for (uint r = 0; r < ROWS_PER_LANE; r++) { 232 data_dst[slot_base + col * S_V + r * LANES_PER_COLUMN + lane] = s_shard[cg][r]; 233 } 234 } 235 } 236 } 237 } 238 239 if (K == 1u) { 240 #pragma unroll 241 for (uint cg = 0; cg < COLS_PER_LANE_GROUP; cg++) { 242 const uint col = sg_col_base + cg * LANE_GROUPS_PER_SG + lane_group; 243 #pragma unroll 244 for (uint r = 0; r < ROWS_PER_LANE; r++) { 245 data_dst[s_off + state_base + col * S_V + r * LANES_PER_COLUMN + lane] = s_shard[cg][r]; 246 } 247 } 248 } 249}