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