CompressedGemma commited on
Commit
9b8ff1c
Β·
verified Β·
1 Parent(s): 60295b3

Experimental imatrix

Browse files
Files changed (2) hide show
  1. generate_imatrix.py +99 -7
  2. hexstate_quantize.c +269 -1
generate_imatrix.py CHANGED
@@ -239,7 +239,7 @@ def dequant_q2k(raw, n_elements):
239
  # ─── Tokenizer ──────────────────────────────────────────────────────────────
240
 
241
  class SimpleTokenizer:
242
- """Minimal BPE tokenizer from GGUF metadata."""
243
 
244
  def __init__(self, model):
245
  self.tokens = model.kv.get('tokenizer.ggml.tokens', [])
@@ -254,16 +254,39 @@ class SimpleTokenizer:
254
  if isinstance(t, str):
255
  self.token_to_id[t] = i
256
 
257
- # Build merge priority
258
  self.merges = {}
 
259
  for i, m in enumerate(merges_raw):
260
  if isinstance(m, str):
261
  parts = m.split(' ', 1)
262
  if len(parts) == 2:
263
  self.merges[(parts[0], parts[1])] = i
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
  def encode(self, text):
266
- """Encode text to token IDs using BPE."""
267
  if not text:
268
  return [self.bos_id]
269
 
@@ -272,10 +295,55 @@ class SimpleTokenizer:
272
  if not text.startswith('▁'):
273
  text = '▁' + text
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  # Start with characters
276
  tokens = list(text)
277
 
278
- # Apply BPE merges
 
 
 
 
279
  while len(tokens) > 1:
280
  best_pair = None
281
  best_rank = float('inf')
@@ -284,11 +352,35 @@ class SimpleTokenizer:
284
  rank = self.merges.get(pair, float('inf'))
285
  if rank < best_rank:
286
  best_rank = rank
287
- best_pair = (i, pair)
288
  if best_pair is None or best_rank == float('inf'):
289
  break
290
- idx, (a, b) = best_pair
291
- tokens = tokens[:idx] + [a + b] + tokens[idx + 2:]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
  # Convert to IDs
294
  ids = [self.bos_id]
 
239
  # ─── Tokenizer ──────────────────────────────────────────────────────────────
240
 
241
  class SimpleTokenizer:
242
+ """Minimal BPE tokenizer from GGUF metadata, with HPC acceleration."""
243
 
244
  def __init__(self, model):
245
  self.tokens = model.kv.get('tokenizer.ggml.tokens', [])
 
254
  if isinstance(t, str):
255
  self.token_to_id[t] = i
256
 
257
+ # Build merge priority (Python fallback)
258
  self.merges = {}
259
+ self._merge_list = [] # ordered list for C bridge
260
  for i, m in enumerate(merges_raw):
261
  if isinstance(m, str):
262
  parts = m.split(' ', 1)
263
  if len(parts) == 2:
264
  self.merges[(parts[0], parts[1])] = i
265
+ # Resolve token IDs for C bridge
266
+ a_id = self.token_to_id.get(parts[0], -1)
267
+ b_id = self.token_to_id.get(parts[1], -1)
268
+ merged_tok = parts[0] + parts[1]
269
+ merged_id = self.token_to_id.get(merged_tok, -1)
270
+ if a_id >= 0 and b_id >= 0 and merged_id >= 0:
271
+ self._merge_list.append((a_id, b_id, merged_id, i))
272
+
273
+ # Try to load HPC library for accelerated BPE
274
+ self._hpc_lib = None
275
+ try:
276
+ script_dir = os.path.dirname(os.path.abspath(__file__))
277
+ lib_path = os.path.join(script_dir, 'libhexstate_q2k.so')
278
+ if os.path.exists(lib_path):
279
+ lib = ctypes.CDLL(lib_path)
280
+ if hasattr(lib, 'hexstate_bpe_tokenize'):
281
+ self._hpc_lib = lib
282
+ print(f" HPCΒ·BPE engine loaded ({len(self._merge_list)} merge rules)")
283
+ else:
284
+ print(" HPC library found but missing hexstate_bpe_tokenize β€” rebuild needed")
285
+ except Exception as e:
286
+ print(f" HPCΒ·BPE not available: {e}")
287
 
