Skip to content

Commit 39b6f5a

Browse files
committed
models : avoid Q and K repeats when using fused GDA
1 parent ec2443a commit 39b6f5a

7 files changed

Lines changed: 33 additions & 26 deletions

File tree

ggml/include/ggml.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,6 +2464,8 @@ extern "C" {
24642464
bool lower,
24652465
bool uni);
24662466

2467+
// TODO: add ggml_gated_delta_net_set_bcast() to be able to configure Q, K broadcast type: tiled vs interleaved [TAG_GGML_GDN_BCAST]
2468+
// ref: https://github.com/ggml-org/llama.cpp/pull/19468#discussion_r2786394306
24672469
GGML_API struct ggml_tensor * ggml_gated_delta_net(
24682470
struct ggml_context * ctx,
24692471
struct ggml_tensor * q,

ggml/src/ggml-cpu/ops.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10436,8 +10436,8 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
1043610436

1043710437
const float * state_in_base = (const float *)src_state->data;
1043810438

10439-
const int64_t rq1 = nev1 / neq1;
10440-
const int64_t rk1 = nev1 / nek1;
10439+
//const int64_t rq1 = nev1 / neq1;
10440+
//const int64_t rk1 = nev1 / nek1;
1044110441
const int64_t rq3 = nev3 / neq3;
1044210442
const int64_t rk3 = nev3 / nek3;
1044310443

@@ -10447,8 +10447,8 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
1044710447
const int64_t iv1 = ir % H; // head_index
1044810448
const int64_t iv3 = ir / H; // sequence
1044910449

10450-
const int64_t iq1 = iv1 / rq1;
10451-
const int64_t ik1 = iv1 / rk1;
10450+
const int64_t iq1 = iv1 % neq1;
10451+
const int64_t ik1 = iv1 % nek1;
1045210452

1045310453
const int64_t iq3 = iv3 / rq3;
1045410454
const int64_t ik3 = iv3 / rk3;

ggml/src/ggml-cuda/gated_delta_net.cu

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ __global__ void gated_delta_net_cuda(const float * q,
2121
int64_t sb1,
2222
int64_t sb2,
2323
int64_t sb3,
24-
int64_t rq1,
24+
int64_t neqk1,
2525
int64_t rq3,
2626
float scale) {
2727
const int64_t h_idx = blockIdx.x;
2828
const int64_t sequence = blockIdx.y;
2929
const int col = threadIdx.x; // each thread owns one column
3030

31-
const int64_t iq1 = h_idx / rq1;
31+
const int64_t iq1 = h_idx % neqk1;
3232
const int64_t iq3 = sequence / rq3;
3333

3434
const int64_t attn_score_elems = S_v * H * n_tokens * n_seqs;
@@ -119,11 +119,11 @@ static void launch_gated_delta_net(
119119
const float * q_d, const float * k_d, const float * v_d,
120120
const float * g_d, const float * b_d, const float * s_d,
121121
float * dst_d,
122-
int64_t S_v, int64_t H, int64_t n_tokens, int64_t n_seqs,
123-
int64_t sq1, int64_t sq2, int64_t sq3,
124-
int64_t sv1, int64_t sv2, int64_t sv3,
125-
int64_t sb1, int64_t sb2, int64_t sb3,
126-
int64_t rq1, int64_t rq3,
122+
int64_t S_v, int64_t H, int64_t n_tokens, int64_t n_seqs,
123+
int64_t sq1, int64_t sq2, int64_t sq3,
124+
int64_t sv1, int64_t sv2, int64_t sv3,
125+
int64_t sb1, int64_t sb2, int64_t sb3,
126+
int64_t neqk1, int64_t rq3,
127127
float scale, cudaStream_t stream) {
128128

129129
dim3 grid_dims(H, n_seqs, 1);
@@ -134,19 +134,19 @@ static void launch_gated_delta_net(
134134
gated_delta_net_cuda<32, KDA><<<grid_dims, block_dims, 0, stream>>>(
135135
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, H,
136136
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
137-
sb1, sb2, sb3, rq1, rq3, scale);
137+
sb1, sb2, sb3, neqk1, rq3, scale);
138138
break;
139139
case 64:
140140
gated_delta_net_cuda<64, KDA><<<grid_dims, block_dims, 0, stream>>>(
141141
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, H,
142142
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
143-
sb1, sb2, sb3, rq1, rq3, scale);
143+
sb1, sb2, sb3, neqk1, rq3, scale);
144144
break;
145145
case 128:
146146
gated_delta_net_cuda<128, KDA><<<grid_dims, block_dims, 0, stream>>>(
147147
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, H,
148148
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
149-
sb1, sb2, sb3, rq1, rq3, scale);
149+
sb1, sb2, sb3, neqk1, rq3, scale);
150150
break;
151151
default:
152152
GGML_ABORT("fatal error");
@@ -163,10 +163,12 @@ void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor *
163163
ggml_tensor * src_state = dst->src[5];
164164

165165
GGML_TENSOR_LOCALS(int64_t, neq, src_q, ne);
166-
GGML_TENSOR_LOCALS(size_t, nbq, src_q, nb);
166+
GGML_TENSOR_LOCALS(size_t , nbq, src_q, nb);
167+
GGML_TENSOR_LOCALS(int64_t, nek, src_k, ne);
168+
GGML_TENSOR_LOCALS(size_t , nbk, src_k, nb);
167169
GGML_TENSOR_LOCALS(int64_t, nev, src_v, ne);
168-
GGML_TENSOR_LOCALS(size_t, nbv, src_v, nb);
169-
GGML_TENSOR_LOCALS(size_t, nbb, src_beta, nb);
170+
GGML_TENSOR_LOCALS(size_t, nbv, src_v, nb);
171+
GGML_TENSOR_LOCALS(size_t, nbb, src_beta, nb);
170172

171173
const int64_t S_v = nev0;
172174
const int64_t H = nev1;
@@ -175,7 +177,9 @@ void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor *
175177

176178
const bool kda = (src_g->ne[0] == S_v);
177179

178-
const int64_t rq1 = nev1 / neq1;
180+
GGML_ASSERT(neq1 == nek1);
181+
const int64_t neqk1 = neq1;
182+
179183
const int64_t rq3 = nev3 / neq3;
180184

181185
const float * q_d = (const float *) src_q->data;
@@ -214,10 +218,10 @@ void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor *
214218
if (kda) {
215219
launch_gated_delta_net<true>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d,
216220
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
217-
sb1, sb2, sb3, rq1, rq3, scale, stream);
221+
sb1, sb2, sb3, neqk1, rq3, scale, stream);
218222
} else {
219223
launch_gated_delta_net<false>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d,
220224
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
221-
sb1, sb2, sb3, rq1, rq3, scale, stream);
225+
sb1, sb2, sb3, neqk1, rq3, scale, stream);
222226
}
223227
}

