Upload q4_0.py
Browse files
q4_0.py
CHANGED
|
@@ -27,6 +27,7 @@ per 18-byte block = 4.5 bpw):
|
|
| 27 |
|
| 28 |
from __future__ import annotations
|
| 29 |
|
|
|
|
| 30 |
from math import ceil
|
| 31 |
import numpy as np
|
| 32 |
|
|
@@ -38,7 +39,7 @@ except ImportError: # pragma: no cover
|
|
| 38 |
from .anneal import thermal_refine_q4_0, thermal_spectral_lams
|
| 39 |
from .config import HPCConfig
|
| 40 |
from .cuda_backend import cuda_is_available
|
| 41 |
-
from .factored import
|
| 42 |
from .fp16 import from_fp16_bits, nearest_int, to_fp16_bits
|
| 43 |
from .sieve import sieve_measure_chain, subblock_chain_edges
|
| 44 |
from .spectral import pin_dc_codes_uniform, pin_dc_codes_uniform_cuda
|
|
@@ -50,6 +51,16 @@ Q4_N_CAND = 24
|
|
| 50 |
Q4_N_STATES = 6
|
| 51 |
Q4_N_LEVELS = 16
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
def dequantize_q4_0_bytes(raw: bytes | np.ndarray, n_blocks: int) -> np.ndarray:
|
| 55 |
blocks = np.frombuffer(raw, dtype=np.uint8).reshape(n_blocks, Q4_0_BLOCK_BYTES)
|
|
@@ -354,6 +365,9 @@ def _quantize_q4_0_hpc_cuda(
|
|
| 354 |
|
| 355 |
# 3. 6-State Sieve + 6-State Viterbi DP:
|
| 356 |
best_cand_np = _q4_sieve_and_viterbi(cand_err_t.cpu().numpy(), cfg)
|
|
|
|
|
|
|
|
|
|
| 357 |
best_cand_t = torch.from_numpy(best_cand_np).to(dev)
|
| 358 |
rows = torch.arange(B, device=dev)
|
| 359 |
d_sel = cand_d[rows, best_cand_t]
|
|
@@ -374,6 +388,7 @@ def _quantize_q4_0_hpc_cuda(
|
|
| 374 |
e_u = X[:, None, :] - all_d[:, :, None] * (q_u.to(torch.float32) - 8.0)
|
| 375 |
sse_u = torch.sum(W[:, None, :] * e_u * e_u, dim=2)
|
| 376 |
pick_u = torch.argmin(sse_u, dim=1)
|
|
|
|
| 377 |
best_d16 = all_b[rows, pick_u]
|
| 378 |
best_d = all_d[rows, pick_u]
|
| 379 |
best_q = q_u[rows, pick_u].to(torch.int64)
|
|
@@ -565,9 +580,14 @@ def quantize_tensor_q4_0(
|
|
| 565 |
weights: np.ndarray,
|
| 566 |
importance: np.ndarray | None = None,
|
| 567 |
cfg: HPCConfig | None = None,
|
| 568 |
-
chunk_blocks: int =
|
| 569 |
) -> tuple[bytes, int, float]:
|
| 570 |
-
"""Quantize a tensor to GGML Q4_0 using the full HPC V2 pipeline.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
cfg = cfg or HPCConfig()
|
| 572 |
x = np.asarray(weights, dtype=np.float32).ravel()
|
| 573 |
if x.size == 0 or x.size % QK4_0 != 0:
|
|
@@ -583,10 +603,19 @@ def quantize_tensor_q4_0(
|
|
| 583 |
else:
|
| 584 |
W_raw = None
|
| 585 |
|
| 586 |
-
|
|
|
|
| 587 |
cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
|
| 588 |
)
|
| 589 |
dev = torch.device("cuda" if cfg.device == "auto" else cfg.device) if use_cuda else None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 590 |
|
| 591 |
chunks: list[bytes] = []
|
| 592 |
total_sse = 0.0
|
|
|
|
| 27 |
|
| 28 |
from __future__ import annotations
|
| 29 |
|
| 30 |
+
import logging
|
| 31 |
from math import ceil
|
| 32 |
import numpy as np
|
| 33 |
|
|
|
|
| 39 |
from .anneal import thermal_refine_q4_0, thermal_spectral_lams
|
| 40 |
from .config import HPCConfig
|
| 41 |
from .cuda_backend import cuda_is_available
|
| 42 |
+
from .factored import MULTS_D
|
| 43 |
from .fp16 import from_fp16_bits, nearest_int, to_fp16_bits
|
| 44 |
from .sieve import sieve_measure_chain, subblock_chain_edges
|
| 45 |
from .spectral import pin_dc_codes_uniform, pin_dc_codes_uniform_cuda
|
|
|
|
| 51 |
Q4_N_STATES = 6
|
| 52 |
Q4_N_LEVELS = 16
|
| 53 |
|
| 54 |
+
_log = logging.getLogger(__name__)
|
| 55 |
+
|
| 56 |
+
# Chunk sizes (in 32-weight blocks). The CUDA default keeps the historical
|
| 57 |
+
# reference chunk (131072 blocks * 32 weights = 4,194,304 weights per chunk);
|
| 58 |
+
# the CPU default is scaled back so the vectorized numpy temporaries
|
| 59 |
+
# ((B, 24, 32) candidate-error fields) stay cache-resident instead of
|
| 60 |
+
# allocating multi-hundred-MB arrays per chunk.
|
| 61 |
+
Q4_0_CHUNK_BLOCKS_CUDA = 131072
|
| 62 |
+
Q4_0_CHUNK_BLOCKS_CPU = 8192
|
| 63 |
+
|
| 64 |
|
| 65 |
def dequantize_q4_0_bytes(raw: bytes | np.ndarray, n_blocks: int) -> np.ndarray:
|
| 66 |
blocks = np.frombuffer(raw, dtype=np.uint8).reshape(n_blocks, Q4_0_BLOCK_BYTES)
|
|
|
|
| 365 |
|
| 366 |
# 3. 6-State Sieve + 6-State Viterbi DP:
|
| 367 |
best_cand_np = _q4_sieve_and_viterbi(cand_err_t.cpu().numpy(), cfg)
|
| 368 |
+
del cand_err_t, e_c, q_c, qi_c, sh_c, sse_c
|
| 369 |
+
if cfg.use_spectral and (lam_dc > 0.0 or lam_vw > 0.0):
|
| 370 |
+
del v_c, dc_c
|
| 371 |
best_cand_t = torch.from_numpy(best_cand_np).to(dev)
|
| 372 |
rows = torch.arange(B, device=dev)
|
| 373 |
d_sel = cand_d[rows, best_cand_t]
|
|
|
|
| 388 |
e_u = X[:, None, :] - all_d[:, :, None] * (q_u.to(torch.float32) - 8.0)
|
| 389 |
sse_u = torch.sum(W[:, None, :] * e_u * e_u, dim=2)
|
| 390 |
pick_u = torch.argmin(sse_u, dim=1)
|
| 391 |
+
del e_u, q_u, qi_u, sh_u, sse_u
|
| 392 |
best_d16 = all_b[rows, pick_u]
|
| 393 |
best_d = all_d[rows, pick_u]
|
| 394 |
best_q = q_u[rows, pick_u].to(torch.int64)
|
|
|
|
| 580 |
weights: np.ndarray,
|
| 581 |
importance: np.ndarray | None = None,
|
| 582 |
cfg: HPCConfig | None = None,
|
| 583 |
+
chunk_blocks: int | None = None,
|
| 584 |
) -> tuple[bytes, int, float]:
|
| 585 |
+
"""Quantize a tensor to GGML Q4_0 using the full HPC V2 pipeline.
|
| 586 |
+
|
| 587 |
+
``chunk_blocks`` (32-weight blocks per chunk) defaults to
|
| 588 |
+
``Q4_0_CHUNK_BLOCKS_CUDA`` on the GPU path and the cache-resident
|
| 589 |
+
``Q4_0_CHUNK_BLOCKS_CPU`` on the CPU path.
|
| 590 |
+
"""
|
| 591 |
cfg = cfg or HPCConfig()
|
| 592 |
x = np.asarray(weights, dtype=np.float32).ravel()
|
| 593 |
if x.size == 0 or x.size % QK4_0 != 0:
|
|
|
|
| 603 |
else:
|
| 604 |
W_raw = None
|
| 605 |
|
| 606 |
+
cuda_ok = cfg.device != "cpu" and cuda_is_available()
|
| 607 |
+
use_cuda = cuda_ok and (
|
| 608 |
cfg.device.startswith("cuda") or (cfg.device == "auto" and n_blocks >= 64)
|
| 609 |
)
|
| 610 |
dev = torch.device("cuda" if cfg.device == "auto" else cfg.device) if use_cuda else None
|
| 611 |
+
if chunk_blocks is None:
|
| 612 |
+
chunk_blocks = Q4_0_CHUNK_BLOCKS_CUDA if use_cuda else Q4_0_CHUNK_BLOCKS_CPU
|
| 613 |
+
chunk_blocks = max(1, int(chunk_blocks))
|
| 614 |
+
_log.info(
|
| 615 |
+
"Q4_0 routing: cfg.device=%r cuda_is_available=%s n_blocks=%d -> %s (chunk_blocks=%d)",
|
| 616 |
+
cfg.device, cuda_ok if cfg.device != "cpu" else "n/a", n_blocks,
|
| 617 |
+
f"CUDA[{dev}]" if use_cuda else "CPU", chunk_blocks,
|
| 618 |
+
)
|
| 619 |
|
| 620 |
chunks: list[bytes] = []
|
| 621 |
total_sse = 0.0
|