char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
5a460dea9
char/aliceai-t5-moe
1#include "gated_delta_net.cuh" 2#include "ggml-cuda/common.cuh" 3 4template <int S_v, bool KDA, bool keep_rs_t> 5__global__ void __launch_bounds__((ggml_cuda_get_physical_warp_size() < S_v ? ggml_cuda_get_physical_warp_size() : S_v) * 4, 2) 6gated_delta_net_cuda(const float * q, 7 const float * k, 8 const float * v, 9 const float * g, 10 const float * beta, 11 const float * curr_state, 12 float * dst, 13 float * state, 14 int64_t H, 15 int64_t n_tokens, 16 int64_t n_seqs, 17 int64_t sq1, 18 int64_t sq2, 19 int64_t sq3, 20 int64_t sv1, 21 int64_t sv2, 22 int64_t sv3, 23 int64_t sb1, 24 int64_t sb2, 25 int64_t sb3, 26 const uint3 neqk1_magic, 27 const uint3 rq3_magic, 28 float scale, 29 int64_t state_slot_stride, 30 int K) { 31 const uint32_t h_idx = blockIdx.x; 32 const uint32_t sequence = blockIdx.y; 33 // each warp owns one column, using warp-level primitives to reduce across rows 34 const int lane = threadIdx.x; 35 const int col = blockIdx.z * blockDim.y + threadIdx.y; 36 37 const uint32_t iq1 = fastmodulo(h_idx, neqk1_magic); 38 const uint32_t iq3 = fastdiv(sequence, rq3_magic); 39 40 float * attn_data = dst; 41 42 // input state holds s0 only: [S_v, S_v, H, n_seqs] — seq stride is D = H * S_v * S_v. 43 // output state layout (per-slot D * n_seqs) — same per-(seq,head) offset as before. 44 const int64_t state_in_offset = sequence * H * S_v * S_v + h_idx * S_v * S_v; 45 const int64_t state_out_offset = (sequence * H + h_idx) * S_v * S_v; 46 state += state_out_offset; 47 curr_state += state_in_offset + col * S_v; 48 attn_data += (sequence * n_tokens * H + h_idx) * S_v; 49 50 constexpr int warp_size = ggml_cuda_get_physical_warp_size() < S_v ? ggml_cuda_get_physical_warp_size() : S_v; 51 static_assert(S_v % warp_size == 0, "S_v must be a multiple of warp_size"); 52 constexpr int rows_per_lane = (S_v + warp_size - 1) / warp_size; 53 float s_shard[rows_per_lane]; 54 // state is stored transposed: M[col][i] = S[i][col], row col is contiguous 55 56 ggml_cuda_pdl_sync(); 57#pragma unroll 58 for (int r = 0; r < rows_per_lane; r++) { 59 const int i = r * warp_size + lane; 60 s_shard[r] = curr_state[i]; 61 } 62 63 for (int t = 0; t < n_tokens; t++) { 64 const float * q_t = q + iq3 * sq3 + t * sq2 + iq1 * sq1; 65 const float * k_t = k + iq3 * sq3 + t * sq2 + iq1 * sq1; 66 const float * v_t = v + sequence * sv3 + t * sv2 + h_idx * sv1; 67 68 const int64_t gb_offset = sequence * sb3 + t * sb2 + h_idx * sb1; 69 const float * beta_t = beta + gb_offset; 70 const float * g_t = g + gb_offset * (KDA ? S_v : 1); 71 72 const float beta_val = *beta_t; 73 74 // Cache k and q in registers 75 float k_reg[rows_per_lane]; 76 float q_reg[rows_per_lane]; 77#pragma unroll 78 for (int r = 0; r < rows_per_lane; r++) { 79 const int i = r * warp_size + lane; 80 k_reg[r] = k_t[i]; 81 q_reg[r] = q_t[i]; 82 } 83 84 if constexpr (!KDA) { 85 const float g_val = expf(*g_t); 86 87 // kv[col] = (S^T @ k)[col] = sum_i S[i][col] * k[i] 88 float kv_shard = 0.0f; 89#pragma unroll 90 for (int r = 0; r < rows_per_lane; r++) { 91 kv_shard += s_shard[r] * k_reg[r]; 92 } 93 float kv_col = warp_reduce_sum<warp_size>(kv_shard); 94 95 // delta[col] = (v[col] - g * kv[col]) * beta 96 float delta_col = (v_t[col] - g_val * kv_col) * beta_val; 97 98 // fused: S[i][col] = g * S[i][col] + k[i] * delta[col] 99 // attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i] 100 float attn_partial = 0.0f; 101#pragma unroll 102 for (int r = 0; r < rows_per_lane; r++) { 103 s_shard[r] = g_val * s_shard[r] + k_reg[r] * delta_col; 104 attn_partial += s_shard[r] * q_reg[r]; 105 } 106 107 float attn_col = warp_reduce_sum<warp_size>(attn_partial); 108 109 if (lane == 0) { 110 attn_data[col] = attn_col * scale; 111 } 112 } else { 113 // kv[col] = sum_i g[i] * S[i][col] * k[i] 114 float kv_shard = 0.0f; 115#pragma unroll 116 for (int r = 0; r < rows_per_lane; r++) { 117 const int i = r * warp_size + lane; 118 kv_shard += expf(g_t[i]) * s_shard[r] * k_reg[r]; 119 } 120 121 float kv_col = warp_reduce_sum<warp_size>(kv_shard); 122 123 // delta[col] = (v[col] - kv[col]) * beta 124 float delta_col = (v_t[col] - kv_col) * beta_val; 125 126 // fused: S[i][col] = g[i] * S[i][col] + k[i] * delta[col] 127 // attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i] 128 float attn_partial = 0.0f; 129#pragma unroll 130 for (int r = 0; r < rows_per_lane; r++) { 131 const int i = r * warp_size + lane; 132 s_shard[r] = expf(g_t[i]) * s_shard[r] + k_reg[r] * delta_col; 133 attn_partial += s_shard[r] * q_reg[r]; 134 } 135 136 float attn_col = warp_reduce_sum<warp_size>(attn_partial); 137 138 if (lane == 0) { 139 attn_data[col] = attn_col * scale; 140 } 141 } 142 143 attn_data += S_v * H; 144 145 if constexpr (keep_rs_t) { 146 // snapshot slot mapping: slot 0 = most recent state, slot s = s tokens back. 147 // When n_tokens < K only slots 0..n_tokens-1 are written; older slots are caller-owned. 148 const int target_slot = (int) n_tokens - 1 - t; 149 if (target_slot >= 0 && target_slot < K) { 150 float * curr_state = state + target_slot * state_slot_stride; 151#pragma unroll 152 for (int r = 0; r < rows_per_lane; r++) { 153 const int i = r * warp_size + lane; 154 curr_state[col * S_v + i] = s_shard[r]; 155 } 156 } 157 } 158 } 159 160 if constexpr (!keep_rs_t) { 161#pragma unroll 162 for (int r = 0; r < rows_per_lane; r++) { 163 const int i = r * warp_size + lane; 164 state[col * S_v + i] = s_shard[r]; 165 } 166 } 167} 168 169template <bool KDA, bool keep_rs_t> 170static void launch_gated_delta_net( 171 const float * q_d, const float * k_d, const float * v_d, 172 const float * g_d, const float * b_d, const float * s_d, 173 float * dst_d, float * state_d, 174 int64_t S_v, int64_t H, int64_t n_tokens, int64_t n_seqs, 175 int64_t sq1, int64_t sq2, int64_t sq3, 176 int64_t sv1, int64_t sv2, int64_t sv3, 177 int64_t sb1, int64_t sb2, int64_t sb3, 178 int64_t neqk1, int64_t rq3, 179 float scale, int64_t state_slot_stride, int K, cudaStream_t stream) { 180 //TODO: Add chunked kernel for even faster pre-fill 181 const int warp_size = ggml_cuda_info().devices[ggml_cuda_get_device()].warp_size; 182 const int num_warps = 4; 183 dim3 grid_dims(H, n_seqs, (S_v + num_warps - 1) / num_warps); 184 dim3 block_dims(warp_size <= S_v ? warp_size : S_v, num_warps, 1); 185 186 const uint3 neqk1_magic = init_fastdiv_values(neqk1); 187 const uint3 rq3_magic = init_fastdiv_values(rq3); 188 189 const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(grid_dims, block_dims, 0, stream); 190 switch (S_v) { 191 case 16: 192 ggml_cuda_kernel_launch(gated_delta_net_cuda<16, KDA, keep_rs_t>, launch_params, 193 q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H, 194 n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 195 sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K); 196 break; 197 case 32: 198 ggml_cuda_kernel_launch(gated_delta_net_cuda<32, KDA, keep_rs_t>, launch_params, 199 q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H, 200 n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 201 sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K); 202 break; 203 case 64: { 204 ggml_cuda_kernel_launch(gated_delta_net_cuda<64, KDA, keep_rs_t>, launch_params, 205 q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H, 206 n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 207 sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K); 208 break; 209 } 210 case 128: { 211 ggml_cuda_kernel_launch(gated_delta_net_cuda<128, KDA, keep_rs_t>, launch_params, 212 q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H, 213 n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 214 sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K); 215 break; 216 } 217 default: 218 GGML_ABORT("fatal error"); 219 break; 220 } 221} 222 223static void ggml_cuda_op_gated_delta_net_impl( 224 ggml_backend_cuda_context & ctx, ggml_tensor * dst, const ggml_cuda_gated_delta_net_fused_cache * cache) { 225 ggml_tensor * src_q = dst->src[0]; 226 ggml_tensor * src_k = dst->src[1]; 227 ggml_tensor * src_v = dst->src[2]; 228 ggml_tensor * src_g = dst->src[3]; 229 ggml_tensor * src_beta = dst->src[4]; 230 ggml_tensor * src_state = dst->src[5]; 231 232 GGML_TENSOR_LOCALS(int64_t, neq, src_q, ne); 233 GGML_TENSOR_LOCALS(size_t , nbq, src_q, nb); 234 GGML_TENSOR_LOCALS(int64_t, nek, src_k, ne); 235 GGML_TENSOR_LOCALS(size_t , nbk, src_k, nb); 236 GGML_TENSOR_LOCALS(int64_t, nev, src_v, ne); 237 GGML_TENSOR_LOCALS(size_t, nbv, src_v, nb); 238 GGML_TENSOR_LOCALS(size_t, nbb, src_beta, nb); 239 240 const int64_t S_v = nev0; 241 const int64_t H = nev1; 242 const int64_t n_tokens = nev2; 243 const int64_t n_seqs = nev3; 244 245 const bool kda = (src_g->ne[0] == S_v); 246 247 GGML_ASSERT(neq1 == nek1); 248 const int64_t neqk1 = neq1; 249 250 const int64_t rq3 = nev3 / neq3; 251 252 const float * q_d = (const float *) src_q->data; 253 const float * k_d = (const float *) src_k->data; 254 const float * v_d = (const float *) src_v->data; 255 const float * g_d = (const float *) src_g->data; 256 const float * b_d = (const float *) src_beta->data; 257 258 const float * s_d = (const float *) src_state->data; 259 float * dst_d = (float *) dst->data; 260 261 GGML_ASSERT(ggml_is_contiguous_rows(src_q)); 262 GGML_ASSERT(ggml_is_contiguous_rows(src_k)); 263 GGML_ASSERT(ggml_is_contiguous_rows(src_v)); 264 GGML_ASSERT(ggml_are_same_stride(src_q, src_k)); 265 GGML_ASSERT(src_g->ne[0] == 1 || kda); 266 GGML_ASSERT(ggml_is_contiguous(src_g)); 267 GGML_ASSERT(ggml_is_contiguous(src_beta)); 268 GGML_ASSERT(ggml_is_contiguous(src_state)); 269 270 // strides in floats (beta strides used for both g and beta offset computation) 271 const int64_t sq1 = nbq1 / sizeof(float); 272 const int64_t sq2 = nbq2 / sizeof(float); 273 const int64_t sq3 = nbq3 / sizeof(float); 274 const int64_t sv1 = nbv1 / sizeof(float); 275 const int64_t sv2 = nbv2 / sizeof(float); 276 const int64_t sv3 = nbv3 / sizeof(float); 277 const int64_t sb1 = nbb1 / sizeof(float); 278 const int64_t sb2 = nbb2 / sizeof(float); 279 const int64_t sb3 = nbb3 / sizeof(float); 280 281 const float scale = 1.0f / sqrtf((float) S_v); 282 283 cudaStream_t stream = ctx.stream(); 284 285 // K (snapshot slot count) is an op param; state holds s0 only [S_v, S_v, H, n_seqs]. 286 const int K = ggml_get_op_params_i32(dst, 0); 287 const bool keep_rs = K > 1; 288 289 // recurrent state -> gdn_out tail (after attention scores), or the cache when fusing 290 float * state_d = dst_d + S_v * H * n_tokens * n_seqs; 291 int64_t state_slot_stride = S_v * S_v * H * n_seqs; 292 if (cache != nullptr) { 293 state_d = cache->data; 294 state_slot_stride = cache->slot_stride; 295 } 296 297 if (kda) { 298 if (keep_rs) { 299 launch_gated_delta_net<true, true>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, 300 S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 301 sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream); 302 } else { 303 launch_gated_delta_net<true, false>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, 304 S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 305 sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream); 306 } 307 } else { 308 if (keep_rs) { 309 launch_gated_delta_net<false, true>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, 310 S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 311 sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream); 312 } else { 313 launch_gated_delta_net<false, false>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, 314 S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3, 315 sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream); 316 } 317 } 318} 319 320void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 321 ggml_cuda_op_gated_delta_net_impl(ctx, dst, nullptr); 322} 323 324void ggml_cuda_op_gated_delta_net_fused_cache( 325 ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_cuda_gated_delta_net_fused_cache cache) { 326 ggml_cuda_op_gated_delta_net_impl(ctx, dst, &cache); 327}