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

Q5_1 x Q8_1 contract kernels used for ggml parity (Gemma-sensitive path) More...

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

Go to the source code of this file.

Macros

#define CK_Q51_STACK_Q8_BLOCKS   256
 
#define QK8_1   32
 

Functions

static float dot_q5_1_q8_1_block (const block_q5_1 *w, const block_q8_1 *x)
 
void gemm_nt_q5_1_q8_1 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_m2 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_m4 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_m8 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_ref (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemv_q5_1_q8_1 (float *y, const void *W, const float *x, int M, int K)
 
void gemv_q5_1_q8_1_ref (float *y, const void *W, const void *x_q8, int M, int K)
 
static void quantize_row_q8_1_scalar (const float *x, block_q8_1 *y, int k)
 

Detailed Description

Q5_1 x Q8_1 contract kernels used for ggml parity (Gemma-sensitive path)

Definition in file gemm_kernels_q5_1_q8_1.c.

Macro Definition Documentation

◆ CK_Q51_STACK_Q8_BLOCKS

#define CK_Q51_STACK_Q8_BLOCKS   256

Definition at line 16 of file gemm_kernels_q5_1_q8_1.c.

◆ QK8_1

#define QK8_1   32

Definition at line 22 of file gemm_kernels_q5_1_q8_1.c.

Function Documentation

◆ dot_q5_1_q8_1_block()

static float dot_q5_1_q8_1_block ( const block_q5_1 *  w,
const block_q8_1 *  x 
)
static

Definition at line 224 of file gemm_kernels_q5_1_q8_1.c.

224 {
225#if defined(__AVX2__)
226 return dot_q5_1_q8_1_block_avx2(w, x);
227#else
228 uint32_t qh;
229 memcpy(&qh, w->qh, sizeof(qh));
230
231 int sumi0 = 0;
232 int sumi1 = 0;
233 for (int j = 0; j < QK5_1 / 2; ++j) {
234 const uint8_t xh0 = (uint8_t)(((qh >> (j + 0)) << 4) & 0x10);
235 const uint8_t xh1 = (uint8_t)(((qh >> (j + 12)) ) & 0x10);
236 const int32_t q0 = (int32_t)((w->qs[j] & 0x0F) | xh0);
237 const int32_t q1 = (int32_t)((w->qs[j] >> 4) | xh1);
238 sumi0 += q0 * (int32_t)x->qs[j];
239 sumi1 += q1 * (int32_t)x->qs[j + QK5_1 / 2];
240 }
241
242 const float wd = CK_FP16_TO_FP32(w->d);
243 const float wm = CK_FP16_TO_FP32(w->m);
244 const float xd = CK_FP16_TO_FP32(x->d);
245 const float xs = CK_FP16_TO_FP32(x->s);
246 return (wd * xd) * (float)(sumi0 + sumi1) + wm * xs;
247#endif
248}
#define CK_FP16_TO_FP32(x)
#define QK5_1
uint8_t qs[32/2]
uint8_t qh[4]

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 gemm_nt_q5_1_q8_1(), gemm_nt_q5_1_q8_1_m2(), gemm_nt_q5_1_q8_1_ref(), and gemv_q5_1_q8_1_ref().

◆ gemm_nt_q5_1_q8_1()

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

Definition at line 320 of file gemm_kernels_q5_1_q8_1.c.

327{
328 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
329 return;
330 }
331
332 const int blocks_per_row = K / QK5_1;
333 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
334 return;
335 }
336
337 const block_q5_1 *W = (const block_q5_1 *)B;
338
339 for (int m = 0; m < M; ++m) {
340 block_q8_1 a_q8[CK_Q51_STACK_Q8_BLOCKS];
341 quantize_row_q8_1_scalar(&A[m * K], a_q8, K);
342 float *c_row = &C[(size_t)m * (size_t)N];
343
344 int n = 0;
345 for (; n + 7 < N; n += 8) {
346 const block_q5_1 *w0 = &W[(size_t)(n + 0) * (size_t)blocks_per_row];
347 const block_q5_1 *w1 = &W[(size_t)(n + 1) * (size_t)blocks_per_row];
348 const block_q5_1 *w2 = &W[(size_t)(n + 2) * (size_t)blocks_per_row];
349 const block_q5_1 *w3 = &W[(size_t)(n + 3) * (size_t)blocks_per_row];
350 const block_q5_1 *w4 = &W[(size_t)(n + 4) * (size_t)blocks_per_row];
351 const block_q5_1 *w5 = &W[(size_t)(n + 5) * (size_t)blocks_per_row];
352 const block_q5_1 *w6 = &W[(size_t)(n + 6) * (size_t)blocks_per_row];
353 const block_q5_1 *w7 = &W[(size_t)(n + 7) * (size_t)blocks_per_row];
354 float s0 = 0.0f;
355 float s1 = 0.0f;
356 float s2 = 0.0f;
357 float s3 = 0.0f;
358 float s4 = 0.0f;
359 float s5 = 0.0f;
360 float s6 = 0.0f;
361 float s7 = 0.0f;
362
363 for (int b = 0; b < blocks_per_row; ++b) {
364 const block_q8_1 *x = &a_q8[b];
365 s0 += dot_q5_1_q8_1_block(&w0[b], x);
366 s1 += dot_q5_1_q8_1_block(&w1[b], x);
367 s2 += dot_q5_1_q8_1_block(&w2[b], x);
368 s3 += dot_q5_1_q8_1_block(&w3[b], x);
369 s4 += dot_q5_1_q8_1_block(&w4[b], x);
370 s5 += dot_q5_1_q8_1_block(&w5[b], x);
371 s6 += dot_q5_1_q8_1_block(&w6[b], x);
372 s7 += dot_q5_1_q8_1_block(&w7[b], x);
373 }
374
375 c_row[n + 0] = s0 + (bias ? bias[n + 0] : 0.0f);
376 c_row[n + 1] = s1 + (bias ? bias[n + 1] : 0.0f);
377 c_row[n + 2] = s2 + (bias ? bias[n + 2] : 0.0f);
378 c_row[n + 3] = s3 + (bias ? bias[n + 3] : 0.0f);
379 c_row[n + 4] = s4 + (bias ? bias[n + 4] : 0.0f);
380 c_row[n + 5] = s5 + (bias ? bias[n + 5] : 0.0f);
381 c_row[n + 6] = s6 + (bias ? bias[n + 6] : 0.0f);
382 c_row[n + 7] = s7 + (bias ? bias[n + 7] : 0.0f);
383 }
384
385 for (; n < N; ++n) {
386 const block_q5_1 *w_row = &W[(size_t)n * (size_t)blocks_per_row];
387 float sum = 0.0f;
388 for (int b = 0; b < blocks_per_row; ++b) {
389 sum += dot_q5_1_q8_1_block(&w_row[b], &a_q8[b]);
390 }
391 c_row[n] = sum + (bias ? bias[n] : 0.0f);
392 }
393 }
394}
static void quantize_row_q8_1_scalar(const float *x, block_q8_1 *y, int k)
#define CK_Q51_STACK_Q8_BLOCKS
static float dot_q5_1_q8_1_block(const block_q5_1 *w, const block_q8_1 *x)
#define C(color)
Definition show_config.c:39