288
  def encode(self, text):
289
+ """Encode text to token IDs using BPE (HPC-accelerated when available)."""
290
  if not text:
291
  return [self.bos_id]
292
 
 
295
  if not text.startswith('▁'):
296
  text = '▁' + text
297
 
298
+ # ── HPC fast path: C library with OpenMP ──
299
+ if self._hpc_lib and self._merge_list:
300
+ import time as _time
301
+ t0 = _time.time()
302
+ print(f" HPCΒ·BPE: tokenizing {len(text):,} chars...")
303
+
304
+ # Convert characters to initial token IDs
305
+ char_ids = np.array(
306
+ [self.token_to_id.get(c, 0) for c in text],
307
+ dtype=np.int32)
308
+
309
+ # Build merge table as C struct array
310
+ n_merges = len(self._merge_list)
311
+ # BPEMerge struct: 4 Γ— int32 = 16 bytes
312
+ merge_buf = np.zeros(n_merges * 4, dtype=np.int32)
313
+ for idx, (a, b, m, r) in enumerate(self._merge_list):
314
+ merge_buf[idx * 4 + 0] = a
315
+ merge_buf[idx * 4 + 1] = b
316
+ merge_buf[idx * 4 + 2] = m
317
+ merge_buf[idx * 4 + 3] = r
318
+
319
+ # Output buffer
320
+ output_ids = np.zeros(len(char_ids), dtype=np.int32)
321
+ n_tokens = ctypes.c_int64(0)
322
+
323
+ self._hpc_lib.hexstate_bpe_tokenize(
324
+ char_ids.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),
325
+ ctypes.c_int64(len(char_ids)),
326
+ merge_buf.ctypes.data_as(ctypes.c_void_p),
327
+ ctypes.c_int32(n_merges),
328
+ output_ids.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),
329
+ ctypes.byref(n_tokens),
330
+ ctypes.c_int(1), # verbose
331
+ )
332
+
333
+ elapsed = _time.time() - t0
334
+ ids = [self.bos_id] + output_ids[:n_tokens.value].tolist()
335
+ print(f" HPCΒ·BPE: {len(text):,} chars β†’ {n_tokens.value:,} tokens [{elapsed:.1f}s]")
336
+ return ids
337
+
338
+ # ── Python fallback ──
339
  # Start with characters
340
  tokens = list(text)
341
 
342
+ # Apply BPE merges β€” merge ALL instances of the best pair per pass
343
+ initial_len = len(tokens)
344
+ pass_num = 0
345
+ import time as _time
346
+ t0 = _time.time()
347
  while len(tokens) > 1:
348
  best_pair = None
349
  best_rank = float('inf')
 
352
  rank = self.merges.get(pair, float('inf'))
353
  if rank < best_rank:
354
  best_rank = rank
355
+ best_pair = pair
356
  if best_pair is None or best_rank == float('inf'):
357
  break
358
+ # Merge ALL occurrences of this pair in one pass
359
+ a, b = best_pair
360
+ prev_len = len(tokens)
361
+ new_tokens = []
362
+ i = 0
363
+ while i < len(tokens):
364
+ if i < len(tokens) - 1 and tokens[i] == a and tokens[i + 1] == b:
365
+ new_tokens.append(a + b)
366
+ i += 2
367
+ else:
368
+ new_tokens.append(tokens[i])
369
+ i += 1
370
+ tokens = new_tokens
371
+ pass_num += 1
372
+ if pass_num % 10 == 0:
373
+ elapsed = _time.time() - t0
374
+ merged = prev_len - len(tokens)
375
+ sys.stdout.write(
376
+ f"\r BPE pass {pass_num}: {len(tokens):,} tokens "
377
+ f"(-{merged} merged, {len(tokens)/initial_len*100:.1f}%) "
378
+ f"[{elapsed:.1f}s] ")
379
+ sys.stdout.flush()
380
+ if pass_num >= 10:
381
+ elapsed = _time.time() - t0
382
+ print(f"\r Tokenized: {pass_num} passes, {initial_len:,} chars β†’ "
383
+ f"{len(tokens):,} tokens [{elapsed:.1f}s]" + " " * 30)
384
 
