char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
5112b9738
char/aliceai-t5-moe
1#ifdef USE_SUBGROUP_REDUCTION 2enable subgroups; 3#endif 4enable f16; 5 6#ifdef MMVQ 7requires packed_4x8_integer_dot_product; 8#endif 9 10#ifdef SRC_OVERLAP 11#define SRC0 merged_src 12#define SRC1 merged_src 13#endif 14 15#define DECLARE_BYTE_LOADERS_SRC0 16#include "common_decls.tmpl" 17 18#ifdef MMVQ 19#include "mul_mat_vec_q_acc.tmpl" 20#else 21#include "mul_mat_vec_acc.tmpl" 22#endif 23 24struct MulMatParams { 25 offset_src0: u32, 26 offset_src1: u32, 27 offset_dst: u32, 28 m: u32, 29 n: u32, 30 k: u32, 31 stride_01: u32, 32 stride_11: u32, 33 stride_02: u32, 34 stride_12: u32, 35 stride_03: u32, 36 stride_13: u32, 37 bs02: u32, 38 bs03: u32, 39 broadcast2: u32, 40 broadcast3: u32 41}; 42 43#if defined(MMVQ) 44@group(0) @binding(0) var<storage, read_write> src0: array<SRC0_TYPE>; 45@group(0) @binding(1) var<storage, read_write> src1q: array<q8_1>; 46#define DST_BINDING 2 47#elif defined(SRC_OVERLAP) 48@group(0) @binding(0) var<storage, read_write> merged_src: array<SRC0_TYPE>; 49#define DST_BINDING 1 50#else 51@group(0) @binding(0) var<storage, read_write> src0: array<SRC0_TYPE>; 52@group(0) @binding(1) var<storage, read_write> src1: array<SRC1_TYPE>; 53#define DST_BINDING 2 54#endif 55 56@group(0) @binding(DST_BINDING) var<storage, read_write> dst: array<f32>; 57// "mul_mat_vec_acc.tmpl" requires params.k, params.m, params.stride_01 58@group(0) @binding(DST_BINDING + 1) var<uniform> params: MulMatParams; 59 60// Flattened as [row][thread] to keep each row's reduction contiguous in memory. 61var<workgroup> partial_sums: array<f32, OUTPUTS_PER_WG * WG_SIZE>; 62 63fn partial_index(row: u32, thread: u32) -> u32 { 64 return row * WG_SIZE + thread; 65} 66 67@compute @workgroup_size(WG_SIZE) 68fn main( 69 @builtin(local_invocation_id) local_id: vec3<u32>, 70 @builtin(workgroup_id) wg_id: vec3<u32>, 71 @builtin(num_workgroups) num_wg: vec3<u32> 72#ifdef USE_SUBGROUP_REDUCTION 73 , @builtin(subgroup_id) subgroup_id: u32, 74 @builtin(subgroup_invocation_id) subgroup_invocation_id: u32, 75 @builtin(num_subgroups) num_subgroups: u32, 76 @builtin(subgroup_size) subgroup_size: u32 77#endif 78) { 79 let thread_id = local_id.x; 80 81 let total_batches = params.bs02 * params.broadcast2 * params.bs03 * params.broadcast3; 82 let wg_linear = wg_id.y * num_wg.x + wg_id.x; 83 let output_groups = (params.m + OUTPUTS_PER_WG - 1u) / OUTPUTS_PER_WG; 84 let batch_idx = wg_linear / output_groups; 85 if (batch_idx >= total_batches) { 86 return; 87 } 88 89 let row_base = (wg_linear % output_groups) * OUTPUTS_PER_WG; 90 91 let dst2_stride = params.m * params.n; 92 let dst2_idx = batch_idx % (params.bs02 * params.broadcast2); 93 let dst3_stride = dst2_stride * params.bs02 * params.broadcast2; 94 let dst3_idx = batch_idx / (params.bs02 * params.broadcast2); 95 let src03_idx = dst3_idx / params.broadcast3; 96 let src13_idx = dst3_idx; 97 let src02_idx = dst2_idx / params.broadcast2; 98 let src12_idx = dst2_idx; 99 100 let src0_batch_offset = params.offset_src0 + src03_idx * params.stride_03 + src02_idx * params.stride_02; 101 let dst_idx_base = params.offset_dst + dst3_idx * dst3_stride + dst2_idx * dst2_stride + row_base; 102 103#ifdef MMVQ 104 let src1q_idx_base = (src13_idx * params.bs02 * params.broadcast2 + src12_idx) * params.n * (params.k / 32u); 105 let acc = accumulate_vec_q_dot(thread_id, row_base, src0_batch_offset, src1q_idx_base); 106#else 107 let src1_idx_base = params.offset_src1 + src13_idx * params.stride_13 + src12_idx * params.stride_12; 108 let acc = accumulate_vec_dot(thread_id, row_base, src0_batch_offset, src1_idx_base); 109#endif 110 111 for (var col = 0u;col < NUM_COLS;col += 1) { 112 113#ifdef USE_SUBGROUP_REDUCTION 114 for (var row = 0u; row < OUTPUTS_PER_WG; row++) { 115 let subgroup_total = subgroupAdd(acc[col][row]); 116 if (subgroup_invocation_id == 0u) { 117 partial_sums[partial_index(row, subgroup_id)] = subgroup_total; 118 } 119 } 120 121 workgroupBarrier(); 122 123 for (var row = subgroup_id; (row < OUTPUTS_PER_WG) && (row_base + row < params.m); row += num_subgroups) { 124 let output_row = row_base + row; 125 var row_acc = 0.0f; 126 for (var k = subgroup_invocation_id; k < num_subgroups; k += subgroup_size) { 127 row_acc += partial_sums[partial_index(row, k)]; 128 } 129 let row_total = subgroupAdd(row_acc); 130 if (subgroup_invocation_id == 0) { 131 dst[dst_idx_base + col * params.m + row] = row_total; 132 } 133 } 134#endif 135 136#ifdef USE_WORKGROUP_REDUCTION 137 for (var row = 0u; row < OUTPUTS_PER_WG; row++) { 138 partial_sums[partial_index(row, thread_id)] = acc[col][row]; 139 } 140 141 workgroupBarrier(); 142 143 var stride = WG_SIZE / 2u; 144 145 while (stride > 0) { 146 if (thread_id < stride) { 147 for (var row = 0u; row < OUTPUTS_PER_WG; row++) { 148 partial_sums[partial_index(row, thread_id)] += partial_sums[partial_index(row, thread_id + stride)]; 149 } 150 } 151 152 workgroupBarrier(); 153 stride = stride / 2; 154 } 155 156 if (thread_id < OUTPUTS_PER_WG) { 157 let output_row = row_base + thread_id; 158 if (output_row < params.m) { 159 dst[dst_idx_base + col * params.m + thread_id] = partial_sums[partial_index(thread_id, 0)]; 160 } 161 } 162#endif 163 164 workgroupBarrier(); 165 166 } 167}