← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
ck_parity_api.h
Go to the documentation of this file.
1/**
2 * @file ck_parity_api.h
3 * @brief C-Kernel-Engine Parity Testing API
4 *
5 * Exposes individual CK kernels for parity testing against llama.cpp/ggml.
6 * This API mirrors the test-kernel-parity.cpp interface in llama.cpp.
7 *
8 * Usage:
9 * 1. Build as shared library: libck_parity.so
10 * 2. Load from Python using ctypes
11 * 3. Call functions with matching signatures to test-kernel-parity.cpp
12 */
13
14#ifndef CK_PARITY_API_H
15#define CK_PARITY_API_H
16
17#include <stddef.h>
18#include <stdint.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24/* ============================================================================
25 * Constants (must match llama.cpp/ggml)
26 * ============================================================================ */
27
28#define CK_QK_K 256 /* Elements per K-quant super-block */
29#define CK_QK4_0 32 /* Elements per Q4_0 block */
30#define CK_QK8_0 32 /* Elements per Q8_0 block */
31
32/* Block sizes in bytes */
33#define CK_BLOCK_Q4_K_SIZE 144
34#define CK_BLOCK_Q6_K_SIZE 210
35#define CK_BLOCK_Q8_K_SIZE 292
36#define CK_BLOCK_Q4_0_SIZE 18
37
38/* ============================================================================
39 * Dequantization Tests
40 * ============================================================================ */
41
42/**
43 * @brief Dequantize Q4_K data to FP32
44 * @param src Input Q4_K blocks
45 * @param dst Output FP32 values
46 * @param n Number of elements (must be multiple of 256)
47 */
48void ck_test_dequant_q4_k(const void *src, float *dst, int n);
49
50/**
51 * @brief Dequantize Q6_K data to FP32
52 */
53void ck_test_dequant_q6_k(const void *src, float *dst, int n);
54
55/**
56 * @brief Dequantize Q4_0 data to FP32
57 */
58void ck_test_dequant_q4_0(const void *src, float *dst, int n);
59
60/* ============================================================================
61 * Quantization Tests
62 * ============================================================================ */
63
64/**
65 * @brief Quantize FP32 to Q8_K (for activations)
66 * @param src Input FP32 values
67 * @param dst Output Q8_K blocks
68 * @param n Number of elements (must be multiple of 256)
69 */
70void ck_test_quantize_q8_k(const float *src, void *dst, int n);
71
72/* ============================================================================
73 * GEMV (Matrix-Vector) Tests
74 * ============================================================================ */
75
76/**
77 * @brief Q4_K GEMV - dot product of quantized weights and FP32 input
78 *
79 * Internally quantizes input to Q8_K, then computes dot product.
80 *
81 * @param weight_q4k Q4_K quantized weights [cols]
82 * @param input_f32 FP32 input vector [cols]
83 * @param output Output scalar [1]
84 * @param cols Number of columns (must be multiple of 256)
85 */
86void ck_test_gemv_q4_k(const void *weight_q4k,
87 const float *input_f32,
88 float *output,
89 int cols);
90
91/**
92 * @brief Q6_K GEMV
93 */
94void ck_test_gemv_q6_k(const void *weight_q6k,
95 const float *input_f32,
96 float *output,
97 int cols);
98
99/**
100 * @brief Q5_0 GEMV - matrix-vector multiply with Q5_0 weights
101 *
102 * @param weight_q5_0 Q5_0 quantized weights [rows * cols]
103 * @param input_f32 FP32 input vector [cols]
104 * @param output FP32 output vector [rows]
105 * @param rows Number of output rows
106 * @param cols Number of columns (must be multiple of 32)
107 */
108void ck_test_gemv_q5_0(const void *weight_q5_0,
109 const float *input_f32,
110 float *output,
111 int rows, int cols);
112
113/**
114 * @brief Q8_0 GEMV - matrix-vector multiply with Q8_0 weights
115 *
116 * @param weight_q8_0 Q8_0 quantized weights [rows * cols]
117 * @param input_f32 FP32 input vector [cols]
118 * @param output FP32 output vector [rows]
119 * @param rows Number of output rows
120 * @param cols Number of columns (must be multiple of 32)
121 */
122void ck_test_gemv_q8_0(const void *weight_q8_0,
123 const float *input_f32,
124 float *output,
125 int rows, int cols);
126
127/**
128 * @brief Q5_0 x Q8_0 quantized GEMV - matches llama.cpp's approach
129 *
130 * This version quantizes the input to Q8_0 first, then uses integer
131 * dot products (like llama.cpp does). Use this for parity testing.
132 *
133 * @param weight_q5_0 Q5_0 quantized weights [rows * cols]
134 * @param input_f32 FP32 input vector [cols] - will be quantized to Q8_0
135 * @param output FP32 output vector [rows]
136 * @param rows Number of output rows
137 * @param cols Number of columns (must be multiple of 32)
138 */
139void ck_test_gemv_q5_0_q8_0(const void *weight_q5_0,
140 const float *input_f32,
141 float *output,
142 int rows, int cols);
143
144/**
145 * @brief Q8_0 x Q8_0 quantized GEMV - matches llama.cpp's approach
146 *
147 * This version quantizes the input to Q8_0 first, then uses integer
148 * dot products (like llama.cpp does). Use this for parity testing.
149 *
150 * @param weight_q8_0 Q8_0 quantized weights [rows * cols]
151 * @param input_f32 FP32 input vector [cols] - will be quantized to Q8_0
152 * @param output FP32 output vector [rows]
153 * @param rows Number of output rows
154 * @param cols Number of columns (must be multiple of 32)
155 */
156void ck_test_gemv_q8_0_q8_0(const void *weight_q8_0,
157 const float *input_f32,
158 float *output,
159 int rows, int cols);
160
161/* ============================================================================
162 * Direct Vec Dot Tests (pre-quantized inputs, no FP32 conversion)
163 * ============================================================================ */
164
165/** Direct Q4_K x Q8_K dot product using identical pre-quantized bytes. */
166void ck_test_vec_dot_q4_k_q8_k(const void *weight_q4_k,
167 const void *input_q8_k,
168 float *output,
169 int cols);
170
171/** Direct Q6_K x Q8_K dot product using identical pre-quantized bytes. */
172void ck_test_vec_dot_q6_k_q8_k(const void *weight_q6_k,
173 const void *input_q8_k,
174 float *output,
175 int cols);
176
177/**
178 * @brief Direct Q5_0 x Q8_0 dot product (takes pre-quantized Q8_0 input)
179 *
180 * This is a "direct" test that bypasses FP32-to-Q8_0 conversion.
181 * Useful for isolating kernel bugs from quantization bugs.
182 *
183 * @param weight_q5_0 Q5_0 quantized weights [cols]
184 * @param input_q8_0 Q8_0 quantized input [cols] (pre-quantized!)
185 * @param output Output scalar [1]
186 * @param cols Number of elements (must be multiple of 32)
187 */
188void ck_test_vec_dot_q5_0_q8_0(const void *weight_q5_0,
189 const void *input_q8_0,
190 float *output,
191 int cols);
192
193/**
194 * @brief Direct Q8_0 x Q8_0 dot product (takes pre-quantized Q8_0 input)
195 *
196 * @param weight_q8_0 Q8_0 quantized weights [cols]
197 * @param input_q8_0 Q8_0 quantized input [cols] (pre-quantized!)
198 * @param output Output scalar [1]
199 * @param cols Number of elements (must be multiple of 32)
200 */
201void ck_test_vec_dot_q8_0_q8_0(const void *weight_q8_0,
202 const void *input_q8_0,
203 float *output,
204 int cols);
205
206/* ============================================================================
207 * GEMM (Matrix-Matrix) Tests
208 * ============================================================================ */
209
210/**
211 * @brief Q4_K GEMM - batched matrix multiply with quantized weights
212 *
213 * Computes: output[t,r] = sum_k(weight[r,k] * input[t,k])
214 *
215 * @param weight_q4k Q4_K quantized weights [rows, cols]
216 * @param input_f32 FP32 input [n_tokens, cols]
217 * @param output FP32 output [n_tokens, rows]
218 * @param rows Number of output rows
219 * @param cols Number of columns (must be multiple of 256)
220 * @param n_tokens Batch size
221 */
222void ck_test_gemm_q4_k(const void *weight_q4k,
223 const float *input_f32,
224 float *output,
225 int rows, int cols, int n_tokens);
226
227/**
228 * @brief Q6_K GEMM - batched matrix multiply with Q6_K weights
229 *
230 * Computes: output[t,r] = sum_k(weight[r,k] * input[t,k])
231 *
232 * @param weight_q6k Q6_K quantized weights [rows, cols]
233 * @param input_f32 FP32 input [n_tokens, cols]
234 * @param output FP32 output [n_tokens, rows]
235 * @param rows Number of output rows
236 * @param cols Number of columns (must be multiple of 256)
237 * @param n_tokens Batch size
238 */
239void ck_test_gemm_q6_k(const void *weight_q6k,
240 const float *input_f32,
241 float *output,
242 int rows, int cols, int n_tokens);
243
244/**
245 * @brief Q5_0 GEMM - batched matrix multiply with Q5_0 weights (32-element blocks)
246 *
247 * Computes: output[t,r] = sum_k(weight[r,k] * input[t,k])
248 *
249 * @param weight_q5_0 Q5_0 quantized weights [rows, cols]
250 * @param input_f32 FP32 input [n_tokens, cols]
251 * @param output FP32 output [n_tokens, rows]
252 * @param rows Number of output rows
253 * @param cols Number of columns (must be multiple of 32)
254 * @param n_tokens Batch size
255 */
256void ck_test_gemm_q5_0(const void *weight_q5_0,
257 const float *input_f32,
258 float *output,
259 int rows, int cols, int n_tokens);
260
261/**
262 * @brief Q8_0 GEMM - batched matrix multiply with Q8_0 weights (32-element blocks)
263 *
264 * Computes: output[t,r] = sum_k(weight[r,k] * input[t,k])
265 *
266 * @param weight_q8_0 Q8_0 quantized weights [rows, cols]
267 * @param input_f32 FP32 input [n_tokens, cols]
268 * @param output FP32 output [n_tokens, rows]
269 * @param rows Number of output rows
270 * @param cols Number of columns (must be multiple of 32)
271 * @param n_tokens Batch size
272 */
273void ck_test_gemm_q8_0(const void *weight_q8_0,
274 const float *input_f32,
275 float *output,
276 int rows, int cols, int n_tokens);
277
278/* ============================================================================
279 * Activation Kernels
280 * ============================================================================ */
281
282/**
283 * @brief RMSNorm
284 *
285 * Computes: output = (input / rms(input)) * weight
286 * where rms(x) = sqrt(mean(x^2) + eps)
287 *
288 * @param input Input tensor [n_tokens, dim]
289 * @param weight Normalization weights [dim]
290 * @param output Output tensor [n_tokens, dim]
291 * @param n_tokens Number of tokens
292 * @param dim Hidden dimension
293 * @param eps Epsilon for numerical stability
294 */
295void ck_test_rmsnorm(const float *input,
296 const float *weight,
297 float *output,
298 int n_tokens, int dim, float eps);
299
300/**
301 * @brief RoPE (Rotary Position Embedding)
302 *
303 * Applies rotary position embeddings to Q and K tensors.
304 *
305 * NOTE: CK uses rotate-half format (split first/second halves)
306 * while some implementations use interleaved format.
307 * The test harness should account for this.
308 *
309 * @param q Query tensor [n_tokens, n_heads * head_dim], modified in-place
310 * @param k Key tensor [n_tokens, n_heads_kv * head_dim], modified in-place
311 * @param n_tokens Number of tokens
312 * @param n_heads Number of query heads
313 * @param n_heads_kv Number of key/value heads
314 * @param head_dim Dimension per head
315 * @param pos_offset Starting position for RoPE
316 * @param theta RoPE base frequency (typically 10000.0)
317 */
318void ck_test_rope(float *q, float *k,
319 int n_tokens, int n_heads, int n_heads_kv, int head_dim,
320 int pos_offset, float theta);
321
322/**
323 * @brief RoPE with interleaved format (for llama.cpp compatibility)
324 *
325 * Uses interleaved format: (x0, x1) -> (x0*cos - x1*sin, x0*sin + x1*cos)
326 */
327void ck_test_rope_interleaved(float *q, float *k,
328 int n_tokens, int n_heads, int n_heads_kv, int head_dim,
329 int pos_offset, float theta);
330
331/**
332 * @brief SwiGLU activation
333 *
334 * Computes: output = SiLU(gate) * up
335 * where SiLU(x) = x * sigmoid(x)
336 *
337 * @param gate_up Input tensor [n_tokens, 2 * intermediate_dim]
338 * Layout: [gate_0..gate_D-1, up_0..up_D-1] per token
339 * @param output Output tensor [n_tokens, intermediate_dim]
340 * @param n_tokens Number of tokens
341 * @param intermediate_dim Intermediate dimension
342 */
343void ck_test_swiglu(const float *gate_up,
344 float *output,
345 int n_tokens, int intermediate_dim);
346
347/**
348 * @brief Softmax (simple, non-causal)
349 *
350 * Computes: output[i] = exp(input[i]) / sum(exp(input))
351 *
352 * @param input Input tensor [n]
353 * @param output Output tensor [n]
354 * @param n Number of elements
355 */
356void ck_test_softmax(const float *input, float *output, int n);
357
358/**
359 * @brief Gated DeltaNet autoregressive update.
360 *
361 * Layout:
362 * q, k, v [num_heads, state_dim]
363 * g, beta [num_heads]
364 * state_* [num_heads, state_dim, state_dim] row-major per head
365 * out [num_heads, state_dim]
366 *
367 * This mirrors the single-token recurrent update used by qwen3next in
368 * llama.cpp after projections/convolution but before output projection.
369 */
370void ck_test_gated_deltanet_autoregressive(const float *q,
371 const float *k,
372 const float *v,
373 const float *g,
374 const float *beta,
375 const float *state_in,
376 float *state_out,
377 float *out,
378 int num_heads,
379 int state_dim,
380 float norm_eps);
381
382/**
383 * @brief qwen3next/Qwen3.5 SSM causal depthwise convolution.
384 *
385 * Layout:
386 * conv_x [num_seqs, num_channels, kernel_size - 1 + num_tokens]
387 * kernel [num_channels, kernel_size]
388 * out [num_seqs, num_tokens, num_channels]
389 *
390 * This mirrors ggml's GGML_OP_SSM_CONV used immediately before the DeltaNet
391 * recurrent update in qwen3next/Qwen3.5.
392 */
393void ck_test_ssm_conv1d(const float *conv_x,
394 const float *kernel,
395 float *out,
396 int kernel_size,
397 int num_channels,
398 int num_tokens,
399 int num_seqs);
400
401/**
402 * @brief Split a packed full-attention Q+gate matrix into Q rows and gate rows.
403 *
404 * Layout:
405 * packed_qg : [rows, q_dim + gate_dim]
406 * q : [rows, q_dim]
407 * gate : [rows, gate_dim]
408 */
409void ck_test_split_q_gate(const float *packed_qg,
410 float *q,
411 float *gate,
412 int rows,
413 int q_dim,
414 int gate_dim,
415 int group_dim);
416
417/**
418 * @brief Split a packed recurrent QKV matrix into explicit Q, K, and V outputs.
419 *
420 * Layout:
421 * packed_qkv : [rows, q_dim + k_dim + v_dim]
422 * q : [rows, q_dim]
423 * k : [rows, k_dim]
424 * v : [rows, v_dim]
425 */
426void ck_test_recurrent_split_qkv(const float *packed_qkv,
427 float *q,
428 float *k,
429 float *v,
430 int rows,
431 int q_dim,
432 int k_dim,
433 int v_dim);
434
435/**
436 * @brief Transform recurrent alpha rows into the DeltaNet gate.
437 *
438 * Layout:
439 * alpha : [rows, dim]
440 * dt_bias : [dim]
441 * a : [dim]
442 * gate : [rows, dim]
443 */
444void ck_test_recurrent_dt_gate(const float *alpha,
445 const float *dt_bias,
446 const float *a,
447 float *gate,
448 int rows,
449 int dim);
450
451/**
452 * @brief Build the recurrent convolution input history window.
453 *
454 * Layout:
455 * state_in [num_seqs, channels, history_len]
456 * q [num_seqs * num_tokens, q_dim]
457 * k [num_seqs * num_tokens, k_dim]
458 * v [num_seqs * num_tokens, v_dim]
459 * conv_x [num_seqs, channels, history_len + num_tokens]
460 * state_out [num_seqs, channels, history_len]
461 */
462void ck_test_recurrent_conv_state_update(const float *state_in,
463 const float *q,
464 const float *k,
465 const float *v,
466 float *conv_x,
467 float *state_out,
468 int history_len,
469 int num_seqs,
470 int num_tokens,
471 int q_dim,
472 int k_dim,
473 int v_dim);
474
475/**
476 * @brief Apply SiLU elementwise to recurrent rows.
477 */
478void ck_test_recurrent_silu(const float *x,
479 float *out,
480 int rows,
481 int dim);
482
483/**
484 * @brief Split the post-convolution recurrent packed QKV rows.
485 */
486void ck_test_recurrent_split_conv_qkv(const float *packed_qkv,
487 float *q,
488 float *k,
489 float *v,
490 int rows,
491 int q_dim,
492 int k_dim,
493 int v_dim);
494
495/**
496 * @brief Apply per-head L2 normalization to recurrent Q/K rows in-place.
497 *
498 * Layout:
499 * q : [rows, q_dim]
500 * k : [rows, k_dim]
501 * where q_dim and k_dim are multiples of head_dim.
502 */
503void ck_test_recurrent_qk_l2_norm(float *q,
504 float *k,
505 int rows,
506 int q_dim,
507 int k_dim,
508 int head_dim,
509 float eps);
510
511/**
512 * @brief Multiply attention output rows by sigmoid(gate) elementwise.
513 *
514 * Layout:
515 * x : [rows, dim]
516 * gate : [rows, dim]
517 * out : [rows, dim]
518 */
519void ck_test_attn_gate_sigmoid_mul(const float *x,
520 const float *gate,
521 float *out,
522 int rows,
523 int dim);
524
525/**
526 * @brief Per-head RMSNorm followed by SiLU(z) gating for recurrent outputs.
527 */
528void ck_test_recurrent_norm_gate(const float *x,
529 const float *gate,
530 const float *weight,
531 float *out,
532 int rows,
533 int num_heads,
534 int head_dim,
535 float eps);
536
537/* ============================================================================
538 * Attention Kernels
539 * ============================================================================ */
540
541/**
542 * @brief Multi-head causal attention for prefill (head-major layout)
543 *
544 * Layout (head-major, matches llama.cpp test):
545 * Q: [num_heads, tokens, head_dim]
546 * K: [num_kv_heads, seq_len, head_dim]
547 * V: [num_kv_heads, seq_len, head_dim]
548 * out: [num_heads, tokens, head_dim]
549 *
550 * Supports GQA (grouped-query attention) where num_heads > num_kv_heads.
551 * Causal masking: token t can only attend to positions 0..t (inclusive).
552 *
553 * @param q Query [num_heads, tokens, head_dim]
554 * @param k Key [num_kv_heads, seq_len, head_dim]
555 * @param v Value [num_kv_heads, seq_len, head_dim]
556 * @param out Output [num_heads, tokens, head_dim]
557 * @param num_heads Number of query heads
558 * @param num_kv_heads Number of key/value heads (for GQA)
559 * @param tokens Number of query tokens
560 * @param seq_len Key/value sequence length (for prefill: seq_len == tokens)
561 * @param head_dim Dimension per head
562 */
563void ck_test_attention_causal(const float *q,
564 const float *k,
565 const float *v,
566 float *out,
567 int num_heads,
568 int num_kv_heads,
569 int tokens,
570 int seq_len,
571 int head_dim);
572
573/* ============================================================================
574 * Mega-Fused Kernels
575 * ============================================================================ */
576
577/**
578 * @brief Test mega-fused OutProj + MLP kernel (Q5_0 weights)
579 *
580 * This tests the mega_fused_outproj_mlp_prefill kernel which fuses:
581 * 1. Quantize attention output (head-major) to Q8_0
582 * 2. OutProj: attn_out @ W_o (Q5_0) → h1
583 * 3. Residual: h1 += residual
584 * 4. RMSNorm: h1 → ln2_out
585 * 5. MLP: silu(ln2_out @ W_gate) * (ln2_out @ W_up) @ W2
586 * 6. Residual: output += h1
587 *
588 * @param attn_out Attention output [num_heads, tokens, head_dim] (FP32, head-major)
589 * @param residual Residual input [tokens, embed_dim] (FP32)
590 * @param ln2_gamma RMSNorm gamma [embed_dim] (FP32)
591 * @param wo OutProj weights [embed_dim, embed_dim] (Q5_0)
592 * @param w1 MLP W1 weights [2*intermediate, embed_dim] (Q5_0)
593 * @param w2 MLP W2 weights [embed_dim, intermediate] (Q4_K or Q6_K)
594 * @param output Output [tokens, embed_dim] (FP32)
595 * @param tokens Number of tokens
596 * @param num_heads Number of attention heads
597 * @param head_dim Dimension per head
598 * @param embed_dim Embedding dimension (= num_heads * head_dim)
599 * @param intermediate MLP intermediate dimension
600 * @param eps RMSNorm epsilon
601 * @param w2_is_q6k If true, W2 is Q6_K; if false, W2 is Q4_K
602 */
604 const float *attn_out,
605 const float *residual,
606 const float *ln2_gamma,
607 const void *wo,
608 const void *w1,
609 const void *w2,
610 float *output,
611 int tokens,
612 int num_heads,
613 int head_dim,
614 int embed_dim,
615 int intermediate,
616 float eps,
617 int w2_is_q6k);
618
619/* ============================================================================
620 * Utility Functions
621 * ============================================================================ */
622
623/**
624 * @brief Get Q4_K block size in bytes
625 */
626int ck_get_block_q4_k_size(void);
627
628/**
629 * @brief Get Q6_K block size in bytes
630 */
631int ck_get_block_q6_k_size(void);
632
633/**
634 * @brief Get Q8_K block size in bytes
635 */
636int ck_get_block_q8_k_size(void);
637
638/**
639 * @brief Get QK_K (elements per super-block)
640 */
641int ck_get_qk_k(void);
642
643#ifdef __cplusplus
644}
645#endif
646
647#endif /* CK_PARITY_API_H */
void ck_test_quantize_q8_k(const float *src, void *dst, int n)
Quantize FP32 to Q8_K (for activations)
void ck_test_gemm_q4_k(const void *weight_q4k, const float *input_f32, float *output, int rows, int cols, int n_tokens)
Q4_K GEMM - batched matrix multiply with quantized weights.
int ck_get_block_q8_k_size(void)
Get Q8_K block size in bytes.
void ck_test_dequant_q6_k(const void *src, float *dst, int n)
Dequantize Q6_K data to FP32.
void ck_test_rope(float *q, float *k, int n_tokens, int n_heads, int n_heads_kv, int head_dim, int pos_offset, float theta)
RoPE (Rotary Position Embedding)
void ck_test_recurrent_silu(const float *x, float *out, int rows, int dim)
Apply SiLU elementwise to recurrent rows.
void ck_test_recurrent_dt_gate(const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int dim)
Transform recurrent alpha rows into the DeltaNet gate.
void ck_test_gated_deltanet_autoregressive(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)
Gated DeltaNet autoregressive update.
void ck_test_attn_gate_sigmoid_mul(const float *x, const float *gate, float *out, int rows, int dim)
Multiply attention output rows by sigmoid(gate) elementwise.
void ck_test_split_q_gate(const float *packed_qg, float *q, float *gate, int rows, int q_dim, int gate_dim, int group_dim)
Split a packed full-attention Q+gate matrix into Q rows and gate rows.
void ck_test_gemv_q5_0_q8_0(const void *weight_q5_0, const float *input_f32, float *output, int rows, int cols)
Q5_0 x Q8_0 quantized GEMV - matches llama.cpp's approach.
void ck_test_recurrent_conv_state_update(const float *state_in, const float *q, const float *k, const float *v, float *conv_x, float *state_out, int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim)
Build the recurrent convolution input history window.
void ck_test_recurrent_split_conv_qkv(const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim)
Split the post-convolution recurrent packed QKV rows.
void ck_test_dequant_q4_0(const void *src, float *dst, int n)
Dequantize Q4_0 data to FP32.
void ck_test_softmax(const float *input, float *output, int n)
Softmax (simple, non-causal)
void ck_test_rmsnorm(const float *input, const float *weight, float *output, int n_tokens, int dim, float eps)
RMSNorm.
void ck_test_gemm_q5_0(const void *weight_q5_0, const float *input_f32, float *output, int rows, int cols, int n_tokens)
Q5_0 GEMM - batched matrix multiply with Q5_0 weights (32-element blocks)
void ck_test_dequant_q4_k(const void *src, float *dst, int n)
Dequantize Q4_K data to FP32.
void ck_test_attention_causal(const float *q, const float *k, const float *v, float *out, int num_heads, int num_kv_heads, int tokens, int seq_len, int head_dim)
Multi-head causal attention for prefill (head-major layout)
void ck_test_gemv_q4_k(const void *weight_q4k, const float *input_f32, float *output, int cols)
Q4_K GEMV - dot product of quantized weights and FP32 input.
void ck_test_recurrent_split_qkv(const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim)
Split a packed recurrent QKV matrix into explicit Q, K, and V outputs.
void ck_test_vec_dot_q6_k_q8_k(const void *weight_q6_k, const void *input_q8_k, float *output, int cols)
void ck_test_gemv_q8_0_q8_0(const void *weight_q8_0, const float *input_f32, float *output, int rows, int cols)
Q8_0 x Q8_0 quantized GEMV - matches llama.cpp's approach.
void ck_test_vec_dot_q8_0_q8_0(const void *weight_q8_0, const void *input_q8_0, float *output, int cols)
Direct Q8_0 x Q8_0 dot product (takes pre-quantized Q8_0 input)
void ck_test_swiglu(const float *gate_up, float *output, int n_tokens, int intermediate_dim)
SwiGLU activation.
void ck_test_gemm_q6_k(const void *weight_q6k, const float *input_f32, float *output, int rows, int cols, int n_tokens)
Q6_K GEMM - batched matrix multiply with Q6_K weights.
void ck_test_vec_dot_q5_0_q8_0(const void *weight_q5_0, const void *input_q8_0, float *output, int cols)
Direct Q5_0 x Q8_0 dot product (takes pre-quantized Q8_0 input)
void ck_test_recurrent_norm_gate(const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
Per-head RMSNorm followed by SiLU(z) gating for recurrent outputs.
int ck_get_qk_k(void)
Get QK_K (elements per super-block)
void ck_test_gemm_q8_0(const void *weight_q8_0, const float *input_f32, float *output, int rows, int cols, int n_tokens)
Q8_0 GEMM - batched matrix multiply with Q8_0 weights (32-element blocks)
void ck_test_gemv_q5_0(const void *weight_q5_0, const float *input_f32, float *output, int rows, int cols)
Q5_0 GEMV - matrix-vector multiply with Q5_0 weights.
void ck_test_ssm_conv1d(const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
qwen3next/Qwen3.5 SSM causal depthwise convolution.
void ck_test_recurrent_qk_l2_norm(float *q, float *k, int rows, int q_dim, int k_dim, int head_dim, float eps)
Apply per-head L2 normalization to recurrent Q/K rows in-place.
void ck_test_rope_interleaved(float *q, float *k, int n_tokens, int n_heads, int n_heads_kv, int head_dim, int pos_offset, float theta)
RoPE with interleaved format (for llama.cpp compatibility)
int ck_get_block_q4_k_size(void)
Get Q4_K block size in bytes.
int ck_get_block_q6_k_size(void)
Get Q6_K block size in bytes.
void ck_test_gemv_q8_0(const void *weight_q8_0, const float *input_f32, float *output, int rows, int cols)
Q8_0 GEMV - matrix-vector multiply with Q8_0 weights.
void ck_test_gemv_q6_k(const void *weight_q6k, const float *input_f32, float *output, int cols)
Q6_K GEMV.
void ck_test_vec_dot_q4_k_q8_k(const void *weight_q4_k, const void *input_q8_k, float *output, int cols)
void ck_test_outproj_mlp_fused_q5_0(const float *attn_out, const float *residual, const float *ln2_gamma, const void *wo, const void *w1, const void *w2, float *output, int tokens, int num_heads, int head_dim, int embed_dim, int intermediate, float eps, int w2_is_q6k)
Test mega-fused OutProj + MLP kernel (Q5_0 weights)