References C, CK_Q51_STACK_Q8_BLOCKS, dot_q5_1_q8_1_block(), QK5_1, and quantize_row_q8_1_scalar().

Referenced by gemm_nt_q5_1_q8_1_m4().

◆ gemm_nt_q5_1_q8_1_m2()

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

Definition at line 396 of file gemm_kernels_q5_1_q8_1.c.

398{
399 if (!A || !B || !C || M != 2 || N <= 0 || K <= 0 || (K % QK5_1) != 0)
400 return;
401 const int blocks_per_row = K / QK5_1;
402 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) return;
403 block_q8_1 x[2][CK_Q51_STACK_Q8_BLOCKS];
404 quantize_row_q8_1_scalar(A, x[0], K);
405 quantize_row_q8_1_scalar(A + K, x[1], K);
406 const block_q5_1 *weights = (const block_q5_1 *)B;
407 for (int n = 0; n < N; ++n) {
408 const block_q5_1 *w = weights + (size_t)n * (size_t)blocks_per_row;
409 float sums[2] = {0.0f, 0.0f};
410 for (int b = 0; b < blocks_per_row; ++b) {
411#if defined(__AVX2__)
412 float partial[2];
413 dot_q5_1_q8_1_block_m2_avx2(w + b, x[0] + b, x[1] + b, partial);
414 sums[0] += partial[0];
415 sums[1] += partial[1];
416#else
417 sums[0] += dot_q5_1_q8_1_block(w + b, x[0] + b);
418 sums[1] += dot_q5_1_q8_1_block(w + b, x[1] + b);
419#endif
420 }
421 const float add = bias ? bias[n] : 0.0f;
422 C[n] = sums[0] + add;
423 C[(size_t)N + n] = sums[1] + add;
424 }
425}

References C, CK_Q51_STACK_Q8_BLOCKS, dot_q5_1_q8_1_block(), QK5_1, and quantize_row_q8_1_scalar().

