char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
1692f9e50
char/aliceai-t5-moe
1#ifdef USE_SUBGROUP_REDUCTION 2enable subgroups; 3#endif 4 5struct Params { 6 offset_s: u32, 7 offset_x: u32, 8 offset_dt: u32, 9 offset_A: u32, 10 offset_B: u32, 11 offset_C: u32, 12 offset_ids: u32, 13 offset_dst: u32, 14 15 stride_s1: u32, 16 stride_s2: u32, 17 stride_s3: u32, 18 19 stride_x1: u32, 20 stride_x2: u32, 21 stride_x3: u32, 22 23 stride_dt1: u32, 24 stride_dt2: u32, 25 26 a_ne0: u32, 27 stride_A1: u32, 28 29 stride_B1: u32, 30 stride_B2: u32, 31 stride_B3: u32, 32 33 stride_C1: u32, 34 stride_C2: u32, 35 stride_C3: u32, 36 37 d_state: u32, 38 d_inner: u32, 39 n_head: u32, 40 n_group: u32, 41 n_seq_tokens: u32, 42 43 y_elems: u32, 44 K: u32, 45}; 46 47@group(0) @binding(0) var<storage, read_write> s_in: array<f32>; 48#ifdef XBC_OVERLAP 49#ifdef IDS_OVERLAP 50@group(0) @binding(1) var<storage, read_write> x_dt_B_C_ids_merged: array<u32>; 51#ifdef A_OVERLAP 52@group(0) @binding(2) var<storage, read_write> dst: array<f32>; 53@group(0) @binding(3) var<uniform> params: Params; 54#else 55@group(0) @binding(2) var<storage, read_write> A: array<f32>; 56@group(0) @binding(3) var<storage, read_write> dst: array<f32>; 57@group(0) @binding(4) var<uniform> params: Params; 58#endif 59#else 60@group(0) @binding(1) var<storage, read_write> x_dt_B_C_merged: array<f32>; 61#ifdef A_OVERLAP 62@group(0) @binding(2) var<storage, read_write> ids: array<i32>; 63@group(0) @binding(3) var<storage, read_write> dst: array<f32>; 64@group(0) @binding(4) var<uniform> params: Params; 65#else 66@group(0) @binding(2) var<storage, read_write> A: array<f32>; 67@group(0) @binding(3) var<storage, read_write> ids: array<i32>; 68@group(0) @binding(4) var<storage, read_write> dst: array<f32>; 69@group(0) @binding(5) var<uniform> params: Params; 70#endif 71#endif 72#else 73@group(0) @binding(1) var<storage, read_write> x: array<f32>; 74@group(0) @binding(2) var<storage, read_write> dt: array<f32>; 75@group(0) @binding(3) var<storage, read_write> A: array<f32>; 76@group(0) @binding(4) var<storage, read_write> B: array<f32>; 77@group(0) @binding(5) var<storage, read_write> C: array<f32>; 78@group(0) @binding(6) var<storage, read_write> ids: array<i32>; 79@group(0) @binding(7) var<storage, read_write> dst: array<f32>; 80@group(0) @binding(8) var<uniform> params: Params; 81#endif 82 83var<workgroup> shared_x_dt: array<f32, TOKENS_PER_TILE>; 84var<workgroup> shared_dtsp: array<f32, TOKENS_PER_TILE>; 85var<workgroup> shared_reduce: array<f32, TOKENS_PER_TILE * WG_SIZE>; 86 87fn reduce_base(token_in_tile: u32) -> u32 { 88 return token_in_tile * WG_SIZE; 89} 90 91#ifdef XBC_OVERLAP 92fn read_merged_f32(idx: u32) -> f32 { 93#ifdef IDS_OVERLAP 94 return bitcast<f32>(x_dt_B_C_ids_merged[idx]); 95#else 96 return x_dt_B_C_merged[idx]; 97#endif 98} 99#endif 100 101fn read_state_slot(i3: u32) -> u32 { 102#ifdef IDS_OVERLAP 103 return x_dt_B_C_ids_merged[params.offset_ids + i3]; 104#else 105 return u32(ids[params.offset_ids + i3]); 106#endif 107} 108 109@compute @workgroup_size(WG_SIZE) 110fn main( 111 @builtin(local_invocation_id) local_id: vec3<u32>, 112 @builtin(workgroup_id) wg_id: vec3<u32>, 113 @builtin(num_workgroups) num_wg: vec3<u32> 114#ifdef USE_SUBGROUP_REDUCTION 115 , @builtin(subgroup_id) subgroup_id: u32, 116 @builtin(subgroup_invocation_id) subgroup_invocation_id: u32, 117 @builtin(num_subgroups) num_subgroups: u32 118#endif 119) { 120 let tid = local_id.x; 121 let wg_linear = wg_id.y * num_wg.x + wg_id.x; 122 123 let i1 = wg_linear % params.d_inner; 124 let head_seq = wg_linear / params.d_inner; 125 let ir = head_seq % params.n_head; 126 let i3 = head_seq / params.n_head; 127 let n_seqs = params.y_elems / (params.n_seq_tokens * params.n_head * params.d_inner); 128 129 let state_slot = read_state_slot(i3); 130 let g = ir / (params.n_head / params.n_group); 131 132 let s_idx = params.offset_s + tid + i1 * params.stride_s1 + ir * params.stride_s2 + state_slot * params.stride_s3; 133 var s_prev = s_in[s_idx]; 134 135 let a_idx = params.offset_A + (tid % params.a_ne0) + ir * params.stride_A1; 136#ifdef A_OVERLAP 137 let A0 = read_merged_f32(a_idx); 138#else 139 let A0 = A[a_idx]; 140#endif 141 142 for (var token_base = 0u; token_base < params.n_seq_tokens; token_base += TOKENS_PER_TILE) { 143 if (tid < TOKENS_PER_TILE) { 144 let token = token_base + tid; 145 if (token < params.n_seq_tokens) { 146 let x_idx = params.offset_x + i1 + ir * params.stride_x1 + token * params.stride_x2 + i3 * params.stride_x3; 147 let dt_idx = params.offset_dt + ir + token * params.stride_dt1 + i3 * params.stride_dt2; 148#ifdef XBC_OVERLAP 149 let dt0 = read_merged_f32(dt_idx); 150#else 151 let dt0 = dt[dt_idx]; 152#endif 153 let dtsp = select(log(1.0 + exp(dt0)), dt0, dt0 > 20.0); 154 shared_dtsp[tid] = dtsp; 155#ifdef XBC_OVERLAP 156 shared_x_dt[tid] = read_merged_f32(x_idx) * dtsp; 157#else 158 shared_x_dt[tid] = x[x_idx] * dtsp; 159#endif 160 } 161 } 162 163 workgroupBarrier(); 164 165 for (var token_in_tile = 0u; token_in_tile < TOKENS_PER_TILE; token_in_tile++) { 166 let token = token_base + token_in_tile; 167 if (token >= params.n_seq_tokens) { 168 break; 169 } 170 171 let x_dt = shared_x_dt[token_in_tile]; 172 let dA = exp(shared_dtsp[token_in_tile] * A0); 173 let reduce_idx = reduce_base(token_in_tile) + tid; 174 175 let b_idx = params.offset_B + tid + g * params.stride_B1 + token * params.stride_B2 + i3 * params.stride_B3; 176 let c_idx = params.offset_C + tid + g * params.stride_C1 + token * params.stride_C2 + i3 * params.stride_C3; 177#ifdef XBC_OVERLAP 178 let s = s_prev * dA + read_merged_f32(b_idx) * x_dt; 179#else 180 let s = s_prev * dA + B[b_idx] * x_dt; 181#endif 182 s_prev = s; 183 184 let slot = params.n_seq_tokens - 1u - token; 185 if (slot > 0u && slot < params.K) { 186 let snapshot_idx = 187 params.offset_dst + params.y_elems + tid + i1 * params.d_state + 188 ir * (params.d_state * params.d_inner) + 189 (slot * n_seqs + i3) * (params.d_state * params.d_inner * params.n_head); 190 dst[snapshot_idx] = s; 191 } 192 193#ifdef USE_SUBGROUP_REDUCTION 194#ifdef XBC_OVERLAP 195 let subgroup_partial = subgroupAdd(s * read_merged_f32(c_idx)); 196#else 197 let subgroup_partial = subgroupAdd(s * C[c_idx]); 198#endif 199 if (subgroup_invocation_id == 0u) { 200 shared_reduce[reduce_idx - tid + subgroup_id] = subgroup_partial; 201 } 202#else 203#ifdef XBC_OVERLAP 204 shared_reduce[reduce_idx] = s * read_merged_f32(c_idx); 205#else 206 shared_reduce[reduce_idx] = s * C[c_idx]; 207#endif 208#endif 209 210 workgroupBarrier(); 211 212#ifdef USE_SUBGROUP_REDUCTION 213 if (tid == 0u) { 214 var sum = 0.0; 215 for (var sg = 0u; sg < num_subgroups; sg++) { 216 sum += shared_reduce[reduce_base(token_in_tile) + sg]; 217 } 218 let y_idx = 219 params.offset_dst + i1 + ir * params.d_inner + token * (params.n_head * params.d_inner) + 220 i3 * (params.n_seq_tokens * params.n_head * params.d_inner); 221 dst[y_idx] = sum; 222 } 223#else 224 for (var stride = WG_SIZE / 2u; stride > 0u; stride >>= 1u) { 225 if (tid < stride) { 226 shared_reduce[reduce_idx] += shared_reduce[reduce_idx + stride]; 227 } 228 workgroupBarrier(); 229 } 230 231 if (tid == 0u) { 232 let y_idx = 233 params.offset_dst + i1 + ir * params.d_inner + token * (params.n_head * params.d_inner) + 234 i3 * (params.n_seq_tokens * params.n_head * params.d_inner); 235 dst[y_idx] = shared_reduce[reduce_base(token_in_tile)]; 236 } 237#endif 238 239 workgroupBarrier(); 240 } 241 } 242 243 let state_idx = 244 params.offset_dst + params.y_elems + tid + i1 * params.d_state + ir * (params.d_state * params.d_inner) + 245 i3 * (params.d_state * params.d_inner * params.n_head); 246 dst[state_idx] = s_prev; 247}