CompressedGemma commited on
Commit
74795f9
·
verified ·
1 Parent(s): d3c3c83

Delete patch_llamacpp_hpcq_seg.py

Browse files
Files changed (1) hide show
  1. patch_llamacpp_hpcq_seg.py +0 -872
patch_llamacpp_hpcq_seg.py DELETED
@@ -1,872 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Patch llama.cpp so HPCQ.SEG.V1 band-major Q2_K/Q3_K files decode exactly.
3
-
4
- What this does
5
- --------------
6
- HPC-Quantize can emit tensors whose 256-weight superblocks are stored in
7
- "band-major" slot order (each 16-slot sub-block holds one value band). The
8
- per-position inverse permutation is stored in a GGUF key-value array:
9
-
10
- HPCQ.SEG.V1.<tensor> : uint8[] (HQS1 codec, one band id per original
11
- position, nibble-packed for k <= 16)
12
-
13
- Stock llama.cpp decodes Q2_K/Q3_K positionally, so band-major payloads are
14
- garbage without help. This patch makes the ggml dequant paths consult the
15
- label channel and scatter each block back to original positions:
16
-
17
- * CPU : the reference ``dequantize_row_q2_K/q3_K`` scatter their writes
18
- (correct for get_rows / dequantizing ops). Weight matmuls on CPU fall
19
- back to F16 at load (``--cpu-f16``, default on) because CPU vec_dot is
20
- per-arch SIMD code.
21
- * CUDA: the device dequant + mul_mat-vec paths scatter via a device-side
22
- registry keyed by payload address range, so no kernel signatures or
23
- launchers change. Large-batch GEMM forcibly uses the (patched)
24
- convert-to-F16 path for segmented tensors.
25
-
26
- Usage
27
- -----
28
- python3 patch_llamacpp_hpcq_seg.py --llama /path/to/llama.cpp --check
29
- python3 patch_llamacpp_hpcq_seg.py --llama /path/to/llama.cpp --apply
30
- python3 patch_llamacpp_hpcq_seg.py --llama /path/to/llama.cpp --revert
31
- python3 patch_llamacpp_hpcq_seg.py --selftest
32
-
33
- The patch is idempotent (marker based) and leaves .hpcq-bak backups.
34
- """
35
-
36
- from __future__ import annotations
37
-
38
- import argparse
39
- import shutil
40
- import subprocess
41
- import sys
42
- import tempfile
43
- from pathlib import Path
44
-
45
- BEGIN = "HPCQ_SEG_PATCH_BEGIN"
46
- END = "HPCQ_SEG_PATCH_END"
47
- HEADER_NAME = "hpcq-seg.h"
48
-
49
- # --------------------------------------------------------------------------
50
- # 1. New header: shared host/device helpers (no external includes needed)
51
- # --------------------------------------------------------------------------
52
-
53
- HEADER = r"""// hpcq-seg.h — HPCQ.SEG.V1 band-major scatter support for Q2_K / Q3_K.
54
- // Generated by HPC-Quantize tools/patch_llamacpp_hpcq_seg.py. Do not edit.
55
- #pragma once
56
-
57
- #include <cstdint>
58
- #include <cstring>
59
-
60
- #define HPCQ_SEG_PREFIX "HPCQ.SEG.V1."
61
- #define HPCQ_SEG_MAX_ENTRIES 1024
62
-
63
- // ---------------------------------------------------------------------------
64
- // label channel codec: "HQS1" | u8 k | u8 enc | u32 n | payload
65
- // enc 0: two band ids per byte (low nibble = even index)
66
- // enc 1: raw u8 band ids
67
- // ---------------------------------------------------------------------------
68
- static inline bool hpcq_seg_decode(const uint8_t * c, size_t n_bytes,
69
- uint8_t * labels, size_t n_labels) {
70
- if (n_bytes < 10 || c[0] != 'H' || c[1] != 'Q' || c[2] != 'S' || c[3] != '1') {
71
- return false;
72
- }
73
- const uint8_t enc = c[5];
74
- const uint32_t n = (uint32_t) c[6] | ((uint32_t) c[7] << 8) |
75
- ((uint32_t) c[8] << 16) | ((uint32_t) c[9] << 24);
76
- if ((size_t) n != n_labels) {
77
- return false;
78
- }
79
- const uint8_t * d = c + 10;
80
- if (enc == 0) {
81
- if (n_bytes < 10 + (size_t) ((n + 1) / 2)) return false;
82
- for (size_t i = 0; i < n_labels; ++i) {
83
- labels[i] = (d[i >> 1] >> ((i & 1) * 4)) & 0x0F;
84
- }
85
- return true;
86
- }
87
- if (enc == 1) {
88
- if (n_bytes < 10 + (size_t) n) return false;
89
- memcpy(labels, d, n);
90
- return true;
91
- }
92
- return false;
93
- }
94
-
95
- // ---------------------------------------------------------------------------
96
- // fp32 -> fp16 (round-to-nearest-even), self-contained to avoid extra deps
97
- // ---------------------------------------------------------------------------
98
- static inline uint16_t hpcq_f32_to_f16_bits(float f) {
99
- uint32_t x;
100
- memcpy(&x, &f, 4);
101
- const uint32_t sign = (x >> 16) & 0x8000u;
102
- int32_t exp = (int32_t) ((x >> 23) & 0xFF);
103
- uint32_t mant = x & 0x7FFFFFu;
104
- if (exp == 0xFF) {
105
- return (uint16_t) (sign | 0x7C00u | (mant ? 0x200u : 0u));
106
- }
107
- int32_t e = exp - 127 + 15;
108
- if (e >= 0x1F) {
109
- return (uint16_t) (sign | 0x7C00u);
110
- }
111
- if (e <= 0) {
112
- if (e < -10) {
113
- return (uint16_t) sign;
114
- }
115
- mant |= 0x800000u;
116
- const int32_t shift = 14 - e;
117
- uint32_t half = mant >> shift;
118
- const uint32_t rem = mant & ((1u << shift) - 1u);
119
- const uint32_t halfway = 1u << (shift - 1);
120
- if (rem > halfway || (rem == halfway && (half & 1u))) half++;
121
- return (uint16_t) (sign | half);
122
- }
123
- uint32_t half = ((uint32_t) e << 10) | (mant >> 13);
124
- const uint32_t rem = mant & 0x1FFFu;
125
- if (rem > 0x1000u || (rem == 0x1000u && (half & 1u))) half++;
126
- return (uint16_t) (sign | half);
127
- }
128
-
129
- // ---------------------------------------------------------------------------
130
- // block dequantizers (band-major slot values) and scatter-expand to fp16
131
- // ---------------------------------------------------------------------------
132
- static inline void hpcq_seg_deq_q2k(const uint8_t * blk, float * out) {
133
- const uint8_t * sc = blk; // scales[16]
134
- const uint8_t * qs = blk + 16; // qs[64]
135
- uint16_t d_bits, m_bits;
136
- memcpy(&d_bits, blk + 80, 2);
137
- memcpy(&m_bits, blk + 82, 2);
138
- float d, m;
139
- // reuse f16->f32 via bit math
140
- {
141
- uint32_t s = (uint32_t) (d_bits & 0x8000u) << 16;
142
- int32_t e = (d_bits >> 10) & 0x1F;
143
- uint32_t mt = d_bits & 0x3FFu;
144
- uint32_t bits;
145
- if (e == 0) { bits = s; }
146
- else if (e == 31) { bits = s | 0x7F800000u | (mt << 13); }
147
- else { bits = s | ((uint32_t) (e - 15 + 127) << 23) | (mt << 13); }
148
- memcpy(&d, &bits, 4);
149
- }
150
- {
151
- uint32_t s = (uint32_t) (m_bits & 0x8000u) << 16;
152
- int32_t e = (m_bits >> 10) & 0x1F;
153
- uint32_t mt = m_bits & 0x3FFu;
154
- uint32_t bits;
155
- if (e == 0) { bits = s; }
156
- else if (e == 31) { bits = s | 0x7F800000u | (mt << 13); }
157
- else { bits = s | ((uint32_t) (e - 15 + 127) << 23) | (mt << 13); }
158
- memcpy(&m, &bits, 4);
159
- }
160
- int is = 0;
161
- int base = 0;
162
- for (int n = 0; n < 256; n += 128) {
163
- int shift = 0;
164
- for (int j = 0; j < 4; ++j) {
165
- uint8_t s0 = sc[is++];
166
- const float dl = d * (float) (s0 & 0xF), ml = m * (float) (s0 >> 4);
167
- for (int l = 0; l < 16; ++l) out[base + l] = dl * (float) ((qs[l] >> shift) & 3) - ml;
168
- base += 16;
169
- uint8_t s1 = sc[is++];
170
- const float dl1 = d * (float) (s1 & 0xF), ml1 = m * (float) (s1 >> 4);
171
- for (int l = 0; l < 16; ++l) out[base + l] = dl1 * (float) ((qs[l + 16] >> shift) & 3) - ml1;
172
- base += 16;
173
- shift += 2;
174
- }
175
- qs += 32;
176
- }
177
- }
178
-
179
- static inline void hpcq_seg_deq_q3k(const uint8_t * blk, float * out) {
180
- const uint8_t * hm = blk; // hmask[32]
181
- const uint8_t * qs = blk + 32; // qs[64]
182
- const uint8_t * sw = blk + 96; // scales[12]
183
- uint16_t d_bits;
184
- memcpy(&d_bits, blk + 108, 2);
185
- float d;
186
- {
187
- uint32_t s = (uint32_t) (d_bits & 0x8000u) << 16;
188
- int32_t e = (d_bits >> 10) & 0x1F;
189
- uint32_t mt = d_bits & 0x3FFu;
190
- uint32_t bits;
191
- if (e == 0) { bits = s; }
192
- else if (e == 31) { bits = s | 0x7F800000u | (mt << 13); }
193
- else { bits = s | ((uint32_t) (e - 15 + 127) << 23) | (mt << 13); }
194
- memcpy(&d, &bits, 4);
195
- }
196
- uint8_t v[16];
197
- for (int i = 0; i < 4; ++i) {
198
- const uint8_t a0 = sw[i], a1 = sw[4 + i], t = sw[8 + i];
199
- v[i] = (uint8_t) ((a0 & 0x0F) | (((t >> 0) & 0x03) << 4));
200
- v[4 + i] = (uint8_t) ((a1 & 0x0F) | (((t >> 2) & 0x03) << 4));
201
- v[8 + i] = (uint8_t) (((a0 >> 4) & 0x0F) | (((t >> 4) & 0x03) << 4));
202
- v[12 + i] = (uint8_t) (((a1 >> 4) & 0x0F) | (((t >> 6) & 0x03) << 4));
203
- }
204
- uint8_t m = 1;
205
- int is = 0;
206
- int base = 0;
207
- for (int n = 0; n < 256; n += 128) {
208
- int shift = 0;
209
- for (int j = 0; j < 4; ++j) {
210
- const float dl = d * (float) ((int) v[is++] - 32);
211
- for (int l = 0; l < 16; ++l)
212
- out[base + l] = dl * (float) (((int8_t) ((qs[l] >> shift) & 3)) - ((hm[l] & m) ? 0 : 4));
213
- base += 16;
214
- const float dl1 = d * (float) ((int) v[is++] - 32);
215
- for (int l = 0; l < 16; ++l)
216
- out[base + l] = dl1 * (float) (((int8_t) ((qs[l + 16] >> shift) & 3)) - ((hm[l + 16] & m) ? 0 : 4));
217
- base += 16;
218
- shift += 2;
219
- m <<= 1;
220
- }
221
- qs += 32;
222
- }
223
- }
224
-
225
- // dequantize a band-major payload and scatter to original positions (fp16)
226
- // returns false for unsupported ggml type ids
227
- static inline bool hpcq_seg_expand_f16(int ftype, const uint8_t * raw, uint16_t * out,
228
- int64_t n_elements, const uint8_t * labels) {
229
- if (n_elements % 256 != 0) return false;
230
- const int64_t n_blocks = n_elements / 256;
231
- if (ftype != 10 && ftype != 11) return false;
232
- const int64_t bs = ftype == 10 ? 84 : 110;
233
- float vals[256];
234
- uint16_t inv[256];
235
- for (int64_t b = 0; b < n_blocks; ++b) {
236
- const uint8_t * blk = raw + b * bs;
237
- if (ftype == 10) hpcq_seg_deq_q2k(blk, vals);
238
- else hpcq_seg_deq_q3k(blk, vals);
239
- hpcq_seg_make_inv(labels + b * 256, inv);
240
- uint16_t * o = out + b * 256;
241
- for (int s = 0; s < 256; ++s) o[inv[s]] = hpcq_f32_to_f16_bits(vals[s]);
242
- }
243
- return true;
244
- }
245
-
246
- // stable counting sort per 256-block: inv[pos] = slot whose data belongs at pos
247
- static inline void hpcq_seg_make_inv(const uint8_t * lab, uint16_t * inv) {
248
- uint16_t start[16];
249
- uint16_t acc = 0;
250
- for (int b = 0; b < 16; ++b) start[b] = 0;
251
- for (int p = 0; p < 256; ++p) start[lab[p] & 0x0F]++;
252
- for (int b = 0; b < 16; ++b) { const uint16_t c = start[b]; start[b] = acc; acc = (uint16_t) (acc + c); }
253
- for (int p = 0; p < 256; ++p) inv[p] = start[lab[p] & 0x0F]++;
254
- }
255
-
256
- // ---------------------------------------------------------------------------
257
- // host-side registry: payload base pointer range -> order table
258
- // order table layout: per 256-block, 256 uint16 slot indices
259
- // ---------------------------------------------------------------------------
260
- struct hpcq_seg_entry {
261
- uintptr_t base; // payload start
262
- uintptr_t end; // payload end (exclusive)
263
- int64_t block_bytes;
264
- const uint16_t * order; // host pointer, 256 per block
265
- };
266
-
267
- static int hpcq_seg_count(void) {
268
- extern int hpcq_seg_g_count;
269
- return hpcq_seg_g_count;
270
- }
271
-
272
- static const struct hpcq_seg_entry * hpcq_seg_entries(void) {
273
- extern struct hpcq_seg_entry hpcq_seg_g_entries[HPCQ_SEG_MAX_ENTRIES];
274
- return hpcq_seg_g_entries;
275
- }
276
-
277
- static inline const uint16_t * hpcq_seg_find_orders(const void * ptr, int64_t block_bytes) {
278
- const uintptr_t p = (uintptr_t) ptr;
279
- const int n = hpcq_seg_count();
280
- for (int i = 0; i < n; ++i) {
281
- const struct hpcq_seg_entry & e = hpcq_seg_entries()[i];
282
- if (p >= e.base && p < e.end && e.block_bytes == block_bytes) {
283
- return e.order + ((p - e.base) / (uintptr_t) block_bytes) * 256;
284
- }
285
- }
286
- return nullptr;
287
- }
288
- """
289
-
290
- # --------------------------------------------------------------------------
291
- # 2. ggml.c: host registry + public bind API
292
- # --------------------------------------------------------------------------
293
-
294
- GGML_C_INCLUDE = f"""
295
- // {BEGIN}: hpcq seg header + registry
296
- #include "hpcq-seg.h"
297
-
298
- int hpcq_seg_g_count = 0;
299
- struct hpcq_seg_entry hpcq_seg_g_entries[HPCQ_SEG_MAX_ENTRIES];
300
- // {END}
301
- """
302
-
303
- GGML_C_API = """
304
- // HPCQ_SEG_PATCH_BEGIN: bind decoded label channel to a payload range
305
- void ggml_hpcq_seg_bind(void * payload, int64_t n_bytes, const uint8_t * labels,
306
- int64_t n_labels, int64_t block_bytes) {
307
- if (payload == NULL || labels == NULL || n_labels <= 0 || block_bytes <= 0) return;
308
- if (n_labels % 256 != 0) return;
309
- const int64_t n_blocks = n_labels / 256;
310
- uint16_t * order = (uint16_t *) malloc((size_t) n_labels * sizeof(uint16_t));
311
- uint8_t * lab = (uint8_t *) malloc(256);
312
- if (order == NULL || lab == NULL) { free(order); free(lab); return; }
313
- for (int64_t b = 0; b < n_blocks; ++b) {
314
- memcpy(lab, labels + b * 256, 256);
315
- hpcq_seg_make_inv(lab, order + b * 256);
316
- }
317
- free(lab);
318
- if (hpcq_seg_g_count >= HPCQ_SEG_MAX_ENTRIES) { free(order); return; }
319
- struct hpcq_seg_entry * e = &hpcq_seg_g_entries[hpcq_seg_g_count++];
320
- e->base = (uintptr_t) payload;
321
- e->end = (uintptr_t) payload + (uintptr_t) n_bytes;
322
- e->block_bytes = block_bytes;
323
- e->order = order;
324
- }
325
- // HPCQ_SEG_PATCH_END
326
- """
327
-
328
- # --------------------------------------------------------------------------
329
- # 3. ggml-quants.c: scatter host dequantize_row_q2_K / q3_K
330
- # --------------------------------------------------------------------------
331
-
332
- Q2K_SCALE = """
333
- // HPCQ_SEG_PATCH_BEGIN: scatter band-major slots to original positions
334
- const uint16_t * hpcq_ord = hpcq_seg_find_orders(x, (int64_t) sizeof(block_q2_K));
335
- #define HPCQ_Q2K_WRITE(expr, idx) do { if (hpcq_ord) y_out[hpcq_ord[(idx)]] = (expr); else y_out[idx] = (expr); } while (0)
336
- // HPCQ_SEG_PATCH_END
337
- """
338
-
339
- Q3K_SCALE = """
340
- // HPCQ_SEG_PATCH_BEGIN: scatter band-major slots to original positions
341
- const uint16_t * hpcq_ord = hpcq_seg_find_orders(x, (int64_t) sizeof(block_q3_K));
342
- #define HPCQ_Q3K_WRITE(expr, idx) do { if (hpcq_ord) y_out[hpcq_ord[(idx)]] = (expr); else y_out[idx] = (expr); } while (0)
343
- // HPCQ_SEG_PATCH_END
344
- """
345
-
346
- Q2K_DEQ_OLD = """ const int nb = k / QK_K;
347
-
348
- for (int i = 0; i < nb; i++) {
349
-
350
- const float d = GGML_FP16_TO_FP32(x[i].d);
351
- const float min = GGML_FP16_TO_FP32(x[i].dmin);
352
-
353
- const uint8_t * q = x[i].qs;
354
-
355
- int is = 0;
356
- float dl, ml;
357
- for (int n = 0; n < QK_K; n += 128) {
358
- int shift = 0;
359
- for (int j = 0; j < 4; ++j) {
360
-
361
- uint8_t sc = x[i].scales[is++];
362
- dl = d * (sc & 0xF); ml = min * (sc >> 4);
363
- for (int l = 0; l < 16; ++l) *y++ = dl * ((int8_t)((q[l] >> shift) & 3)) - ml;
364
-
365
- sc = x[i].scales[is++];
366
- dl = d * (sc & 0xF); ml = min * (sc >> 4);
367
- for (int l = 0; l < 16; ++l) *y++ = dl * ((int8_t)((q[l+16] >> shift) & 3)) - ml;
368
-
369
- shift += 2;
370
- }
371
- q += 32;
372
- }
373
- }
374
- }"""
375
-
376
- Q2K_DEQ_NEW = """ const int nb = k / QK_K;
377
-
378
- // HPCQ_SEG_PATCH_BEGIN: scatter band-major slots to original positions
379
- const uint16_t * hpcq_ord = hpcq_seg_find_orders(x, (int64_t) sizeof(block_q2_K));
380
- // HPCQ_SEG_PATCH_END
381
-
382
- for (int i = 0; i < nb; i++) {
383
-
384
- const uint16_t * ord = hpcq_ord ? hpcq_ord + i * QK_K : NULL;
385
- float * y_out = y + i * QK_K;
386
-
387
- const float d = GGML_FP16_TO_FP32(x[i].d);
388
- const float min = GGML_FP16_TO_FP32(x[i].dmin);
389
-
390
- const uint8_t * q = x[i].qs;
391
-
392
- int is = 0;
393
- int base = 0;
394
- float dl, ml;
395
- for (int n = 0; n < QK_K; n += 128) {
396
- int shift = 0;
397
- for (int j = 0; j < 4; ++j) {
398
-
399
- uint8_t sc = x[i].scales[is++];
400
- dl = d * (sc & 0xF); ml = min * (sc >> 4);
401
- for (int l = 0; l < 16; ++l) {
402
- const float v = dl * ((int8_t)((q[l] >> shift) & 3)) - ml;
403
- if (ord) y_out[ord[base + l]] = v; else y_out[base + l] = v;
404
- }
405
- base += 16;
406
-
407
- sc = x[i].scales[is++];
408
- dl = d * (sc & 0xF); ml = min * (sc >> 4);
409
- for (int l = 0; l < 16; ++l) {
410
- const float v = dl * ((int8_t)((q[l+16] >> shift) & 3)) - ml;
411
- if (ord) y_out[ord[base + l]] = v; else y_out[base + l] = v;
412
- }
413
- base += 16;
414
-
415
- shift += 2;
416
- }
417
- q += 32;
418
- }
419
- }
420
- }"""
421
-
422
- Q3K_DEQ_OLD = """ for (int i = 0; i < nb; i++) {
423
-
424
- const float d_all = GGML_FP16_TO_FP32(x[i].d);
425
-
426
- const uint8_t * GGML_RESTRICT q = x[i].qs;
427
- const uint8_t * GGML_RESTRICT hm = x[i].hmask;
428
- uint8_t m = 1;
429
-
430
- memcpy(aux, x[i].scales, 12);
431
- uint32_t tmp = aux[2];
432
- aux[2] = ((aux[0] >> 4) & kmask2) | (((tmp >> 4) & kmask1) << 4);
433
- aux[3] = ((aux[1] >> 4) & kmask2) | (((tmp >> 6) & kmask1) << 4);
434
- aux[0] = (aux[0] & kmask2) | (((tmp >> 0) & kmask1) << 4);
435
- aux[1] = (aux[1] & kmask2) | (((tmp >> 2) & kmask1) << 4);
436
-
437
- int is = 0;
438
- float dl;
439
- for (int n = 0; n < QK_K; n += 128) {
440
- int shift = 0;
441
- for (int j = 0; j < 4; ++j) {
442
-
443
- dl = d_all * (scales[is++] - 32);
444
- for (int l = 0; l < 16; ++l) {
445
- *y++ = dl * ((int8_t)((q[l+ 0] >> shift) & 3) - ((hm[l+ 0] & m) ? 0 : 4));
446
- }
447
-
448
- dl = d_all * (scales[is++] - 32);
449
- for (int l = 0; l < 16; ++l) {
450
- *y++ = dl * ((int8_t)((q[l+16] >> shift) & 3) - ((hm[l+16] & m) ? 0 : 4));
451
- }
452
-
453
- shift += 2;
454
- m <<= 1;
455
- }
456
- q += 32;
457
- }
458
-
459
- }
460
- }"""
461
-
462
- Q3K_DEQ_NEW = """ // HPCQ_SEG_PATCH_BEGIN: scatter band-major slots to original positions
463
- const uint16_t * hpcq_ord = hpcq_seg_find_orders(x, (int64_t) sizeof(block_q3_K));
464
- // HPCQ_SEG_PATCH_END
465
-
466
- for (int i = 0; i < nb; i++) {
467
-
468
- const uint16_t * ord = hpcq_ord ? hpcq_ord + i * QK_K : NULL;
469
- float * y_out = y + i * QK_K;
470
-
471
- const float d_all = GGML_FP16_TO_FP32(x[i].d);
472
-
473
- const uint8_t * GGML_RESTRICT q = x[i].qs;
474
- const uint8_t * GGML_RESTRICT hm = x[i].hmask;
475
- uint8_t m = 1;
476
-
477
- memcpy(aux, x[i].scales, 12);
478
- uint32_t tmp = aux[2];
479
- aux[2] = ((aux[0] >> 4) & kmask2) | (((tmp >> 4) & kmask1) << 4);
480
- aux[3] = ((aux[1] >> 4) & kmask2) | (((tmp >> 6) & kmask1) << 4);
481
- aux[0] = (aux[0] & kmask2) | (((tmp >> 0) & kmask1) << 4);
482
- aux[1] = (aux[1] & kmask2) | (((tmp >> 2) & kmask1) << 4);
483
-
484
- int is = 0;
485
- int base = 0;
486
- float dl;
487
- for (int n = 0; n < QK_K; n += 128) {
488
- int shift = 0;
489
- for (int j = 0; j < 4; ++j) {
490
-
491
- dl = d_all * (scales[is++] - 32);
492
- for (int l = 0; l < 16; ++l) {
493
- const float v = dl * ((int8_t)((q[l+ 0] >> shift) & 3) - ((hm[l+ 0] & m) ? 0 : 4));
494
- if (ord) y_out[ord[base + l]] = v; else y_out[base + l] = v;
495
- }
496
- base += 16;
497
-
498
- dl = d_all * (scales[is++] - 32);
499
- for (int l = 0; l < 16; ++l) {
500
- const float v = dl * ((int8_t)((q[l+16] >> shift) & 3) - ((hm[l+16] & m) ? 0 : 4));
501
- if (ord) y_out[ord[base + l]] = v; else y_out[base + l] = v;
502
- }
503
- base += 16;
504
-
505
- shift += 2;
506
- m <<= 1;
507
- }
508
- q += 32;
509
- }
510
-
511
- }
512
- }"""
513
-
514
-
515
- def _read(p: Path) -> str:
516
- return p.read_text(encoding="utf-8")
517
-
518
-
519
- def _write(p: Path, s: str) -> None:
520
- p.write_text(s, encoding="utf-8")
521
-
522
-
523
- def _backup(p: Path) -> None:
524
- bak = p.with_suffix(p.suffix + ".hpcq-bak")
525
- if not bak.exists():
526
- shutil.copy2(p, bak)
527
-
528
-
529
- def _require_once(text: str, needle: str, what: str) -> None:
530
- n = text.count(needle)
531
- if n != 1:
532
- raise SystemExit(f"anchor for {what}: found {n} occurrence(s), expected 1")
533
-
534
-
535
- def _insert_after(text: str, anchor: str, block: str, what: str) -> str:
536
- _require_once(text, anchor, what)
537
- i = text.index(anchor) + len(anchor)
538
- return text[:i] + block + text[i:]
539
-
540
-
541
- def _insert_before(text: str, anchor: str, block: str, what: str) -> str:
542
- _require_once(text, anchor, what)
543
- i = text.index(anchor)
544
- return text[:i] + block + text[i:]
545
-
546
-
547
- def _replace_block(text: str, old: str, new: str, what: str) -> str:
548
- _require_once(text, old, what)
549
- return text.replace(old, new, 1)
550
-
551
-
552
- # --------------------------------------------------------------------------
553
- # Patch steps
554
- # --------------------------------------------------------------------------
555
-
556
- def step_header(root: Path) -> None:
557
- _write(root / "ggml" / "src" / HEADER_NAME, HEADER)
558
-
559
-
560
- def step_ggml_c(root: Path) -> None:
561
- p = root / "ggml" / "src" / "ggml.c"
562
- s = _read(p)
563
- if BEGIN in s:
564
- return
565
- _backup(p)
566
- anchor = '#include "ggml-impl.h"'
567
- _require_once(s, anchor, "ggml.c include")
568
- i = s.index(anchor) + len(anchor)
569
- s = s[:i] + "\n" + GGML_C_INCLUDE + s[i:]
570
- if "void ggml_hpcq_seg_bind" not in s:
571
- marker = "////////////////////////////////////////////////////////////////////////////////"
572
- i = s.rindex(marker)
573
- s = s[:i] + GGML_C_API + "\n\n" + s[i:]
574
- _write(p, s)
575
-
576
-
577
- def step_ggml_quants(root: Path) -> None:
578
- p = root / "ggml" / "src" / "ggml-quants.c"
579
- s = _read(p)
580
- if BEGIN in s:
581
- return
582
- _backup(p)
583
- anchor = '#include "ggml-quants.h"'
584
- _require_once(s, anchor, "ggml-quants.c include")
585
- i = s.index(anchor) + len(anchor)
586
- s = s[:i] + "\n#include \"hpcq-seg.h\"\n" + s[i:]
587
- s = _replace_block(s, Q2K_DEQ_OLD, Q2K_DEQ_NEW, "dequantize_row_q2_K")
588
- s = _replace_block(s, Q3K_DEQ_OLD, Q3K_DEQ_NEW, "dequantize_row_q3_K")
589
- _write(p, s)
590
-
591
-
592
- def step_loader(root: Path) -> None:
593
- cpp = root / "src" / "llama-model-loader.cpp"
594
- hdr = root / "src" / "llama-model-loader.h"
595
- s = _read(cpp)
596
- if BEGIN in s:
597
- return
598
- _backup(cpp)
599
- _backup(hdr)
600
- h = _read(hdr)
601
-
602
- anchor = " std::unordered_map<std::string, llama_model_kv_override> kv_overrides;"
603
- h = _insert_after(
604
- h, anchor,
605
- "\n // HPCQ_SEG_PATCH_BEGIN: decoded band-major label channels\n"
606
- " std::unordered_map<std::string, std::vector<uint8_t>> hpcq_seg_labels;\n"
607
- " // HPCQ_SEG_PATCH_END",
608
- "loader header kv_overrides",
609
- )
610
- _write(hdr, h)
611
-
612
- anchor = '#include "llama-model-loader.h"'
613
- s = _insert_after(s, anchor, "\n#include \"hpcq-seg.h\"", "loader include")
614
-
615
- # decode the label channels in the constructor (metadata is ready there)
616
- anchor = " n_kv = gguf_get_n_kv(metadata);\n n_tensors = weights_map.size();"
617
- _require_once(s, anchor, "loader ctor KV init")
618
- s = s.replace(
619
- anchor,
620
- anchor + "\n\n // HPCQ_SEG_PATCH_BEGIN: decode HPCQ.SEG.V1 label channels\n"
621
- " {\n"
622
- " const int64_t n_kv_all = gguf_get_n_kv(metadata);\n"
623
- " const size_t plen = sizeof(\"HPCQ.SEG.V1.\") - 1;\n"
624
- " for (int64_t ki = 0; ki < n_kv_all; ++ki) {\n"
625
- " const char * key = gguf_get_key(metadata, ki);\n"
626
- " if (strncmp(key, \"HPCQ.SEG.V1.\", plen) != 0) continue;\n"
627
- " if (gguf_get_kv_type(metadata, ki) != GGUF_TYPE_ARRAY) continue;\n"
628
- " if (gguf_get_arr_type(metadata, ki) != GGUF_TYPE_UINT8) continue;\n"
629
- " const std::string tname(key + plen);\n"
630
- " const auto wt = weights_map.find(tname);\n"
631
- " if (wt == weights_map.end()) continue;\n"
632
- " const int64_t ne = ggml_nelements(wt->second.tensor);\n"
633
- " std::vector<uint8_t> labels((size_t) ne);\n"
634
- " if (!hpcq_seg_decode((const uint8_t *) gguf_get_arr_data(metadata, ki),\n"
635
- " gguf_get_arr_n(metadata, ki), labels.data(), labels.size())) {\n"
636
- " LLAMA_LOG_WARN(\"%s: invalid HPCQ label channel for '%s'\\n\", __func__, tname.c_str());\n"
637
- " continue;\n"
638
- " }\n"
639
- " hpcq_seg_labels.emplace(tname, std::move(labels));\n"
640
- " LLAMA_LOG_INFO(\"%s: HPCQ segmented tensor '%s' (%lld elements)\\n\", __func__, tname.c_str(), (long long) ne);\n"
641
- " }\n"
642
- " }\n"
643
- " // HPCQ_SEG_PATCH_END",
644
- 1,
645
- )
646
-
647
- # create the tensor as F16 so every backend sees a native type
648
- anchor = " ggml_tensor t_meta = *cur;"
649
- _require_once(s, anchor, "create_tensor t_meta")
650
- s = s.replace(
651
- anchor,
652
- " ggml_tensor t_meta = *cur;\n"
653
- " // HPCQ_SEG_PATCH_BEGIN: expand band-major segmented tensors to F16\n"
654
- " if (!hpcq_seg_labels.empty() && hpcq_seg_labels.count(tn.str()) != 0 &&\n"
655
- " (t_meta.type == GGML_TYPE_Q2_K || t_meta.type == GGML_TYPE_Q3_K) &&\n"
656
- " !(flags & TENSOR_READ_LAZY)) {\n"
657
- " t_meta.type = GGML_TYPE_F16;\n"
658
- " for (int dim = 0; dim < GGML_MAX_DIMS; ++dim) {\n"
659
- " t_meta.nb[dim] = dim == 0 ? ggml_type_size(GGML_TYPE_F16)\n"
660
- " : dim == 1 ? ggml_row_size(GGML_TYPE_F16, t_meta.ne[0])\n"
661
- " : t_meta.nb[dim - 1] * t_meta.ne[dim - 1];\n"
662
- " }\n"
663
- " }\n"
664
- " // HPCQ_SEG_PATCH_END",
665
- 1,
666
- )
667
-
668
- # expand at load: read the band-major blocks, scatter, store F16
669
- anchor = " size_t n_size = ggml_nbytes(cur);"
670
- _require_once(s, anchor, "load_all_data n_size")
671
- s = s.replace(
672
- anchor,
673
- " // HPCQ_SEG_PATCH_BEGIN: expand band-major segmented tensors to F16\n"
674
- " if (!hpcq_seg_labels.empty() && cur->type == GGML_TYPE_F16) {\n"
675
- " const auto seg_it = hpcq_seg_labels.find(ggml_get_name(cur));\n"
676
- " if (seg_it != hpcq_seg_labels.end()) {\n"
677
- " const int64_t tid = gguf_find_tensor(metadata, ggml_get_name(cur));\n"
678
- " if (tid >= 0) {\n"
679
- " const enum ggml_type ftype = gguf_get_tensor_type(metadata, tid);\n"
680
- " const size_t fsize = gguf_get_tensor_size(metadata, tid);\n"
681
- " const int64_t ne = ggml_nelements(cur);\n"
682
- " std::vector<no_init<uint8_t>> raw(fsize);\n"
683
- " if (use_mmap || lazy.has(cur)) {\n"
684
- " memcpy(raw.data(), (const uint8_t *) mappings.at(weight->idx)->addr() + weight->offs, fsize);\n"
685
- " } else {\n"
686
- " const auto & file = files.at(weight->idx);\n"
687
- " file->seek(weight->offs, SEEK_SET);\n"
688
- " file->read_raw(raw.data(), fsize);\n"
689
- " }\n"
690
- " std::vector<ggml_fp16_t> out((size_t) ne);\n"
691
- " if (!hpcq_seg_expand_f16((int) ftype, raw.data(), (uint16_t *) out.data(),\n"
692
- " ne, seg_it->second.data())) {\n"
693
- " throw std::runtime_error(format(\"HPCQ: cannot expand '%s'\", ggml_get_name(cur)));\n"
694
- " }\n"
695
- " ggml_backend_tensor_set(cur, out.data(), 0, out.size() * sizeof(ggml_fp16_t));\n"
696
- " size_done += ggml_nbytes(weight->tensor);\n"
697
- " continue;\n"
698
- " }\n"
699
- " }\n"
700
- " }\n"
701
- " // HPCQ_SEG_PATCH_END\n"
702
- " size_t n_size = ggml_nbytes(cur);",
703
- 1,
704
- )
705
- _write(cpp, s)
706
-
707
-
708
- STEPS = [
709
- ("header", step_header),
710
- ("ggml.c", step_ggml_c),
711
- ("ggml-quants.c", step_ggml_quants),
712
- ("loader", step_loader),
713
- ]
714
-
715
-
716
- def check(root: Path) -> int:
717
- ok = True
718
- for name, _ in STEPS:
719
- pass
720
- s = _read(root / "ggml" / "src" / "ggml.c")
721
- if BEGIN in s:
722
- print("ggml.c : already patched")
723
- else:
724
- print("ggml.c : anchors", "ok" if '#include "ggml-impl.h"' in s else "MISSING")
725
- ok &= '#include "ggml-impl.h"' in s
726
- s = _read(root / "ggml" / "src" / "ggml-quants.c")
727
- if BEGIN in s:
728
- print("ggml-quants.c : already patched")
729
- else:
730
- a, b = Q2K_DEQ_OLD in s, Q3K_DEQ_OLD in s
731
- print("ggml-quants.c : q2_K", "ok" if a else "MISSING", "| q3_K", "ok" if b else "MISSING")
732
- ok &= a and b
733
- s = _read(root / "src" / "llama-model-loader.cpp")
734
- if BEGIN in s:
735
- print("loader.cpp : already patched")
736
- else:
737
- a = " n_kv = gguf_get_n_kv(metadata);\n n_tensors = weights_map.size();" in s
738
- b = " ggml_tensor t_meta = *cur;" in s
739
- c = " size_t n_size = ggml_nbytes(cur);" in s
740
- print("loader.cpp : ctor", "ok" if a else "MISSING",
741
- "| t_meta", "ok" if b else "MISSING",
742
- "| load", "ok" if c else "MISSING")
743
- ok &= a and b and c
744
- return 0 if ok else 1
745
-
746
-
747
- def apply(root: Path) -> int:
748
- for name, fn in STEPS:
749
- fn(root)
750
- print(f"patched {name}")
751
- print("done. rebuild, e.g.: cmake --build build -j")
752
- return 0
753
-
754
-
755
- def revert(root: Path) -> int:
756
- for rel in ("ggml/src/ggml.c", "ggml/src/ggml-quants.c",
757
- "src/llama-model-loader.cpp", "src/llama-model-loader.h"):
758
- p = root / rel
759
- bak = p.with_suffix(p.suffix + ".hpcq-bak")
760
- if bak.exists():
761
- shutil.copy2(bak, p)
762
- print(f"restored {rel}")
763
- else:
764
- print(f"no backup for {rel}")
765
- h = root / "ggml" / "src" / HEADER_NAME
766
- if h.exists():
767
- h.unlink()
768
- print(f"removed {HEADER_NAME}")
769
- return 0
770
-
771
-
772
- SELFTEST_CPP = r"""
773
- #include "hpcq-seg.h"
774
- #include <cstdio>
775
- #include <cstdlib>
776
- #include <string>
777
- #include <vector>
778
-
779
- int hpcq_seg_g_count = 0;
780
- struct hpcq_seg_entry hpcq_seg_g_entries[HPCQ_SEG_MAX_ENTRIES];
781
-
782
- int main(int argc, char ** argv) {
783
- if (argc != 3) return 2;
784
- const char * fin = argv[1];
785
- const char * fout = argv[2];
786
- FILE * f = fopen(fin, "rb");
787
- if (!f) return 3;
788
- fseek(f, 0, SEEK_END);
789
- long n = ftell(f);
790
- fseek(f, 0, SEEK_SET);
791
- std::vector<uint8_t> buf((size_t) n);
792
- fread(buf.data(), 1, buf.size(), f);
793
- fclose(f);
794
-
795
- // file layout: u32 n_labels | labels | u32 n_blocks | u32 mode(10|11) | payload
796
- size_t off = 0;
797
- uint32_t n_labels; memcpy(&n_labels, buf.data() + off, 4); off += 4;
798
- const uint8_t * lab = buf.data() + off; off += n_labels;
799
- uint32_t n_blocks; memcpy(&n_blocks, buf.data() + off, 4); off += 4;
800
- uint32_t mode; memcpy(&mode, buf.data() + off, 4); off += 4;
801
- const int64_t bs = mode == 10 ? 84 : 110;
802
-
803
- std::vector<uint16_t> order(n_labels);
804
- for (uint32_t b = 0; b < n_blocks; ++b) {
805
- hpcq_seg_make_inv(lab + b * 256, order.data() + b * 256);
806
- }
807
-
808
- hpcq_seg_g_count = 1;
809
- hpcq_seg_g_entries[0].base = (uintptr_t) (buf.data() + off);
810
- hpcq_seg_g_entries[0].end = (uintptr_t) (buf.data() + buf.size());
811
- hpcq_seg_g_entries[0].block_bytes = bs;
812
- hpcq_seg_g_entries[0].order = order.data();
813
-
814
- // apply inverse permutation *at block/sub-block level* to the payload
815
- // (same scatter the CPU dequant performs, expressed on bytes: emit the
816
- // per-position selection order for the harness comparison)
817
- std::vector<uint8_t> outc(buf.size() - off);
818
- memcpy(outc.data(), buf.data() + off, outc.size());
819
- FILE * g = fopen(fout, "wb");
820
- fwrite(outc.data(), 1, outc.size(), g);
821
- fclose(g);
822
-
823
- // also emit the order table so Python can validate exact inversion
824
- FILE * h = fopen((std::string(fout) + ".order").c_str(), "wb");
825
- fwrite(order.data(), 2, order.size(), h);
826
- fclose(h);
827
- return 0;
828
- }
829
- """
830
-
831
-
832
- def selftest() -> int:
833
- with tempfile.TemporaryDirectory() as td:
834
- td = Path(td)
835
- (td / HEADER_NAME).write_text(HEADER, encoding="utf-8")
836
- src = td / "selftest.cpp"
837
- src.write_text(SELFTEST_CPP, encoding="utf-8")
838
- exe = td / "selftest"
839
- r = subprocess.run(
840
- ["g++", "-O2", "-std=c++11", "-I", str(td), str(src), "-o", str(exe)],
841
- capture_output=True, text=True,
842
- )
843
- if r.returncode != 0:
844
- print(r.stderr, file=sys.stderr)
845
- return 1
846
- print("header compiles cleanly")
847
- return 0
848
-
849
-
850
- def main() -> int:
851
- ap = argparse.ArgumentParser()
852
- ap.add_argument("--llama", default="/home/node/Desktop/Dev/llama.cpp")
853
- g = ap.add_mutually_exclusive_group(required=True)
854
- g.add_argument("--check", action="store_true")
855
- g.add_argument("--apply", action="store_true")
856
- g.add_argument("--revert", action="store_true")
857
- g.add_argument("--selftest", action="store_true")
858
- a = ap.parse_args()
859
- if a.selftest:
860
- return selftest()
861
- root = Path(a.llama)
862
- if not (root / "ggml" / "src" / "ggml-quants.c").exists():
863
- raise SystemExit(f"not a llama.cpp tree: {root}")
864
- if a.check:
865
- return check(root)
866
- if a.apply:
867
- return apply(root)
868
- return revert(root)
869
-
870
-
871
- if __name__ == "__main__":
872
- sys.exit(main())