58 const int blocks_per_row = K /
QK5_1;
60 for (
int row = 0; row < M; row++) {
63 for (
int b = 0; b < blocks_per_row; b++) {
64 const block_q5_1 *block = &blocks[row * blocks_per_row + b];
67 const float *xp = &x[b *
QK5_1];
71 memcpy(&qh, block->
qh,
sizeof(qh));
73 for (
int i = 0; i <
QK5_1 / 2; i++) {
74 const uint8_t packed = block->
qs[i];
77 const int lo0 = (packed & 0x0F);
78 const int lo1 = (packed >> 4);
81 const int hi0 = ((qh >> (2 * i + 0)) & 1) << 4;
82 const int hi1 = ((qh >> (2 * i + 1)) & 1) << 4;
85 const int q0 = lo0 | hi0;
86 const int q1 = lo1 | hi1;
89 const float w0 = d * (float)q0 + m;
90 const float w1 = d * (float)q1 + m;
92 sum += w0 * xp[2 * i + 0];
93 sum += w1 * xp[2 * i + 1];
105void gemv_q5_1_avx512(
float *y,
111 const int blocks_per_row = K /
QK5_1;
112 const __m512i mask_lo = _mm512_set1_epi32(0x0F);
114 for (
int row = 0; row < M; row++) {
115 __m512 acc = _mm512_setzero_ps();
117 for (
int b = 0; b < blocks_per_row; b++) {
118 const block_q5_1 *block = &blocks[row * blocks_per_row + b];
121 const float *xp = &x[b *
QK5_1];
125 memcpy(&qh, block->
qh,
sizeof(qh));
128 __m128i packed = _mm_loadu_si128((
const __m128i *)block->
qs);
129 __m512i bytes = _mm512_cvtepu8_epi32(packed);
132 __m512i lo = _mm512_and_epi32(bytes, mask_lo);
133 __m512i hi_shift = _mm512_srli_epi32(bytes, 4);
136 __m512i qh_lo = _mm512_set_epi32(
137 ((qh >> 30) & 1) << 4, ((qh >> 28) & 1) << 4,
138 ((qh >> 26) & 1) << 4, ((qh >> 24) & 1) << 4,
139 ((qh >> 22) & 1) << 4, ((qh >> 20) & 1) << 4,
140 ((qh >> 18) & 1) << 4, ((qh >> 16) & 1) << 4,
141 ((qh >> 14) & 1) << 4, ((qh >> 12) & 1) << 4,
142 ((qh >> 10) & 1) << 4, ((qh >> 8) & 1) << 4,
143 ((qh >> 6) & 1) << 4, ((qh >> 4) & 1) << 4,
144 ((qh >> 2) & 1) << 4, ((qh >> 0) & 1) << 4
148 __m512i qh_hi = _mm512_set_epi32(
149 ((qh >> 31) & 1) << 4, ((qh >> 29) & 1) << 4,
150 ((qh >> 27) & 1) << 4, ((qh >> 25) & 1) << 4,
151 ((qh >> 23) & 1) << 4, ((qh >> 21) & 1) << 4,
152 ((qh >> 19) & 1) << 4, ((qh >> 17) & 1) << 4,
153 ((qh >> 15) & 1) << 4, ((qh >> 13) & 1) << 4,
154 ((qh >> 11) & 1) << 4, ((qh >> 9) & 1) << 4,
155 ((qh >> 7) & 1) << 4, ((qh >> 5) & 1) << 4,
156 ((qh >> 3) & 1) << 4, ((qh >> 1) & 1) << 4
160 __m512i q_lo = _mm512_or_epi32(lo, qh_lo);
161 __m512i q_hi = _mm512_or_epi32(hi_shift, qh_hi);
164 __m512 w_lo = _mm512_fmadd_ps(_mm512_cvtepi32_ps(q_lo), vscale, vmin);
165 __m512 w_hi = _mm512_fmadd_ps(_mm512_cvtepi32_ps(q_hi), vscale, vmin);
168 __m512 x_even = _mm512_set_ps(
169 xp[30], xp[28], xp[26], xp[24], xp[22], xp[20], xp[18], xp[16],
170 xp[14], xp[12], xp[10], xp[8], xp[6], xp[4], xp[2], xp[0]);
171 __m512 x_odd = _mm512_set_ps(
172 xp[31], xp[29], xp[27], xp[25], xp[23], xp[21], xp[19], xp[17],
173 xp[15], xp[13], xp[11], xp[9], xp[7], xp[5], xp[3], xp[1]);
175 acc = _mm512_fmadd_ps(w_lo, x_even, acc);
176 acc = _mm512_fmadd_ps(w_hi, x_odd, acc);
179 y[row] = _mm512_reduce_add_ps(acc);
193 gemv_q5_1_avx512(y, W, x, M, K);
211 for (
int n = 0; n < N; n++) {
212 gemv_q5_1(&Y[n * M], W, &X[n * K], M, K);
235 const int blocks_per_row = K /
QK5_1;
238 memset(dX, 0, K *
sizeof(
float));
241 for (
int row = 0; row < M; row++) {
242 const float dy = dY[row];
244 for (
int b = 0; b < blocks_per_row; b++) {
245 const block_q5_1 *block = &blocks[row * blocks_per_row + b];
248 float *dxp = &dX[b *
QK5_1];
252 memcpy(&qh, block->
qh,
sizeof(qh));
254 for (
int i = 0; i <
QK5_1 / 2; i++) {
255 const uint8_t packed = block->
qs[i];
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;
265 const float w0 = d * (float)q0 + m;
266 const float w1 = d * (float)q1 + m;
268 dxp[2 * i + 0] += w0 * dy;
269 dxp[2 * i + 1] += w1 * dy;
294 for (
int n = 0; n < N; n++) {
321 const int blocks_per_row = K /
QK5_1;
323 for (
int m = 0; m < M; m++) {
324 const float *a_row = &A[m * K];
326 for (
int n = 0; n < N; n++) {
329 for (
int b = 0; b < blocks_per_row; b++) {
330 const block_q5_1 *block = &blocks[n * blocks_per_row + b];
333 const float *ap = &a_row[b *
QK5_1];
336 memcpy(&qh, block->
qh,
sizeof(qh));
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;
347 const float w0 = d * (float)q0 + min;
348 const float w1 = d * (float)q1 + min;
350 sum += w0 * ap[2 * i + 0];
351 sum += w1 * ap[2 * i + 1];
355 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
364float dot_q5_1(
const void *w_q5_1,
const float *x,
int K)
Quantization block structures for weight-only quantization.
#define CK_FP16_TO_FP32(x)
void gemm_q5_1_backward(float *dX, const void *W, const float *dY, int M, int N, int K)
Batched backward pass.
float dot_q5_1(const void *w_q5_1, const float *x, int K)
void gemv_q5_1(float *y, const void *W, const float *x, int M, int K)
Auto-dispatch GEMV.
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)
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 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_backward(float *dX, const void *W, const float *dY, int M, int K)
Auto-dispatch backward.
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.