◆ gemm_nt_q5_1_q8_1_m4()

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

Definition at line 427 of file gemm_kernels_q5_1_q8_1.c.

434{
435#if defined(__AVX2__)
436 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
437 return;
438 }
439
440 const int blocks_per_row = K / QK5_1;
441 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
442 gemm_nt_q5_1_q8_1(A, B, bias, C, M, N, K);
443 return;
444 }
445
446 const block_q5_1 *weights = (const block_q5_1 *)B;
447 int m = 0;
448 for (; m + 3 < M; m += 4) {
449 block_q8_1 activation_q8[4][CK_Q51_STACK_Q8_BLOCKS];
450 for (int row = 0; row < 4; ++row) {
452 &A[(size_t)(m + row) * (size_t)K], activation_q8[row], K);
453 }
454
455 for (int n = 0; n < N; ++n) {
456 const block_q5_1 *weight_row =
457 &weights[(size_t)n * (size_t)blocks_per_row];
458 float sums[4] = {0.0f, 0.0f, 0.0f, 0.0f};
459 for (int block = 0; block < blocks_per_row; ++block) {
460 float partial[4];
461 dot_q5_1_q8_1_block_m4_avx2(
462 &weight_row[block],
463 &activation_q8[0][block], &activation_q8[1][block],
464 &activation_q8[2][block], &activation_q8[3][block], partial);
465 sums[0] += partial[0];
466 sums[1] += partial[1];
467 sums[2] += partial[2];
468 sums[3] += partial[3];
469 }
470 const float add = bias ? bias[n] : 0.0f;
471 C[(size_t)(m + 0) * (size_t)N + n] = sums[0] + add;
472 C[(size_t)(m + 1) * (size_t)N + n] = sums[1] + add;
473 C[(size_t)(m + 2) * (size_t)N + n] = sums[2] + add;
474 C[(size_t)(m + 3) * (size_t)N + n] = sums[3] + add;
475 }
476 }
477
478 if (m < M) {
480 A + (size_t)m * (size_t)K, B, bias,
481 C + (size_t)m * (size_t)N, M - m, N, K);
482 }
483#else
484 gemm_nt_q5_1_q8_1(A, B, bias, C, M, N, K);
485#endif
486}
void gemm_nt_q5_1_q8_1(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, CK_Q51_STACK_Q8_BLOCKS, gemm_nt_q5_1_q8_1(), QK5_1, and quantize_row_q8_1_scalar().

Referenced by gemm_nt_q5_1_q8_1_m8().

◆ gemm_nt_q5_1_q8_1_m8()

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

Definition at line 488 of file gemm_kernels_q5_1_q8_1.c.

495{
496#if defined(__AVX2__)
497 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
498 return;
499 }
500
501 const int blocks_per_row = K / QK5_1;
502 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
503 gemm_nt_q5_1_q8_1_m4(A, B, bias, C, M, N, K);
504 return;
505 }
506
507 const block_q5_1 *weights = (const block_q5_1 *)B;
508 int m = 0;
509 for (; m + 7 < M; m += 8) {
510 block_q8_1 activation_q8[8][CK_Q51_STACK_Q8_BLOCKS];
511 for (int row = 0; row < 8; ++row) {
513 &A[(size_t)(m + row) * (size_t)K], activation_q8[row], K);
514 }
515
516 for (int n = 0; n < N; ++n) {
517 const block_q5_1 *weight_row =
518 &weights[(size_t)n * (size_t)blocks_per_row];
519 float sums[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
520 for (int block = 0; block < blocks_per_row; ++block) {
521 const block_q8_1 *rows[8] = {
522 &activation_q8[0][block], &activation_q8[1][block],
523 &activation_q8[2][block], &activation_q8[3][block],
524 &activation_q8[4][block], &activation_q8[5][block],
525 &activation_q8[6][block], &activation_q8[7][block],
526 };
527 float partial[8];
528 dot_q5_1_q8_1_block_m8_avx2(&weight_row[block], rows, partial);
529 for (int row = 0; row < 8; ++row) {
530 sums[row] += partial[row];
531 }
532 }
533 const float add = bias ? bias[n] : 0.0f;
534 for (int row = 0; row < 8; ++row) {
535 C[(size_t)(m + row) * (size_t)N + n] = sums[row] + add;
536 }
537 }
538 }
539
540 if (m < M) {
542 A + (size_t)m * (size_t)K, B, bias,
543 C + (size_t)m * (size_t)N, M - m, N, K);
544 }
545#else
546 gemm_nt_q5_1_q8_1_m4(A, B, bias, C, M, N, K);
547#endif
548}
void gemm_nt_q5_1_q8_1_m4(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, CK_Q51_STACK_Q8_BLOCKS, gemm_nt_q5_1_q8_1_m4(), QK5_1, and quantize_row_q8_1_scalar().

◆ gemm_nt_q5_1_q8_1_ref()

void gemm_nt_q5_1_q8_1_ref ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 273 of file gemm_kernels_q5_1_q8_1.c.

278{
279 if (!A_q8 || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
280 return;
281 }
282
283 const block_q8_1 *A = (const block_q8_1 *)A_q8;
284 const block_q5_1 *W = (const block_q5_1 *)B;
285 const int blocks_per_row = K / QK5_1;
286
287 for (int m = 0; m < M; ++m) {
288 const block_q8_1 *a_row = &A[m * blocks_per_row];
289 for (int n = 0; n < N; ++n) {
290 const block_q5_1 *w_row = &W[n * blocks_per_row];
291 float sum = 0.0f;
292 for (int b = 0; b < blocks_per_row; ++b) {
293 sum += dot_q5_1_q8_1_block(&w_row[b], &a_row[b]);
294 }
295 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
296 }
297 }
298}

References C, dot_q5_1_q8_1_block(), and QK5_1.

◆ gemv_q5_1_q8_1()

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

Definition at line 300 of file gemm_kernels_q5_1_q8_1.c.

305{
306 if (!y || !W || !x || M <= 0 || K <= 0 || (K % QK5_1) != 0) {
307 return;
308 }
309
310 const int blocks_per_row = K / QK5_1;
311 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
312 return;
313 }
314
315 block_q8_1 x_q8[CK_Q51_STACK_Q8_BLOCKS];
316 quantize_row_q8_1_scalar(x, x_q8, K);
317 gemv_q5_1_q8_1_ref(y, W, x_q8, M, K);
318}
void gemv_q5_1_q8_1_ref(float *y, const void *W, const void *x_q8, int M, int K)

