Skip to content

Commit dbc4ddb

Browse files
author
Molly
committed
test sdpa persistent kv cache semantics
1 parent 1960a06 commit dbc4ddb

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

tests/test_sdpa_kvcache.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,153 @@ static int test_sdpa_kvcache2_invalid_past_len()
132132
return 0;
133133
}
134134

135+
static int test_sdpa_kvcache2_persistent_buffer()
136+
{
137+
const int embed_dim = 4;
138+
const int out_embed_dim = 3;
139+
const int past_seqlen = 2;
140+
const int cur_seqlen = 2;
141+
const int max_seqlen = 5;
142+
143+
ncnn::Mat query(embed_dim, cur_seqlen, 2);
144+
query.fill(0.01f);
145+
146+
ncnn::Mat cur_key(embed_dim, cur_seqlen, 1);
147+
ncnn::Mat cur_value(out_embed_dim, cur_seqlen, 1);
148+
ncnn::Mat past_key(embed_dim, max_seqlen, 1);
149+
ncnn::Mat past_value(out_embed_dim, max_seqlen, 1);
150+
151+
for (int y = 0; y < cur_seqlen; y++)
152+
{
153+
float* kptr = cur_key.row(y);
154+
for (int x = 0; x < embed_dim; x++)
155+
kptr[x] = 100.f + y * 10 + x;
156+
157+
float* vptr = cur_value.row(y);
158+
for (int x = 0; x < out_embed_dim; x++)
159+
vptr[x] = 200.f + y * 10 + x;
160+
}
161+
162+
for (int y = 0; y < max_seqlen; y++)
163+
{
164+
float* kptr = past_key.row(y);
165+
for (int x = 0; x < embed_dim; x++)
166+
kptr[x] = 300.f + y * 10 + x;
167+
168+
float* vptr = past_value.row(y);
169+
for (int x = 0; x < out_embed_dim; x++)
170+
vptr[x] = 400.f + y * 10 + x;
171+
}
172+
173+
ncnn::Mat past_len(1);
174+
past_len.fill((float)past_seqlen);
175+
176+
ncnn::ParamDict pd;
177+
pd.set(7, 2); // kv_cache
178+
179+
ncnn::Layer* op = ncnn::create_layer_cpu("SDPA");
180+
op->load_param(pd);
181+
182+
ncnn::Option opt;
183+
opt.num_threads = 1;
184+
185+
op->create_pipeline(opt);
186+
187+
std::vector<ncnn::Mat> bottom_blobs(6);
188+
bottom_blobs[0] = query;
189+
bottom_blobs[1] = cur_key;
190+
bottom_blobs[2] = cur_value;
191+
bottom_blobs[3] = past_key;
192+
bottom_blobs[4] = past_value;
193+
bottom_blobs[5] = past_len;
194+
195+
std::vector<ncnn::Mat> top_blobs(3);
196+
int ret = op->forward(bottom_blobs, top_blobs, opt);
197+
if (ret != 0)
198+
{
199+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer failed forward\n");
200+
op->destroy_pipeline(opt);
201+
delete op;
202+
return -1;
203+
}
204+
205+
if (top_blobs[1].data != past_key.data || top_blobs[2].data != past_value.data)
206+
{
207+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer failed buffer identity\n");
208+
op->destroy_pipeline(opt);
209+
delete op;
210+
return -1;
211+
}
212+
213+
for (int y = 0; y < past_seqlen; y++)
214+
{
215+
const float* kptr = past_key.row(y);
216+
for (int x = 0; x < embed_dim; x++)
217+
{
218+
if (kptr[x] != 300.f + y * 10 + x)
219+
{
220+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer clobbered past_key\n");
221+
op->destroy_pipeline(opt);
222+
delete op;
223+
return -1;
224+
}
225+
}
226+
227+
const float* vptr = past_value.row(y);
228+
for (int x = 0; x < out_embed_dim; x++)
229+
{
230+
if (vptr[x] != 400.f + y * 10 + x)
231+
{
232+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer clobbered past_value\n");
233+
op->destroy_pipeline(opt);
234+
delete op;
235+
return -1;
236+
}
237+
}
238+
}
239+
240+
for (int y = 0; y < cur_seqlen; y++)
241+
{
242+
const float* kptr = past_key.row(past_seqlen + y);
243+
for (int x = 0; x < embed_dim; x++)
244+
{
245+
if (kptr[x] != 100.f + y * 10 + x)
246+
{
247+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer failed appended key\n");
248+
op->destroy_pipeline(opt);
249+
delete op;
250+
return -1;
251+
}
252+
}
253+
254+
const float* vptr = past_value.row(past_seqlen + y);
255+
for (int x = 0; x < out_embed_dim; x++)
256+
{
257+
if (vptr[x] != 200.f + y * 10 + x)
258+
{
259+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer failed appended value\n");
260+
op->destroy_pipeline(opt);
261+
delete op;
262+
return -1;
263+
}
264+
}
265+
}
266+
267+
past_len.fill((float)(max_seqlen - cur_seqlen + 1));
268+
ret = op->forward(bottom_blobs, top_blobs, opt);
269+
if (ret == 0)
270+
{
271+
fprintf(stderr, "test_sdpa_kvcache2_persistent_buffer failed overflow check\n");
272+
op->destroy_pipeline(opt);
273+
delete op;
274+
return -1;
275+
}
276+
277+
op->destroy_pipeline(opt);
278+
delete op;
279+
return 0;
280+
}
281+
135282
static int test_sdpa_0()
136283
{
137284
return 0
@@ -152,6 +299,7 @@ static int test_sdpa_0()
152299
|| test_sdpa_kvcache2(RandomMat(32, 16, 8), RandomMat(32, 16, 8), RandomMat(20, 16, 8), 0, 0, 32)
153300
|| test_sdpa_kvcache2(RandomMat(64, 17, 12), RandomMat(64, 17, 2), RandomMat(64, 17, 2), 0, 0, 32)
154301
|| test_sdpa_kvcache2_invalid_past_len()
302+
|| test_sdpa_kvcache2_persistent_buffer()
155303
|| test_sdpa_kvcache2(RandomMat(32, 16, 8), RandomMat(32, 16, 8), RandomMat(20, 16, 8), 1, 0, 32)
156304
|| test_sdpa_kvcache2(RandomMat(64, 17, 12), RandomMat(64, 17, 2), RandomMat(64, 17, 2), 1, 0, 32);
157305
}

0 commit comments

Comments
 (0)