← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
gemm_kernels_q5_1.c File Reference

GEMM/GEMV kernels with Q5_1 quantized weights. More...

#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "ckernel_quant.h"

Go to the source code of this file.

Functions

float dot_q5_1 (const void *w_q5_1, const float *x, int K)
 
void gemm_nt_q5_1 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 GEMM with transposed Q5_1 weights: C = A @ B^T.
 
void gemm_q5_1 (float *Y, const void *W, const float *X, int M, int N, int K)
 Matrix-matrix multiply with Q5_1 weights.
 
void gemm_q5_1_backward (float *dX, const void *W, const float *dY, int M, int N, int K)
 Batched backward pass.
 
void gemv_q5_1 (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV.
 
void gemv_q5_1_backward (float *dX, const void *W, const float *dY, int M, int K)
 Auto-dispatch backward.
 
void gemv_q5_1_backward_ref (float *dX, const void *W, const float *dY, int M, int K)
 Backward pass: compute input gradient.
 
void gemv_q5_1_ref (float *y, const void *W, const float *x, int M, int K)
 Matrix-vector multiply with Q5_1 weights (scalar reference)
 

Detailed Description

GEMM/GEMV kernels with Q5_1 quantized weights.

CK-ENGINE KERNEL RULES:

  1. NO malloc/free - memory via bump allocator, pointers passed in
  2. NO OpenMP - parallelization at orchestrator/codegen layer
  3. API must define: inputs, outputs, workspace, and memory layouts
  4. Pure computation - deterministic, no side effects

After changes: make test && make llamacpp-parity-full

Q5_1 Format:

  • 32 weights per block
  • 1 FP16 scale (d) per block
  • 1 FP16 minimum (m) per block
  • Low 4-bits stored like Q4_1 (16 bytes)
  • High 1-bit packed separately (4 bytes)
  • 24 bytes per 32 weights = 6.0 bits/weight

Dequantization: w = d * q5 + m where q5 = low4bit | (highbit << 4), giving values 0-31

Operations: Forward: Y = W @ X (W is Q5_1, X and Y are FP32) Backward: dX = W^T @ dY (gradient w.r.t. input)

Definition in file gemm_kernels_q5_1.c.

Function Documentation

◆ dot_q5_1()

float dot_q5_1 ( const void *  w_q5_1,
const float *  x,
int  K 
)

Definition at line 364 of file gemm_kernels_q5_1.c.

365{
366 float result;
367 gemv_q5_1(&result, w_q5_1, x, 1, K);
368 return result;
369}
void gemv_q5_1(float *y, const void *W, const float *x, int M, int K)
Auto-dispatch GEMV.

References gemv_q5_1().

◆ gemm_nt_q5_1()

void gemm_nt_q5_1 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

GEMM with transposed Q5_1 weights: C = A @ B^T.

Parameters
AInput activations [M x K], row-major FP32
BWeight matrix in Q5_1 format [N x K], row-major quantized
biasOptional bias [N], NULL if not used
COutput [M x N], row-major FP32
MBatch size (number of tokens)
NOutput dimension
KInput dimension

Definition at line 314 of file gemm_kernels_q5_1.c.

319{
320 const block_q5_1 *blocks = (const block_q5_1 *)B;
321 const int blocks_per_row = K / QK5_1;
322
323 for (int m = 0; m < M; m++) {
324 const float *a_row = &A[m * K];
325
326 for (int n = 0; n < N; n++) {
327 float sum = 0.0f;
328
329 for (int b = 0; b < blocks_per_row; b++) {
330 const block_q5_1 *block = &blocks[n * blocks_per_row + b];
331 const float d = CK_FP16_TO_FP32(block->d);
332 const float min = CK_FP16_TO_FP32(block->m);
333 const float *ap = &a_row[b * QK5_1];
334
335 uint32_t qh;
336 memcpy(&qh, block->qh, sizeof(qh));
337
338 for (int i = 0; i < QK5_1 / 2; i++) {
339 const uint8_t packed = block->qs[i];
340 const int lo0 = (packed & 0x0F);
341 const int lo1 = (packed >> 4);
342 const int hi0 = ((qh >> (2 * i + 0)) & 1) << 4;
343 const int hi1 = ((qh >> (2 * i + 1)) & 1) << 4;
344 const int q0 = lo0 | hi0;
345 const int q1 = lo1 | hi1;
346
347 const float w0 = d * (float)q0 + min;
348 const float w1 = d * (float)q1 + min;
349
350 sum += w0 * ap[2 * i + 0];
351 sum += w1 * ap[2 * i + 1];
352 }
353 }
354
355 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
356 }
357 }
358}
#define CK_FP16_TO_FP32(x)
#define QK5_1
#define C(color)
Definition show_config.c:39
uint8_t qs[32/2]
uint8_t qh[4]

References C, CK_FP16_TO_FP32, block_q5_1::d, block_q5_1::m, block_q5_1::qh, QK5_1, and block_q5_1::qs.

Referenced by ck_gemm_nt_quant().

◆ gemm_q5_1()

void gemm_q5_1 ( float *  Y,
const void *  W,
const float *  X,
int  M,
int  N,
int  K 
)

Matrix-matrix multiply with Q5_1 weights.

Definition at line 206 of file gemm_kernels_q5_1.c.

210{
211 for (int n = 0; n < N; n++) {
212 gemv_q5_1(&Y[n * M], W, &X[n * K], M, K);
213 }
214}

References gemv_q5_1().

◆ gemm_q5_1_backward()

void gemm_q5_1_backward ( float *  dX,
const void *  W,
const float *  dY,
int  M,
int  N,
int  K 
)

Batched backward pass.

Definition at line 289 of file gemm_kernels_q5_1.c.

293{
294 for (int n = 0; n < N; n++) {
295 gemv_q5_1_backward(&dX[n * K], W, &dY[n * M], M, K);
296 }
297}
void gemv_q5_1_backward(float *dX, const void *W, const float *dY, int M, int K)
Auto-dispatch backward.

References gemv_q5_1_backward().

◆ gemv_q5_1()

void gemv_q5_1 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV.

Definition at line 187 of file gemm_kernels_q5_1.c.

191{
192#ifdef __AVX512F__
193 gemv_q5_1_avx512(y, W, x, M, K);
194#else
195 gemv_q5_1_ref(y, W, x, M, K);
196#endif
197}
void gemv_q5_1_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q5_1 weights (scalar reference)

References gemv_q5_1_ref().

Referenced by dot_q5_1(), and gemm_q5_1().

◆ gemv_q5_1_backward()

void gemv_q5_1_backward ( float *  dX,
const void *  W,
const float *  dY,
int  M,
int  K 
)

Auto-dispatch backward.

Definition at line 278 of file gemm_kernels_q5_1.c.

282{
283 gemv_q5_1_backward_ref(dX, W, dY, M, K);
284}
void gemv_q5_1_backward_ref(float *dX, const void *W, const float *dY, int M, int K)
Backward pass: compute input gradient.

References gemv_q5_1_backward_ref().

Referenced by gemm_q5_1_backward().

◆ gemv_q5_1_backward_ref()

void gemv_q5_1_backward_ref ( float *  dX,
const void *  W,
const float *  dY,
int  M,
int  K 
)

Backward pass: compute input gradient.

Parameters
dXOutput gradient w.r.t. input [K]
WWeight matrix in Q5_1 format [M x K]
dYGradient w.r.t. output [M]
MNumber of output rows
KNumber of columns (input dimension)

Definition at line 229 of file gemm_kernels_q5_1.c.

233{
234 const block_q5_1 *blocks = (const block_q5_1 *)W;
235 const int blocks_per_row = K / QK5_1;
236
237 /* Zero output gradient */
238 memset(dX, 0, K * sizeof(float));
239
240 /* Accumulate: dX += W^T @ dY */
241 for (int row = 0; row < M; row++) {
242 const float dy = dY[row];
243
244 for (int b = 0; b < blocks_per_row; b++) {
245 const block_q5_1 *block = &blocks[row * blocks_per_row + b];
246 const float d = CK_FP16_TO_FP32(block->d);
247 const float m = CK_FP16_TO_FP32(block->m);
248 float *dxp = &dX[b * QK5_1];
249
250 /* Get high bits */
251 uint32_t qh;
252 memcpy(&qh, block->qh, sizeof(qh));
253
254 for (int i = 0; i < QK5_1 / 2; i++) {
255 const uint8_t packed = block->qs[i];
256
257 /* Extract and reconstruct 5-bit values */
258 const int lo0 = (packed & 0x0F);
259 const int lo1 = (packed >> 4);
260 const int hi0 = ((qh >> (2 * i + 0)) & 1) << 4;
261 const int hi1 = ((qh >> (2 * i + 1)) & 1) << 4;
262 const int q0 = lo0 | hi0;
263 const int q1 = lo1 | hi1;
264
265 const float w0 = d * (float)q0 + m;
266 const float w1 = d * (float)q1 + m;
267
268 dxp[2 * i + 0] += w0 * dy;
269 dxp[2 * i + 1] += w1 * dy;
270 }
271 }
272 }
273}

References CK_FP16_TO_FP32, block_q5_1::d, block_q5_1::m, block_q5_1::qh, QK5_1, and block_q5_1::qs.

Referenced by gemv_q5_1_backward().

◆ gemv_q5_1_ref()

void gemv_q5_1_ref ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Matrix-vector multiply with Q5_1 weights (scalar reference)

Parameters
yOutput vector [M]
WWeight matrix in Q5_1 format [M x K]
xInput vector [K]
MNumber of output rows
KNumber of columns (must be multiple of 32)

Definition at line 52 of file gemm_kernels_q5_1.c.

56{
57 const block_q5_1 *blocks = (const block_q5_1 *)W;
58 const int blocks_per_row = K / QK5_1;
59
60 for (int row = 0; row < M; row++) {
61 float sum = 0.0f;
62
63 for (int b = 0; b < blocks_per_row; b++) {
64 const block_q5_1 *block = &blocks[row * blocks_per_row + b];
65 const float d = CK_FP16_TO_FP32(block->d);
66 const float m = CK_FP16_TO_FP32(block->m);
67 const float *xp = &x[b * QK5_1];
68
69 /* Get high bits as 32-bit integer */
70 uint32_t qh;
71 memcpy(&qh, block->qh, sizeof(qh));
72
73 for (int i = 0; i < QK5_1 / 2; i++) {
74 const uint8_t packed = block->qs[i];
75
76 /* Extract low 4 bits */
77 const int lo0 = (packed & 0x0F);
78 const int lo1 = (packed >> 4);
79
80 /* Extract high bits */
81 const int hi0 = ((qh >> (2 * i + 0)) & 1) << 4;
82 const int hi1 = ((qh >> (2 * i + 1)) & 1) << 4;
83
84 /* Combine to 5-bit unsigned value */
85 const int q0 = lo0 | hi0;
86 const int q1 = lo1 | hi1;
87
88 /* Dequantize: w = d * q + m */
89 const float w0 = d * (float)q0 + m;
90 const float w1 = d * (float)q1 + m;
91
92 sum += w0 * xp[2 * i + 0];
93 sum += w1 * xp[2 * i + 1];
94 }
95 }
96
97 y[row] = sum;
98 }
99}

References CK_FP16_TO_FP32, block_q5_1::d, block_q5_1::m, block_q5_1::qh, QK5_1, and block_q5_1::qs.

Referenced by gemv_q5_1().