char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
20d3bc2cc
char/aliceai-t5-moe
1enable f16; 2 3#define DECLARE_BYTE_LOADERS_SRC0 4#include "common_decls.tmpl" 5 6#include "mul_mat_decls.tmpl" 7 8#ifdef VEC 9fn store_val(acc: array<array<f16, TILE_M>, TILE_N>, tn: u32, tm: u32) -> vec4<f32> { 10 return vec4<f32>(f32(acc[tn][tm]), f32(acc[tn][tm + 1]), f32(acc[tn][tm + 2]), f32(acc[tn][tm + 3])); 11} 12#endif 13 14#ifdef SCALAR 15fn store_val(acc: array<array<f16, TILE_M>, TILE_N>, tn: u32, tm: u32) -> f32 { 16 return f32(acc[tn][tm]); 17} 18#endif 19 20struct MulMatIdParams { 21 offset_src0: u32, 22 offset_src1: u32, 23 offset_dst: u32, 24 25 k: u32, 26 m: u32, 27 n_expert: u32, 28 n_expert_used: u32, 29 n_tokens: u32, 30 b_ne1: u32, 31 32 stride_01: u32, 33 stride_11: u32, 34 stride_02: u32, 35 stride_12: u32, 36}; 37 38@group(0) @binding(0) var<storage, read_write> src0: array<SRC0_TYPE>; // [cols, rows, n_expert] 39@group(0) @binding(1) var<storage, read_write> src1: array<SRC1_TYPE>; // [cols, b_ne1, n_tokens] 40@group(0) @binding(2) var<storage, read_write> dst: array<DST_TYPE>; // [rows, n_expert_used, n_tokens] 41@group(0) @binding(3) var<storage, read_write> global_gathered_expert_used: array<u32>; // [n_expert][n_tokens] 42@group(0) @binding(4) var<storage, read_write> global_gathered_tokens: array<u32>; // [n_expert][n_tokens] 43@group(0) @binding(5) var<storage, read_write> gathered_count_ids: array<u32>; // [n_expert] 44 45@group(0) @binding(6) var<uniform> params: MulMatIdParams; 46 47fn get_local_n(thread_id: u32) -> u32 { 48 return thread_id / WORKGROUP_SIZE_M; 49} 50fn get_local_m(thread_id: u32) -> u32 { 51 return thread_id % WORKGROUP_SIZE_M; 52} 53 54const TOTAL_WORKGROUP_SIZE = WORKGROUP_SIZE_M * WORKGROUP_SIZE_N; 55const TILE_SRC0_SHMEM = TILE_K * WORKGROUP_SIZE_M * TILE_M; 56const TILE_SRC1_SHMEM = TILE_K * WORKGROUP_SIZE_N * TILE_N; 57 58var<workgroup> shmem: array<f16, TILE_SRC0_SHMEM + TILE_SRC1_SHMEM>; 59var<workgroup> gathered_expert_used: array<u32, TILE_N * WORKGROUP_SIZE_N>; 60var<workgroup> gathered_tokens: array<u32, TILE_N * WORKGROUP_SIZE_N>; 61 62#ifdef INIT_SRC1_SHMEM_FLOAT 63fn init_shmem_id_src1(thread_id: u32, offset_src1: u32, rest_token_n: u32, k_outer: u32) { 64 for (var elem_idx = thread_id * VEC_SIZE; elem_idx < TILE_SRC1_SHMEM; elem_idx += TOTAL_WORKGROUP_SIZE * VEC_SIZE) { 65 let tile_n = elem_idx / TILE_K; 66 let tile_k = elem_idx % TILE_K; 67 if (tile_n < rest_token_n) { 68 let global_src10 = k_outer + tile_k; 69 let expert_used_idx = gathered_expert_used[tile_n] % params.b_ne1; 70 let token_idx = gathered_tokens[tile_n]; 71 let src1_idx = offset_src1 + token_idx * params.stride_12 + expert_used_idx * params.stride_11 + global_src10; 72 let src1_val = select( 73 SRC1_TYPE(0.0), 74 src1[src1_idx/VEC_SIZE], 75 global_src10 < params.k); 76 store_shmem(SHMEM_TYPE(src1_val), TILE_SRC0_SHMEM + elem_idx); 77 } else { 78 store_shmem(SHMEM_TYPE(0.0), TILE_SRC0_SHMEM + elem_idx); 79 } 80 } 81} 82#endif // INIT_SRC1_SHMEM_FLOAT 83 84@compute @workgroup_size(TOTAL_WORKGROUP_SIZE) 85fn main(@builtin(workgroup_id) wg_id: vec3<u32>, 86 @builtin(local_invocation_id) local_id: vec3<u32>, 87 @builtin(num_workgroups) num_wg: vec3<u32>) { 88 89 let thread_id = local_id.x; 90 let local_m = get_local_m(thread_id); 91 let local_n = get_local_n(thread_id); 92 93 var expert_idx:u32 = 0xFFFFFFFFu; 94 var wg_in_batch:u32 = 0; 95 var wg_sum:u32 = 0; 96 let wg_m_count = (params.m + WORKGROUP_SIZE_M * TILE_M - 1u) / (WORKGROUP_SIZE_M * TILE_M); 97 let wg_linear = wg_id.y * num_wg.x + wg_id.x; 98 99 for (var i = 0u;i < params.n_expert;i += 1) { 100 let wg_n_count = (gathered_count_ids[i] + WORKGROUP_SIZE_N * TILE_N - 1u) / (WORKGROUP_SIZE_N * TILE_N); 101 let wg_per_matrix = wg_m_count * wg_n_count; 102 if (wg_sum <= wg_linear && wg_linear < wg_sum + wg_per_matrix) { 103 expert_idx = i; 104 wg_in_batch = wg_linear - wg_sum; 105 break; 106 } 107 wg_sum += wg_per_matrix; 108 } 109 110 let is_valid = expert_idx != 0xFFFFFFFFu; 111 112 var wg_m: u32 = 0; 113 var wg_n: u32 = 0; 114 var offset_wg_m: u32 = 0; 115 var offset_wg_n: u32 = 0; 116 var rest_token_n: u32 = 0; 117 var src0_batch_offset: u32 = 0; 118 119 wg_m = wg_in_batch % wg_m_count; 120 wg_n = wg_in_batch / wg_m_count; 121 122 offset_wg_m = wg_m * WORKGROUP_SIZE_M * TILE_M; 123 offset_wg_n = wg_n * WORKGROUP_SIZE_N * TILE_N; 124 125 if (is_valid) { 126 rest_token_n = gathered_count_ids[expert_idx] - offset_wg_n; 127 let global_gathered_base = expert_idx * params.n_tokens + offset_wg_n; 128 for (var i = thread_id; i < TILE_N * WORKGROUP_SIZE_N && offset_wg_n + i < gathered_count_ids[expert_idx]; i += TOTAL_WORKGROUP_SIZE) { 129 gathered_expert_used[i] = global_gathered_expert_used[global_gathered_base + i]; 130 gathered_tokens[i] = global_gathered_tokens[global_gathered_base + i]; 131 } 132 src0_batch_offset = params.offset_src0 + expert_idx * params.stride_02; 133 } 134 135 workgroupBarrier(); 136 137 let output_row_base = offset_wg_m + local_m * TILE_M; 138 let output_col_base = offset_wg_n + local_n * TILE_N; 139 140 let dst2_stride = params.m * params.n_expert_used; 141 let dst1_stride = params.m; 142 143 var acc: array<array<f16, TILE_M>, TILE_N>; 144 145 for (var k_outer = 0u; k_outer < params.k; k_outer += TILE_K) { 146 147 if (is_valid) { 148 init_shmem_src0(thread_id, src0_batch_offset, offset_wg_m, k_outer); 149 init_shmem_id_src1(thread_id, params.offset_src1, rest_token_n, k_outer); 150 } 151 152 workgroupBarrier(); 153 154 if (is_valid) { 155 let k_end = min(TILE_K, params.k - k_outer); 156 157 for (var k_inner = 0u; k_inner < k_end; k_inner++) { 158 var src0_tile: array<f16, TILE_M>; 159 for (var tm = 0u; tm < TILE_M; tm++) { 160 let src0_m = local_m * TILE_M + tm; 161 let src0_idx = k_inner + src0_m * TILE_K; 162 src0_tile[tm] = shmem[src0_idx]; 163 } 164 for (var tn = 0u; tn < TILE_N; tn++) { 165 let src1_n = local_n * TILE_N + tn; 166 let src1_idx = src1_n * TILE_K + k_inner; 167 let src1_val = shmem[TILE_SRC0_SHMEM + src1_idx]; 168 for (var tm = 0u; tm < TILE_M; tm++) { 169 acc[tn][tm] += src0_tile[tm] * src1_val; 170 } 171 } 172 } 173 } 174 175 workgroupBarrier(); 176 } 177 178 if (is_valid) { 179 for (var tn = 0u; tn < TILE_N; tn++) { 180 let n_idx = output_col_base + tn; 181 if (n_idx < gathered_count_ids[expert_idx]) { 182 let dst1_idx = gathered_expert_used[n_idx - offset_wg_n]; 183 let dst2_idx = gathered_tokens[n_idx - offset_wg_n]; 184 let dst12_offset = params.offset_dst + dst2_idx * dst2_stride + dst1_idx * dst1_stride; 185 for (var tm = 0u; tm < TILE_M; tm += VEC_SIZE) { 186 let global_row = output_row_base + tm; 187 if (global_row < params.m) { 188 let dst_idx = dst12_offset + global_row; 189 dst[dst_idx/VEC_SIZE] = store_val(acc, tn, tm); 190 } 191 } 192 } 193 } 194 } 195}