char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
60addddf3
char/aliceai-t5-moe
1#pragma OPENCL EXTENSION cl_khr_fp16 : enable 2 3#define ACC_TYPE float 4#define ACC_TYPE4 float4 5#define DATA_TYPE half 6#define DATA_TYPE4 half4 7#define CONVERT_ACC4(x) ((float4)((float)(x).s0, (float)(x).s1, (float)(x).s2, (float)(x).s3)) 8#define CONVERT_DATA4(x) ((half4)((half)(x).s0, (half)(x).s1, (half)(x).s2, (half)(x).s3)) 9 10#define DK_VEC (DK/4) 11#define DV_VEC (DV/4) 12#define WG_SIZE (BLOCK_M) 13// q1 reduces over a Q1_WG_SIZE-wide WG via work-group barriers; the launch WG 14// must match. Defaults to the Adreno sg (64); host passes -D FA_SG=32 on Intel. 15#ifndef FA_SG 16#define FA_SG 64 17#endif 18#define Q1_WG_SIZE FA_SG 19 20// The kernels are built with -cl-finite-math-only. On some older Adreno GPUs, 21// infinite operand can cause undefined behavior and miscompilation for exp. 22// Therefore, a large negative value is used instead. 23#define FA_M_INIT (-3.0e38f) 24 25// Drop full unroll at DK>=192 — Adreno compiler host-memory budget. 26#if DK >= 192 27#define FA_UNROLL 28#else 29#define FA_UNROLL _Pragma("unroll" ) 30#endif 31 32inline float get_alibi_slope( 33 const float max_bias, const uint h, const uint n_head_log2, const float m0, const float m1 34) { 35 if (max_bias <= 0.0f) { 36 return 1.0f; 37 } 38 const float base = h < n_head_log2 ? m0 : m1; 39 const int exph = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1; 40 41 return pow(base, exph); 42} 43__kernel void flash_attn_f16( 44 const global void * q_void, ulong q_offset, 45 const global void * k_void, ulong k_offset, 46 const global void * v_void, ulong v_offset, 47 global void * o_void, ulong o_offset, 48 const float scale, 49 const int n_q, 50 const int n_kv, 51 const int is_causal, 52 const int n_head, 53 const ulong q_nb1, const ulong q_nb2, const ulong q_nb3, 54 const ulong k_nb1, const ulong k_nb2, const ulong k_nb3, 55 const ulong v_nb1, const ulong v_nb2, const ulong v_nb3, 56 const ulong o_nb1, const ulong o_nb2, const ulong o_nb3, 57 const float max_bias, 58 const float m0, 59 const float m1, 60 const int n_head_log2, 61 const float logit_softcap, 62 const int n_head_kv, 63 const global void* mask_void, 64 const ulong mask_offset, 65 const ulong mask_nb1, 66 const ulong mask_nb2, 67 const ulong mask_nb3, 68 const int mask_ne2, 69 const int mask_ne3, 70 const global void* sinks_void, 71 const ulong sinks_offset 72) { 73 const int tid = get_local_id(0); 74 const int block_q_idx = get_group_id(0); 75 const int head_batch_idx = get_global_id(1); 76 77 const int my_query_row = block_q_idx * BLOCK_M + tid; 78 79 const int batch_idx = head_batch_idx / n_head; 80 const int head_idx = head_batch_idx % n_head; 81 82 const int gqa_ratio = n_head / n_head_kv; 83 const int head_kv_idx = head_idx / gqa_ratio; 84 85 const global char* q_base = (const global char*)q_void + q_offset; 86 const global char* k_base = (const global char*)k_void + k_offset; 87 const global char* v_base = (const global char*)v_void + v_offset; 88 global char* o_base = (global char*)o_void + o_offset; 89 90 const global char* mask_base = NULL; 91 if (mask_void != NULL) { 92 const int mask_head_idx = head_idx % mask_ne2; 93 const int mask_batch_idx = batch_idx % mask_ne3; 94 mask_base = (const global char*)mask_void + mask_offset + mask_batch_idx * mask_nb3 + mask_head_idx * mask_nb2; 95 } 96 97 ACC_TYPE4 q_priv[DK_VEC]; 98 if (my_query_row < n_q) { 99 const ulong q_row_offset = batch_idx * q_nb3 + head_idx * q_nb2 + my_query_row * q_nb1; 100 const global DATA_TYPE4* q_ptr = (const global DATA_TYPE4*)(q_base + q_row_offset); 101 FA_UNROLL 102 for (int i = 0; i < DK_VEC; ++i) { 103 q_priv[i] = CONVERT_ACC4(q_ptr[i]); 104 } 105 } 106 107 ACC_TYPE4 o_acc[DV_VEC]; 108 FA_UNROLL 109 for (int i = 0; i < DV_VEC; ++i) { 110 o_acc[i] = (ACC_TYPE4)(0.0f); 111 } 112 ACC_TYPE m_i = FA_M_INIT; 113 ACC_TYPE l_i = 0.0f; 114 115 float slope = get_alibi_slope(max_bias, head_idx, n_head_log2, m0, m1); 116 117 __local DATA_TYPE4 l_k[BLOCK_N][DK_VEC]; 118 __local DATA_TYPE4 l_v[BLOCK_N][DV_VEC]; 119 120 for (int k_start = 0; k_start < n_kv; k_start += BLOCK_N) { 121#if WG_SIZE > FA_SG 122 // WAR on l_k/l_v: a thread that finishes the compute below early — either 123 // it skipped it (my_query_row >= n_q, the continue) or its subgroup simply 124 // ran ahead — wraps around and reloads the tiles while another subgroup is 125 // still reading them. Any WG that is exactly one lockstep subgroup 126 // (WG_SIZE == FA_SG) cannot diverge and hides this; a WG spanning multiple 127 // subgroups (Intel sg=32, or BLOCK_M > 64 on Adreno) corrupts the result. 128 // All threads reach this each iteration (no-op on the first), so it does 129 // not diverge with the continue. Compiled out when WG == one subgroup. 130 barrier(CLK_LOCAL_MEM_FENCE); 131#endif 132 for (int i = tid; i < BLOCK_N * DK_VEC; i += WG_SIZE) { 133 const int row = i / DK_VEC; 134 const int col = i % DK_VEC; 135 const int k_row_idx = k_start + row; 136 if (k_row_idx < n_kv) { 137 const ulong k_row_offset = batch_idx * k_nb3 + head_kv_idx * k_nb2 + k_row_idx * k_nb1; 138 l_k[row][col] = ((__global DATA_TYPE4*)(k_base + k_row_offset))[col]; 139 } 140 } 141 for (int i = tid; i < BLOCK_N * DV_VEC; i += WG_SIZE) { 142 const int row = i / DV_VEC; 143 const int col = i % DV_VEC; 144 const int v_row_idx = k_start + row; 145 if (v_row_idx < n_kv) { 146 const ulong v_row_offset = batch_idx * v_nb3 + head_kv_idx * v_nb2 + v_row_idx * v_nb1; 147 l_v[row][col] = ((__global DATA_TYPE4*)(v_base + v_row_offset))[col]; 148 } 149 } 150 barrier(CLK_LOCAL_MEM_FENCE); 151 152 if (my_query_row >= n_q) { 153 continue; 154 } 155 156 for (int j = 0; j < BLOCK_N; j += 4) { 157 const int k_row0 = k_start + j; 158 const int k_row1 = k_start + j + 1; 159 const int k_row2 = k_start + j + 2; 160 const int k_row3 = k_start + j + 3; 161 162 ACC_TYPE4 dot_acc0 = (ACC_TYPE4)(0.0f); 163 ACC_TYPE4 dot_acc1 = (ACC_TYPE4)(0.0f); 164 ACC_TYPE4 dot_acc2 = (ACC_TYPE4)(0.0f); 165 ACC_TYPE4 dot_acc3 = (ACC_TYPE4)(0.0f); 166 FA_UNROLL 167 for (int k = 0; k < DK_VEC; k++) { 168 const ACC_TYPE4 qk = q_priv[k]; 169 dot_acc0 = mad(qk, CONVERT_ACC4(l_k[j][k]), dot_acc0); 170 dot_acc1 = mad(qk, CONVERT_ACC4(l_k[j+1][k]), dot_acc1); 171 dot_acc2 = mad(qk, CONVERT_ACC4(l_k[j+2][k]), dot_acc2); 172 dot_acc3 = mad(qk, CONVERT_ACC4(l_k[j+3][k]), dot_acc3); 173 } 174 ACC_TYPE s0 = (dot_acc0.s0 + dot_acc0.s1 + dot_acc0.s2 + dot_acc0.s3) * scale; 175 ACC_TYPE s1 = (dot_acc1.s0 + dot_acc1.s1 + dot_acc1.s2 + dot_acc1.s3) * scale; 176 ACC_TYPE s2 = (dot_acc2.s0 + dot_acc2.s1 + dot_acc2.s2 + dot_acc2.s3) * scale; 177 ACC_TYPE s3 = (dot_acc3.s0 + dot_acc3.s1 + dot_acc3.s2 + dot_acc3.s3) * scale; 178 179 if (is_causal) { 180 const int causal_limit = n_kv - n_q + my_query_row; 181 if (k_row0 > causal_limit) s0 = FA_M_INIT; 182 if (k_row1 > causal_limit) s1 = FA_M_INIT; 183 if (k_row2 > causal_limit) s2 = FA_M_INIT; 184 if (k_row3 > causal_limit) s3 = FA_M_INIT; 185 } 186 if (k_row0 >= n_kv) s0 = FA_M_INIT; 187 if (k_row1 >= n_kv) s1 = FA_M_INIT; 188 if (k_row2 >= n_kv) s2 = FA_M_INIT; 189 if (k_row3 >= n_kv) s3 = FA_M_INIT; 190 191 if (mask_base != NULL) { 192 const global DATA_TYPE* mask_ptr = (const global DATA_TYPE*)(mask_base + my_query_row * mask_nb1); 193 if (k_row0 < n_kv) s0 += slope * (ACC_TYPE)mask_ptr[k_row0]; 194 if (k_row1 < n_kv) s1 += slope * (ACC_TYPE)mask_ptr[k_row1]; 195 if (k_row2 < n_kv) s2 += slope * (ACC_TYPE)mask_ptr[k_row2]; 196 if (k_row3 < n_kv) s3 += slope * (ACC_TYPE)mask_ptr[k_row3]; 197 } 198 199 if (logit_softcap > 0.0f) { 200 s0 = logit_softcap * tanh(s0 / logit_softcap); 201 s1 = logit_softcap * tanh(s1 / logit_softcap); 202 s2 = logit_softcap * tanh(s2 / logit_softcap); 203 s3 = logit_softcap * tanh(s3 / logit_softcap); 204 } 205 206 const ACC_TYPE m_new = max(m_i, max(max(s0, s1), max(s2, s3))); 207 const ACC_TYPE scale_prev = native_exp(m_i - m_new); 208 const ACC_TYPE p0 = native_exp(s0 - m_new); 209 const ACC_TYPE p1 = native_exp(s1 - m_new); 210 const ACC_TYPE p2 = native_exp(s2 - m_new); 211 const ACC_TYPE p3 = native_exp(s3 - m_new); 212 213 FA_UNROLL 214 for (int i = 0; i < DV_VEC; ++i) { 215 o_acc[i] = mad(p3, CONVERT_ACC4(l_v[j+3][i]), 216 mad(p2, CONVERT_ACC4(l_v[j+2][i]), 217 mad(p1, CONVERT_ACC4(l_v[j+1][i]), 218 mad(p0, CONVERT_ACC4(l_v[j][i]), 219 o_acc[i] * scale_prev)))); 220 } 221 l_i = l_i * scale_prev + p0 + p1 + p2 + p3; 222 m_i = m_new; 223 } 224 } 225 226 if (my_query_row < n_q) { 227 if (sinks_void != NULL) { 228 const global ACC_TYPE* sinks_ptr = (const global ACC_TYPE*)((const global char*)sinks_void + sinks_offset); 229 const ACC_TYPE m_sink = sinks_ptr[head_idx]; 230 const ACC_TYPE m_final = max(m_i, m_sink); 231 232 const ACC_TYPE scale_o = exp(m_i - m_final); 233 FA_UNROLL 234 for (int i = 0; i < DV_VEC; ++i) { 235 o_acc[i] *= scale_o; 236 } 237 238 l_i = l_i * exp(m_i - m_final) + exp(m_sink - m_final); 239 } 240 241 const ulong o_row_offset = batch_idx * o_nb3 + my_query_row * o_nb2 + head_idx * o_nb1; 242 global DATA_TYPE4 *o_row = (global DATA_TYPE4 *)(o_base + o_row_offset); 243 if (l_i > 0.0f) { 244 const ACC_TYPE l_inv = 1.0f / l_i; 245 FA_UNROLL 246 for (int i = 0; i < DV_VEC; ++i) { 247 o_row[i] = CONVERT_DATA4(o_acc[i] * l_inv); 248 } 249 } else { 250 FA_UNROLL 251 for (int i = 0; i < DV_VEC; ++i) { 252 o_row[i] = (DATA_TYPE4)(0.0f); 253 } 254 } 255 } 256} 257 258__kernel void flash_attn_f16_q1( 259 const global void * q_void, ulong q_offset, 260 const global void * k_void, ulong k_offset, 261 const global void * v_void, ulong v_offset, 262 global void * o_void, ulong o_offset, 263 const float scale, 264 const int n_q, 265 const int n_kv, 266 const int is_causal, 267 const int n_head, 268 const ulong q_nb1, const ulong q_nb2, const ulong q_nb3, 269 const ulong k_nb1, const ulong k_nb2, const ulong k_nb3, 270 const ulong v_nb1, const ulong v_nb2, const ulong v_nb3, 271 const ulong o_nb1, const ulong o_nb2, const ulong o_nb3, 272 const float max_bias, 273 const float m0, 274 const float m1, 275 const int n_head_log2, 276 const float logit_softcap, 277 const int n_head_kv, 278 const global void* mask_void, 279 const ulong mask_offset, 280 const ulong mask_nb1, 281 const ulong mask_nb2, 282 const ulong mask_nb3, 283 const int mask_ne2, 284 const int mask_ne3, 285 const global void* sinks_void, 286 const ulong sinks_offset 287) { 288 const int tid = get_local_id(0); 289 const int head_batch_idx = get_global_id(1); 290 291 const int batch_idx = head_batch_idx / n_head; 292 const int head_idx = head_batch_idx % n_head; 293 294 const int gqa_ratio = n_head / n_head_kv; 295 const int head_kv_idx = head_idx / gqa_ratio; 296 297 const global char* q_base = (const global char*)q_void + q_offset; 298 const global char* k_base = (const global char*)k_void + k_offset; 299 const global char* v_base = (const global char*)v_void + v_offset; 300 global char* o_base = (global char*)o_void + o_offset; 301 302 const global char* mask_base = NULL; 303 if (mask_void != NULL) { 304 const int mask_head_idx = head_idx % mask_ne2; 305 const int mask_batch_idx = batch_idx % mask_ne3; 306 mask_base = (const global char*)mask_void + mask_offset + mask_batch_idx * mask_nb3 + mask_head_idx * mask_nb2; 307 } 308 309 ACC_TYPE4 q_priv[DK_VEC]; 310 const ulong q_row_offset = batch_idx * q_nb3 + head_idx * q_nb2; 311 const global DATA_TYPE4* q_ptr = (const global DATA_TYPE4*)(q_base + q_row_offset); 312 FA_UNROLL 313 for (int i = 0; i < DK_VEC; ++i) { 314 q_priv[i] = CONVERT_ACC4(q_ptr[i]); 315 } 316 317 float slope = get_alibi_slope(max_bias, head_idx, n_head_log2, m0, m1); 318 319 const global ACC_TYPE* sinks_ptr = NULL; 320 if (sinks_void != NULL) { 321 sinks_ptr = (const global ACC_TYPE*)((const global char*)sinks_void + sinks_offset); 322 } 323 324 ACC_TYPE m_i = (sinks_ptr != NULL) ? sinks_ptr[head_idx] : FA_M_INIT; 325 for (int k_idx = tid; k_idx < n_kv; k_idx += Q1_WG_SIZE) { 326 const ulong k_row_offset = batch_idx * k_nb3 + head_kv_idx * k_nb2 + k_idx * k_nb1; 327 const global DATA_TYPE4* k_ptr = (const global DATA_TYPE4*)(k_base + k_row_offset); 328 ACC_TYPE4 dot_acc = (ACC_TYPE4)(0.0f); 329 FA_UNROLL 330 for (int k = 0; k < DK_VEC; k++) { 331 dot_acc = mad(q_priv[k], CONVERT_ACC4(k_ptr[k]), dot_acc); 332 } 333 ACC_TYPE score = (dot_acc.s0 + dot_acc.s1 + dot_acc.s2 + dot_acc.s3) * scale; 334 if (mask_base != NULL) { 335 const global DATA_TYPE* mask_ptr = (const global DATA_TYPE*)(mask_base); 336 score += slope * (ACC_TYPE)mask_ptr[k_idx]; 337 } 338 if (logit_softcap > 0.0f) { 339 score = logit_softcap * tanh(score / logit_softcap); 340 } 341 m_i = max(m_i, score); 342 } 343 344 __local ACC_TYPE local_m[Q1_WG_SIZE]; 345 local_m[tid] = m_i; 346 barrier(CLK_LOCAL_MEM_FENCE); 347 FA_UNROLL 348 for (int s = Q1_WG_SIZE / 2; s > 0; s >>= 1) { 349 if (tid < s) local_m[tid] = max(local_m[tid], local_m[tid + s]); 350 barrier(CLK_LOCAL_MEM_FENCE); 351 } 352 const ACC_TYPE m_final = local_m[0]; 353 354 ACC_TYPE4 o_acc[DV_VEC]; 355 FA_UNROLL 356 for (int i = 0; i < DV_VEC; ++i) o_acc[i] = (ACC_TYPE4)(0.0f); 357 ACC_TYPE l_i = 0.0f; 358 359 for (int k_idx = tid; k_idx < n_kv; k_idx += Q1_WG_SIZE) { 360 const ulong k_row_offset = batch_idx * k_nb3 + head_kv_idx * k_nb2 + k_idx * k_nb1; 361 const ulong v_row_offset = batch_idx * v_nb3 + head_kv_idx * v_nb2 + k_idx * v_nb1; 362 const global DATA_TYPE4* k_ptr = (const global DATA_TYPE4*)(k_base + k_row_offset); 363 const global DATA_TYPE4* v_ptr = (const global DATA_TYPE4*)(v_base + v_row_offset); 364 ACC_TYPE4 dot_acc = (ACC_TYPE4)(0.0f); 365 FA_UNROLL 366 for (int k = 0; k < DK_VEC; k++) { 367 dot_acc = mad(q_priv[k], CONVERT_ACC4(k_ptr[k]), dot_acc); 368 } 369 ACC_TYPE score = (dot_acc.s0 + dot_acc.s1 + dot_acc.s2 + dot_acc.s3) * scale; 370 if (mask_base != NULL) { 371 const global DATA_TYPE* mask_ptr = (const global DATA_TYPE*)(mask_base); 372 score += slope * (ACC_TYPE)mask_ptr[k_idx]; 373 } 374 if (logit_softcap > 0.0f) { 375 score = logit_softcap * tanh(score / logit_softcap); 376 } 377 const ACC_TYPE p = exp(score - m_final); 378 l_i += p; 379 FA_UNROLL 380 for (int i = 0; i < DV_VEC; i++) { 381 o_acc[i] = mad(p, CONVERT_ACC4(v_ptr[i]), o_acc[i]); 382 } 383 } 384 385 __local ACC_TYPE local_l[Q1_WG_SIZE]; 386 __local ACC_TYPE4 local_o_comp[Q1_WG_SIZE]; 387 local_l[tid] = l_i; 388 barrier(CLK_LOCAL_MEM_FENCE); 389 FA_UNROLL 390 for (int s = Q1_WG_SIZE / 2; s > 0; s >>= 1) { 391 if (tid < s) local_l[tid] += local_l[tid + s]; 392 barrier(CLK_LOCAL_MEM_FENCE); 393 } 394 395 const ulong o_row_offset = batch_idx * o_nb3 + head_idx * o_nb1; 396 global DATA_TYPE4 *o_row = (global DATA_TYPE4 *)(o_base + o_row_offset); 397 ACC_TYPE l_final = local_l[0]; 398 399 if (sinks_ptr != NULL) { 400 l_final += exp(sinks_ptr[head_idx] - m_final); 401 } 402 403 if (l_final > 0.0f) { 404 const ACC_TYPE l_inv = 1.0f / l_final; 405 for (int i = 0; i < DV_VEC; i++) { 406 local_o_comp[tid] = o_acc[i]; 407 barrier(CLK_LOCAL_MEM_FENCE); 408 FA_UNROLL 409 for (int s = Q1_WG_SIZE / 2; s > 0; s >>= 1) { 410 if (tid < s) local_o_comp[tid] += local_o_comp[tid + s]; 411 barrier(CLK_LOCAL_MEM_FENCE); 412 } 413 if (tid == 0) { 414 o_row[i] = CONVERT_DATA4(local_o_comp[0] * l_inv); 415 } 416 } 417 } else if (tid == 0) { 418 FA_UNROLL 419 for (int i = 0; i < DV_VEC; ++i) o_row[i] = (DATA_TYPE4)(0.0f); 420 } 421}