CompressedGemma commited on
Commit
0d897d3
·
verified ·
1 Parent(s): 2a7a6b0

Upload segmentation.py

Browse files
Files changed (1) hide show
  1. segmentation.py +41 -10
segmentation.py CHANGED
@@ -156,10 +156,15 @@ def label_channel_bytes(n: int, k: int, table_size: int = SEG_TABLE_SIZE) -> int
156
 
157
 
158
  def pack_label_channel(labels: np.ndarray, k: int, table_size: int = SEG_TABLE_SIZE) -> bytes:
159
- flat = np.ascontiguousarray(labels, dtype=np.int64).ravel()
160
- n = int(flat.size)
161
  k = int(k)
162
  table_size = int(table_size)
 
 
 
 
 
 
 
163
  if k <= 16:
164
  if flat.size and int(flat.max()) > 15:
165
  raise ValueError(f"label {int(flat.max())} does not fit nibble packing (k={k})")
@@ -167,7 +172,7 @@ def pack_label_channel(labels: np.ndarray, k: int, table_size: int = SEG_TABLE_S
167
  enc = 2 if table_size <= 256 else 3
168
  idx_dt = np.uint8 if enc == 2 else np.dtype("<u2")
169
  n_blocks = n // 256
170
- rows = flat.reshape(n_blocks, 256).astype(np.uint8)
171
  lo = rows[:, 0::2]
172
  hi = rows[:, 1::2]
173
  packed_rows = (lo | (hi << 4)).astype(np.uint8) # (n_blocks, 128)
@@ -193,9 +198,9 @@ def pack_label_channel(labels: np.ndarray, k: int, table_size: int = SEG_TABLE_S
193
  data = _pack_nibbles_1d(flat)
194
  else:
195
  enc = 1
196
- if flat.size and (int(flat.max()) > 255 or int(flat.min()) < 0):
197
  raise ValueError("labels must be in [0, 255] for 8-bit packing")
198
- data = flat.astype(np.uint8).tobytes()
199
  return SEG_MAGIC + bytes([k, enc]) + _struct.pack("<I", n) + data
200
 
201
 
@@ -260,6 +265,10 @@ def _segment_stage_dense(
260
  return order, labels, rounds
261
 
262
 
 
 
 
 
263
  def segment_stage(
264
  X: np.ndarray,
265
  W: np.ndarray | None,
@@ -296,14 +305,21 @@ def segment_stage(
296
  col_abs = np.mean(np.abs(X_sample), axis=0)
297
  table_labels[2] = _order_to_canonical_labels(np.argsort(col_abs, kind="stable"), k).astype(np.uint8)
298
 
299
- # Entries 3..M-1: prototype blocks refined with the proxy fixed-point loop
300
- n_proto = M - 3
301
- proto_idx = np.linspace(0, n_blocks - 1, n_proto, dtype=np.int64)
 
 
302
  Xp = Xf[proto_idx].astype(np.float64)
303
  Wp = None if W is None else np.asarray(W[proto_idx], dtype=np.float64)
304
  ord_p, _, rounds = _segment_stage_dense(Xp, Wp, cfg, proxy, k)
305
- for i in range(n_proto):
306
  table_labels[3 + i] = _order_to_canonical_labels(ord_p[i], k).astype(np.uint8)
 
 
 
 
 
307
 
308
  table_orders = make_order(table_labels) # (M, 256) int64
309
 
@@ -392,7 +408,22 @@ def segment_stage(
392
  best_local = np.argmin(sse, axis=1)
393
  best_m[s:e] = top_idx[np.arange(e - s), best_local]
394
 
395
- return table_orders[best_m], table_labels[best_m], rounds
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
 
397
 
398
  def q2k_proxy_cfg(clamp_val: float, cfg: HPCConfig):
 
156
 
157
 
158
  def pack_label_channel(labels: np.ndarray, k: int, table_size: int = SEG_TABLE_SIZE) -> bytes:
 
 
159
  k = int(k)
160
  table_size = int(table_size)
161
+ # Fast path when segment_stage attached pre-packed LUT data
162
+ lut_cache = getattr(labels, "_hpcq_lut_bytes", None)
163
+ if lut_cache is not None and lut_cache[0] == (k, table_size):
164
+ return lut_cache[1]
165
+
166
+ flat = np.ascontiguousarray(labels, dtype=np.uint8).ravel()
167
+ n = int(flat.size)
168
  if k <= 16:
169
  if flat.size and int(flat.max()) > 15:
170
  raise ValueError(f"label {int(flat.max())} does not fit nibble packing (k={k})")
 
172
  enc = 2 if table_size <= 256 else 3
173
  idx_dt = np.uint8 if enc == 2 else np.dtype("<u2")
174
  n_blocks = n // 256
175
+ rows = flat.reshape(n_blocks, 256)
176
  lo = rows[:, 0::2]
177
  hi = rows[:, 1::2]
178
  packed_rows = (lo | (hi << 4)).astype(np.uint8) # (n_blocks, 128)
 
198
  data = _pack_nibbles_1d(flat)
199
  else:
200
  enc = 1
201
+ if flat.size and (int(labels.max()) > 255 or int(labels.min()) < 0):
202
  raise ValueError("labels must be in [0, 255] for 8-bit packing")
203
+ data = flat.tobytes()
204
  return SEG_MAGIC + bytes([k, enc]) + _struct.pack("<I", n) + data
205
 
206
 
 
265
  return order, labels, rounds
266
 
267
 
268
+ class _LUTLabels(np.ndarray):
269
+ _hpcq_lut_bytes: tuple[tuple[int, int], bytes] | None = None
270
+
271
+
272
  def segment_stage(
273
  X: np.ndarray,
274
  W: np.ndarray | None,
 
305
  col_abs = np.mean(np.abs(X_sample), axis=0)
306
  table_labels[2] = _order_to_canonical_labels(np.argsort(col_abs, kind="stable"), k).astype(np.uint8)
307
 
308
+ # Entries 3..M-1: up to 253 prototype blocks refined with the proxy loop,
309
+ # plus fast direct band_labels prototypes when M > 256
310
+ n_need = M - 3
311
+ n_dense = min(n_need, 253)
312
+ proto_idx = np.linspace(0, n_blocks - 1, n_dense, dtype=np.int64)
313
  Xp = Xf[proto_idx].astype(np.float64)
314
  Wp = None if W is None else np.asarray(W[proto_idx], dtype=np.float64)
315
  ord_p, _, rounds = _segment_stage_dense(Xp, Wp, cfg, proxy, k)
316
+ for i in range(n_dense):
317
  table_labels[3 + i] = _order_to_canonical_labels(ord_p[i], k).astype(np.uint8)
318
+ if n_need > n_dense:
319
+ extra_idx = np.linspace(1, n_blocks - 2, n_need - n_dense, dtype=np.int64)
320
+ ord_e = make_order(band_labels(Xf[extra_idx].astype(np.float64), k))
321
+ for i in range(n_need - n_dense):
322
+ table_labels[3 + n_dense + i] = _order_to_canonical_labels(ord_e[i], k).astype(np.uint8)
323
 
324
  table_orders = make_order(table_labels) # (M, 256) int64
325
 
 
408
  best_local = np.argmin(sse, axis=1)
409
  best_m[s:e] = top_idx[np.arange(e - s), best_local]
410
 
411
+ out_labels = table_labels[best_m].view(_LUTLabels)
412
+ enc = 2 if M <= 256 else 3
413
+ idx_dt = np.uint8 if enc == 2 else np.dtype("<u2")
414
+ lo = table_labels[:, 0::2]
415
+ hi = table_labels[:, 1::2]
416
+ table_nib = (lo | (hi << 4)).astype(np.uint8)
417
+ raw_lut = (
418
+ SEG_MAGIC
419
+ + bytes([k, enc])
420
+ + _struct.pack("<I", n_blocks * 256)
421
+ + _struct.pack("<H", M)
422
+ + table_nib.tobytes()
423
+ + best_m.astype(idx_dt).tobytes()
424
+ )
425
+ out_labels._hpcq_lut_bytes = ((k, M), raw_lut)
426
+ return table_orders[best_m], out_labels, rounds
427
 
428
 
429
  def q2k_proxy_cfg(clamp_val: float, cfg: HPCConfig):