References CK_Q51_STACK_Q8_BLOCKS, gemv_q5_1_q8_1_ref(), QK5_1, and quantize_row_q8_1_scalar().

◆ gemv_q5_1_q8_1_ref()

void gemv_q5_1_q8_1_ref ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 250 of file gemm_kernels_q5_1_q8_1.c.

254{
255 if (!y || !W || !x_q8 || M <= 0 || K <= 0 || (K % QK5_1) != 0) {
256 return;
257 }
258
259 const block_q5_1 *blocks = (const block_q5_1 *)W;
260 const block_q8_1 *x = (const block_q8_1 *)x_q8;
261 const int blocks_per_row = K / QK5_1;
262
263 for (int row = 0; row < M; ++row) {
264 const block_q5_1 *w_row = &blocks[row * blocks_per_row];
265 float sum = 0.0f;
266 for (int b = 0; b < blocks_per_row; ++b) {
267 sum += dot_q5_1_q8_1_block(&w_row[b], &x[b]);
268 }
269 y[row] = sum;
270 }
271}

References dot_q5_1_q8_1_block(), and QK5_1.

Referenced by gemv_q5_1_q8_1().

◆ quantize_row_q8_1_scalar()

static void quantize_row_q8_1_scalar ( const float *  x,
block_q8_1 *  y,
int  k 
)
static

Definition at line 63 of file gemm_kernels_q5_1_q8_1.c.

63 {
64 const int nb = k / QK8_1;
65 for (int b = 0; b < nb; ++b) {
66 const float *xb = x + (size_t)b * QK8_1;
67 float amax = 0.0f;
68 for (int j = 0; j < QK8_1; ++j) {
69 float av = xb[j] >= 0.0f ? xb[j] : -xb[j];
70 if (av > amax) amax = av;
71 }
72
73 const float d = amax / 127.0f;
74 const float id = (d != 0.0f) ? (1.0f / d) : 0.0f;
75 y[b].d = CK_FP32_TO_FP16(d);
76
77 int sum = 0;
78 for (int j = 0; j < QK8_1; ++j) {
79 int q = (int)roundf(xb[j] * id);
80 y[b].qs[j] = (int8_t)q;
81 sum += q;
82 }
83 y[b].s = CK_FP32_TO_FP16((float)sum * d);
84 }
85}
#define CK_FP32_TO_FP16(x)
#define QK8_1

References CK_FP32_TO_FP16, and QK8_1.

Referenced by gemm_nt_q5_1_q8_1(), gemm_nt_q5_1_q8_1_m2(), gemm_nt_q5_1_q8_1_m4(), gemm_nt_q5_1_q8_1_m8(), and gemv_q5_1_q8_1().