ggml/src/ggml-cuda/ggml-cuda.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,8 +4999,8 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
49994999
#ifdef GGML_USE_MUSA
50005000
return false;
50015001
#else
5002-
// TODO: add chunked support
5003-
return op->src[0]->ne[2] == 1;
5002+
// TODO: add non-KDA chunked support. for now enable chunked support for KDA only
5003+
return op->src[0]->ne[2] == 1 || op->src[3]->ne[0] == op->src[2]->ne[0];
50045004
#endif // GGML_USE_MUSA
50055005
case GGML_OP_FLASH_ATTN_EXT:
50065006
return ggml_cuda_flash_attn_ext_supported(dev_ctx->device, op);

src/models/qwen35.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ ggml_tensor * llm_build_qwen35::build_layer_attn_linear(
321321
//v_conv = ggml_cont_4d(ctx0, v_conv, head_v_dim, num_v_heads, n_seq_tokens, n_seqs);
322322

323323
// if head keys and value keys are different, repeat to force tensors into matching shapes
324-
if (num_k_heads != num_v_heads) {
324+
// note: need explicit repeat only if we are not using the fused GDN
325+
if (num_k_heads != num_v_heads && (!cparams.fused_gdn_ar || !cparams.fused_gdn_ch)) {
325326
GGML_ASSERT(num_v_heads % num_k_heads == 0);
326-
// TODO: try to avoid these explicit repeats by utilizing op broadcast
327327
q_conv = ggml_repeat_4d(ctx0, q_conv, head_k_dim, num_v_heads, n_seq_tokens, n_seqs);
328328
k_conv = ggml_repeat_4d(ctx0, k_conv, head_k_dim, num_v_heads, n_seq_tokens, n_seqs);
329329
}

src/models/qwen35moe.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ ggml_tensor * llm_build_qwen35moe ::build_layer_attn_linear(
321321
//v_conv = ggml_cont_4d(ctx0, v_conv, head_v_dim, num_v_heads, n_seq_tokens, n_seqs);
322322

323323
// if head keys and value keys are different, repeat to force tensors into matching shapes
324-
if (num_k_heads != num_v_heads) {
324+
// note: need explicit repeat only if we are not using the fused GDN
325+
if (num_k_heads != num_v_heads && (!cparams.fused_gdn_ar || !cparams.fused_gdn_ch)) {
325326
GGML_ASSERT(num_v_heads % num_k_heads == 0);
326-
// TODO: try to avoid these explicit repeats by utilizing op broadcast
327327
q_conv = ggml_repeat_4d(ctx0, q_conv, head_k_dim, num_v_heads, n_seq_tokens, n_seqs);
328328
k_conv = ggml_repeat_4d(ctx0, k_conv, head_k_dim, num_v_heads, n_seq_tokens, n_seqs);
329329
}

src/models/qwen3next.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ ggml_tensor * llm_build_qwen3next::build_layer_attn_linear(
406406
//v_conv = ggml_cont_4d(ctx0, v_conv, head_v_dim, num_v_heads, n_seq_tokens, n_seqs);
407407

408408
// if head keys and value keys are different, repeat to force tensors into matching shapes
409+
// TODO: avoid repeats for fused GDN, needs broadcast configuration for GDN op [TAG_GGML_GDN_BCAST]
409410
if (num_k_heads != num_v_heads) {
410411
GGML_ASSERT(num_v_heads % num_k_heads == 0);
411412
int64_t repeat_factor = num_v_heads / num_k_heads;

0 commit comments

Comments
 (0)