char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
daef7b687
char/aliceai-t5-moe
1#version 450 2 3#extension GL_EXT_control_flow_attributes : enable 4#extension GL_EXT_shader_16bit_storage : require 5 6#include "types.glsl" 7 8layout(constant_id = 0) const int BLOCK_SIZE = 1024; 9layout(constant_id = 1) const int QSA = 0; // 1: fuse the qwen4 QSA indexer gather + f16 mask 10 11layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; 12 13layout (binding = 0) readonly buffer A {float data_a[];}; // input values, or QSA block scores [n_tps, n_blocks, n_stream] 14layout (binding = 1) writeonly buffer D {int data_d[];}; // [k, ...] 15layout (binding = 2) readonly buffer CB {int cell_blk[];}; // QSA: cell->block map [n_kv, n_stream] 16layout (binding = 3) readonly buffer M {float16_t mask[];}; // QSA: raw f16 kq_mask [n_kv, n_tps, n_stream] 17layout (binding = 4) buffer S {float scratch[];}; // QSA: [nrows, n_kv] gathered inputs 18 19layout (push_constant) uniform parameter { 20 uint ncols; 21 uint k; 22 uint nrows; 23 uint n_tps; // QSA only 24 uint n_blocks; // QSA only 25 uint n_stream; // QSA only 26} p; 27 28#define RADIX_BITS 8 29#define RADIX_SIZE (1 << RADIX_BITS) 30 31shared uint histo[RADIX_SIZE]; 32shared uint sh_bucket; 33shared uint sh_above; 34shared uint out_count; 35 36// order-preserving float -> uint mapping 37uint f2ui(float x) { 38 uint y = floatBitsToUint(x); 39 if ((y & 0x80000000u) != 0u) { 40 y ^= 0xFFFFFFFFu; 41 } else { 42 y |= 0x80000000u; 43 } 44 return y; 45} 46 47// QSA element i of row (t,s): score[cell_blk[i,s], t, s] + mask[i,t,s] 48float gather(uint row, uint i) { 49 const uint t = row % p.n_tps; 50 const uint s = row / p.n_tps; 51 const uint block = uint(cell_blk[s * p.ncols + i]); 52 const float a = data_a[(s * p.n_blocks + block) * p.n_tps + t]; 53 const float m = float(mask[(s * p.n_tps + t) * p.ncols + i]); 54 return a + m; 55} 56 57float load(uint row, uint i, bool first) { 58 if (QSA == 0) { 59 return data_a[row * p.ncols + i]; 60 } 61 // materialize the scattered gather on the first pass and reuse it after; each 62 // invocation only touches its own scratch entries, so no barrier is needed 63 const uint off = row * p.ncols + i; 64 if (first) { 65 const float v = gather(row, i); 66 scratch[off] = v; 67 return v; 68 } 69 return scratch[off]; 70} 71 72// one workgroup per row: radix-select the K-th largest, then compact it plus enough ties 73void topk(const uint row) { 74 const uint tid = gl_LocalInvocationID.x; 75 const uint ncols = p.ncols; 76 const uint row_out = row * p.k; 77 78 uint prefix = 0; // fixed high bits of the threshold key 79 uint desired = p.k; // count still needed from the candidate range 80 81 [[unroll]] for (int shift = 32 - RADIX_BITS; shift >= 0; shift -= RADIX_BITS) { 82 for (uint i = tid; i < RADIX_SIZE; i += BLOCK_SIZE) { 83 histo[i] = 0; 84 } 85 barrier(); 86 87 const bool first = (shift == 32 - RADIX_BITS); 88 const uint hi_mask = (shift + RADIX_BITS >= 32) ? 0u : (0xFFFFFFFFu << uint(shift + RADIX_BITS)); 89 const uint prefix_hi = prefix & hi_mask; 90 for (uint i = tid; i < ncols; i += BLOCK_SIZE) { 91 const uint key = f2ui(load(row, i, first)); 92 if ((key & hi_mask) == prefix_hi) { 93 atomicAdd(histo[(key >> uint(shift)) & (RADIX_SIZE - 1)], 1u); 94 } 95 } 96 barrier(); 97 98 // top-down scan for the bucket holding the K-th value 99 if (tid == 0) { 100 uint acc = 0; 101 uint b = 0; 102 for (int bb = RADIX_SIZE - 1; bb >= 0; --bb) { 103 const uint c = histo[bb]; 104 if (acc + c >= desired) { b = uint(bb); break; } 105 acc += c; 106 } 107 sh_bucket = b; 108 sh_above = acc; 109 } 110 barrier(); 111 112 prefix |= sh_bucket << uint(shift); 113 desired -= sh_above; 114 barrier(); 115 } 116 117 if (tid == 0) { 118 out_count = 0; 119 } 120 barrier(); 121 122 // emit everything above the threshold, then fill the rest from ties 123 const uint threshold = prefix; 124 for (uint i = tid; i < ncols; i += BLOCK_SIZE) { 125 if (f2ui(load(row, i, false)) > threshold) { 126 data_d[row_out + atomicAdd(out_count, 1u)] = int(i); 127 } 128 } 129 barrier(); 130 for (uint i = tid; i < ncols; i += BLOCK_SIZE) { 131 if (f2ui(load(row, i, false)) == threshold) { 132 const uint pos = atomicAdd(out_count, 1u); 133 if (pos < p.k) { 134 data_d[row_out + pos] = int(i); 135 } 136 } 137 } 138} 139 140void main() { 141 for (uint row = gl_WorkGroupID.y; row < p.nrows; row += gl_NumWorkGroups.y) { 142 topk(row); 143 } 144}