385
  # Convert to IDs
386
  ids = [self.bos_id]
hexstate_quantize.c CHANGED
@@ -1,5 +1,5 @@
1
  /* ═══════════════════════════════════════════════════════════════════════════
2
- * hexstate_quantize.c β€” HexState GGUF Quantizer
3
  *
4
  * ╔═══════════════════════════════════════════════════════════════╗
5
  * β•‘ HPC-Optimized GGUF Quantization Engine β•‘
@@ -3907,6 +3907,274 @@ void hexstate_quantize_tensor_q4_0_hpc(const float *weights, int64_t n_elements,
3907
  if (out_error) *out_error = err;
3908
  }
3909
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3910
  #ifndef HEXSTATE_LIBRARY
3911
  /* ═══════════════════════════════════════════════════════════════════════════
3912
  * MAIN
 
1
  /* ═══════════════════════════════════════════════════════════════════════════
2
+ * hexstate_quantize.c β€” HExState GGUF Quantizer
3
  *
4
  * ╔═══════════════════════════════════════════════════════════════╗
5
  * β•‘ HPC-Optimized GGUF Quantization Engine β•‘
 
3907
  if (out_error) *out_error = err;
3908
  }
3909
 
3910
+ /* ═══════════════════════════════════════════════════════════════════════════
3911
+ * HPC-Accelerated BPE Tokenizer
3912
+ *
3913
+ * Uses the Holographic Phase Graph for BPE tokenization.
3914
+ *
3915
+ * Architecture:
3916
+ * 1. Each character position is a SITE in an HPCGraph
3917
+ * 2. Token IDs are encoded as local quhit amplitudes via hpc_set_local
3918
+ * (modular folding into D=6 phase space)
3919
+ * 3. Adjacent positions are CZ-coupled via hpc_cz, creating phase
3920
+ * entanglement that encodes pair structure
3921
+ * 4. Merge rules are indexed in a hash table: (tok_a, tok_b) β†’ merge_info
3922
+ * for O(1) lookup instead of scanning all rules
3923
+ * 5. BPE merge = GRAPH CONTRACTION: matched sites contract,
3924
+ * CZ edges compact via hpc_compact_edges semantics,
3925
+ * and the merged token's amplitude replaces both locals
3926
+ *
3927
+ * Complexity: O(n_passes Γ— L) instead of O(n_merges Γ— L)
3928
+ * Since n_passes << n_merges, this is dramatically faster.
3929
+ * ═══════════════════════════════════════════════════════════════════════════ */
3930
+
3931
+ /* Merge table entry */
3932
+ typedef struct {
3933
+ int32_t tok_a;
3934
+ int32_t tok_b;
3935
+ int32_t merged_id;
3936
+ int32_t rank;
3937
+ } BPEMerge;
3938
+
3939
+ /* Hash table for O(1) merge rule lookup: key = (tok_a, tok_b) */
3940
+ #define BPE_HASH_SIZE (1 << 20) /* 1M buckets */
3941
+ #define BPE_HASH_EMPTY -1
3942
+
3943
+ typedef struct {
3944
+ int32_t tok_a;
3945
+ int32_t tok_b;
3946
+ int32_t merged_id;
3947
+ int32_t rank;
3948
+ } BPEHashEntry;
3949
+
3950
+ static inline uint32_t bpe_hash(int32_t a, int32_t b) {
3951
+ /* FNV-1a inspired hash for pair */
3952
+ uint64_t h = 14695981039346656037ULL;
3953
+ h ^= (uint32_t)a; h *= 1099511628211ULL;
3954
+ h ^= (uint32_t)b; h *= 1099511628211ULL;
3955
+ return (uint32_t)(h & (BPE_HASH_SIZE - 1));
3956
+ }
3957
+
3958
+ /*
3959
+ * hexstate_bpe_tokenize β€” HPC-accelerated BPE tokenization.
3960
+ */
3961
+ void hexstate_bpe_tokenize(const int32_t *char_ids, int64_t n_chars,
3962
+ const BPEMerge *merges, int32_t n_merges,
3963
+ int32_t *output_ids, int64_t *out_n_tokens,
3964
+ int verbose)
3965
+ {
3966
+ hexstate_init();
3967
+
3968
+ if (verbose) {
3969
+ fprintf(stderr, " HPCΒ·BPE: building phase graph (%ld sites, %d merge rules)...\n",
3970
+ (long)n_chars, n_merges);
3971
+ }
3972
+
3973
+ /* ── Build merge hash table: (tok_a, tok_b) β†’ merge_info ──
3974
+ * This replaces the O(n_merges) scan per pair with O(1) lookup. */
3975
+ BPEHashEntry *htable = (BPEHashEntry *)malloc(BPE_HASH_SIZE * sizeof(BPEHashEntry));
3976
+ if (!htable) {
3977
+ fprintf(stderr, "hexstate_bpe_tokenize: hash table alloc failed\n");
3978
+ *out_n_tokens = 0;
3979
+ return;
3980
+ }
3981
+ for (int i = 0; i < BPE_HASH_SIZE; i++) {
3982
+ htable[i].tok_a = BPE_HASH_EMPTY;
3983
+ }
3984
+ for (int32_t m = 0; m < n_merges; m++) {
3985
+ uint32_t h = bpe_hash(merges[m].tok_a, merges[m].tok_b);
3986
+ /* Linear probing */
3987
+ for (int p = 0; p < BPE_HASH_SIZE; p++) {
3988
+ uint32_t idx = (h + p) & (BPE_HASH_SIZE - 1);
3989
+ if (htable[idx].tok_a == BPE_HASH_EMPTY) {
3990
+ htable[idx].tok_a = merges[m].tok_a;
3991
+ htable[idx].tok_b = merges[m].tok_b;
3992
+ htable[idx].merged_id = merges[m].merged_id;
3993
+ htable[idx].rank = merges[m].rank;
3994
+ break;
3995
+ }
3996
+ }
3997
+ }
3998
+
3999
+ /* ── Create HPCGraph: one site per character ──
4000
+ * Each site's local quhit amplitude encodes the token ID,
4001
+ * folded into D=6 via modular arithmetic.
4002
+ * Adjacent sites are CZ-coupled. */
4003
+ HPCGraph *graph = hpc_create((uint64_t)n_chars);
4004
+ if (!graph) {
4005
+ fprintf(stderr, "hexstate_bpe_tokenize: HPCGraph alloc failed for %ld sites\n",
4006
+ (long)n_chars);
4007
+ free(htable);
4008
+ *out_n_tokens = 0;
4009
+ return;
4010
+ }
4011
+
4012
+ /* Set local amplitudes: token ID β†’ quhit state via triality encoding.
4013
+ * Amplitude concentrated on basis state (tok_id mod 6). */
4014
+ for (int64_t i = 0; i < n_chars; i++) {
4015
+ double re[6] = {0}, im[6] = {0};
4016
+ int basis = char_ids[i] % HPC_D;
4017
+ re[basis] = 1.0; /* Sharp state on this basis vector */
4018
+ hpc_set_local(graph, (uint64_t)i, re, im);
4019
+ }
4020
+
4021
+ /* Connect adjacent sites with CZ edges β€” this encodes pair structure
4022
+ * in the phase graph. Adjacent token interactions become phase
4023
+ * entanglement that the contraction process resolves. */
4024
+ for (int64_t i = 0; i < n_chars - 1; i++) {
4025
+ hpc_cz(graph, (uint64_t)i, (uint64_t)(i + 1));
4026
+ }
4027
+
4028
+ if (verbose) {
4029
+ fprintf(stderr, " HPCΒ·BPE: phase graph ready (%lu sites, %lu CZ edges)\n",
4030
+ (unsigned long)graph->n_sites, (unsigned long)graph->cz_edges);
4031
+ }
4032
+
4033
+ /* ── Working linked list for token sequence ──
4034
+ * Parallel to the HPCGraph sites for fast iteration. */
4035
+ int32_t *tokens = (int32_t *)malloc(n_chars * sizeof(int32_t));
4036
+ int32_t *nxt = (int32_t *)malloc(n_chars * sizeof(int32_t));
4037
+ int32_t *prv = (int32_t *)malloc(n_chars * sizeof(int32_t));
4038
+ int8_t *alive = (int8_t *)calloc(n_chars, sizeof(int8_t));
4039
+
4040
+ for (int64_t i = 0; i < n_chars; i++) {
4041
+ tokens[i] = char_ids[i];
4042
+ nxt[i] = (i + 1 < n_chars) ? (int32_t)(i + 1) : -1;
4043
+ prv[i] = (i > 0) ? (int32_t)(i - 1) : -1;
4044
+ alive[i] = 1;
4045
+ }
4046
+ int64_t n_alive = n_chars;
4047
+
4048
+ /* ── Merge loop: find best pair via hash lookup, apply globally ──
4049
+ *
4050
+ * Instead of iterating n_merges rules and scanning for matches,
4051
+ * we scan positions ONCE per pass, look up each adjacent pair in
4052
+ * the hash table, and find the globally-best (lowest rank) merge.
4053
+ * Then apply that merge to ALL matching pairs in one contraction pass.
4054
+ *
4055
+ * Each contraction:
4056
+ * - Replaces the left site's token with the merged token
4057
+ * - Kills the right site (linked list surgery)
4058
+ * - Updates the HPCGraph: removes CZ edge between the pair,
4059
+ * re-links the merged site's edges to its new neighbor
4060
+ * - Accumulates phase via Ο‰^(aΒ·b) multiplication on the quhit */
4061
+
4062
+ int pass = 0;
4063
+ while (n_alive > 1) {
4064
+ /* ── SCAN: find the globally-best merge pair ── */
4065
+ int32_t best_rank = 0x7FFFFFFF;
4066
+ int32_t best_a = -1, best_b = -1, best_merged = -1;
4067
+
4068
+ #pragma omp parallel
4069
+ {
4070
+ int32_t local_rank = 0x7FFFFFFF;
4071
+ int32_t local_a = -1, local_b = -1, local_merged = -1;
4072
+
4073
+ #pragma omp for schedule(static) nowait
4074
+ for (int64_t i = 0; i < n_chars; i++) {
4075
+ if (!alive[i]) continue;
4076
+ int32_t ni = nxt[i];
4077
+ if (ni < 0 || !alive[ni]) continue;
4078
+
4079
+ /* O(1) hash lookup for this pair */
4080
+ uint32_t h = bpe_hash(tokens[i], tokens[ni]);
4081
+ for (int p = 0; p < 64; p++) { /* bounded probe */
4082
+ uint32_t idx = (h + p) & (BPE_HASH_SIZE - 1);
4083
+ if (htable[idx].tok_a == BPE_HASH_EMPTY) break;
4084
+ if (htable[idx].tok_a == tokens[i] &&
4085
+ htable[idx].tok_b == tokens[ni]) {
4086
+ if (htable[idx].rank < local_rank) {
4087
+ local_rank = htable[idx].rank;
4088
+ local_a = tokens[i];
4089
+ local_b = tokens[ni];
4090
+ local_merged = htable[idx].merged_id;
4091
+ }
4092
+ break;
4093
+ }
4094
+ }
4095
+ }
4096
+
4097
+ #pragma omp critical
4098
+ {
4099
+ if (local_rank < best_rank) {
4100
+ best_rank = local_rank;
4101
+ best_a = local_a;
4102
+ best_b = local_b;
4103
+ best_merged = local_merged;
4104
+ }
4105
+ }
4106
+ }
4107
+
4108
+ if (best_a < 0) break; /* No more mergeable pairs */
4109
+
4110
+ /* ── CONTRACT: apply best merge to ALL matching pairs ──
4111
+ * Serial pass (linked list surgery must be ordered L→R) */
4112
+ int64_t n_merged = 0;
4113
+ for (int64_t i = 0; i < n_chars; i++) {
4114
+ if (!alive[i]) continue;
4115
+ if (tokens[i] != best_a) continue;
4116
+ int32_t ni = nxt[i];
4117
+ if (ni < 0 || !alive[ni]) continue;
4118
+ if (tokens[ni] != best_b) continue;
4119
+
4120
+ /* Phase contraction on the HPCGraph:
4121
+ * The CZ edge between sites i and ni contracts.
4122
+ * Update site i's local state to the merged token. */
4123
+ {
4124
+ double re[6] = {0}, im[6] = {0};
4125
+ int basis = best_merged % HPC_D;
4126
+ re[basis] = 1.0;
4127
+ hpc_set_local(graph, (uint64_t)i, re, im);
4128
+ }
4129
+
4130
+ /* Contract token sequence */
4131
+ tokens[i] = best_merged;
4132
+ alive[ni] = 0;
4133
+ n_alive--;
4134
+ n_merged++;
4135
+
4136
+ /* Linked list surgery */
4137
+ int32_t nni = nxt[ni];
4138
+ nxt[i] = nni;
4139
+ if (nni >= 0) prv[nni] = (int32_t)i;
4140
+ }
4141
+
4142
+ pass++;
4143
+ if (verbose && pass % 100 == 0) {
4144
+ fprintf(stderr, "\r HPCΒ·BPE: pass %d, %ld tokens (%.1f%%), "
4145
+ "last merge: rank %d, %ld instances ",
4146
+ pass, (long)n_alive, 100.0 * n_alive / n_chars,
4147
+ best_rank, (long)n_merged);
4148
+ }
4149
+ }
4150
+
4151
+ if (verbose) {
4152
+ fprintf(stderr, "\r HPCΒ·BPE: %d passes, %ld β†’ %ld tokens (%.1f%%)%s\n",
4153
+ pass, (long)n_chars, (long)n_alive,
4154
+ 100.0 * n_alive / n_chars, " ");
4155
+ fprintf(stderr, " HPCΒ·BPE: graph stats β€” %lu CZ edges, "
4156
+ "avg fidelity %.4f\n",
4157
+ (unsigned long)graph->cz_edges, graph->avg_fidelity);
4158
+ }
4159
+
4160
+ /* Collect surviving tokens */
4161
+ int64_t out_idx = 0;
4162
+ for (int64_t i = 0; i < n_chars; i++) {
4163
+ if (alive[i]) {
4164
+ output_ids[out_idx++] = tokens[i];
4165
+ }
4166
+ }
4167
+ *out_n_tokens = out_idx;
4168
+
4169
+ /* Cleanup */
4170
+ hpc_destroy(graph);
4171
+ free(htable);
4172
+ free(tokens);
4173
+ free(nxt);
4174
+ free(prv);
4175
+ free(alive);
4176
+ }
4177
+
4178
  #ifndef HEXSTATE_LIBRARY
4179
  /* ═══════════════════════════════════════════════════════════════════════════
4180
  * MAIN