quantbench-engine 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. quantbench_engine-0.1.0/.github/workflows/ci.yml +35 -0
  2. quantbench_engine-0.1.0/.github/workflows/release.yml +43 -0
  3. quantbench_engine-0.1.0/.gitignore +52 -0
  4. quantbench_engine-0.1.0/CONTRIBUTING.md +146 -0
  5. quantbench_engine-0.1.0/DEVLOG.md +72 -0
  6. quantbench_engine-0.1.0/GUIDE.md +193 -0
  7. quantbench_engine-0.1.0/LICENSE +190 -0
  8. quantbench_engine-0.1.0/PKG-INFO +276 -0
  9. quantbench_engine-0.1.0/README.md +248 -0
  10. quantbench_engine-0.1.0/examples/01_quant_linear_inference.py +124 -0
  11. quantbench_engine-0.1.0/examples/02_advanced_calibration.py +111 -0
  12. quantbench_engine-0.1.0/examples/03_servebench_roofline_eval.py +140 -0
  13. quantbench_engine-0.1.0/pyproject.toml +78 -0
  14. quantbench_engine-0.1.0/src/quantbench/__init__.py +76 -0
  15. quantbench_engine-0.1.0/src/quantbench/bench/__init__.py +22 -0
  16. quantbench_engine-0.1.0/src/quantbench/bench/pareto.py +182 -0
  17. quantbench_engine-0.1.0/src/quantbench/cli.py +301 -0
  18. quantbench_engine-0.1.0/src/quantbench/eval/__init__.py +27 -0
  19. quantbench_engine-0.1.0/src/quantbench/eval/perplexity.py +143 -0
  20. quantbench_engine-0.1.0/src/quantbench/eval/sqnr.py +66 -0
  21. quantbench_engine-0.1.0/src/quantbench/nn/__init__.py +9 -0
  22. quantbench_engine-0.1.0/src/quantbench/nn/model_convert.py +109 -0
  23. quantbench_engine-0.1.0/src/quantbench/nn/quant_linear.py +296 -0
  24. quantbench_engine-0.1.0/src/quantbench/quant/__init__.py +58 -0
  25. quantbench_engine-0.1.0/src/quantbench/quant/affine.py +188 -0
  26. quantbench_engine-0.1.0/src/quantbench/quant/algorithms/__init__.py +41 -0
  27. quantbench_engine-0.1.0/src/quantbench/quant/algorithms/awq.py +184 -0
  28. quantbench_engine-0.1.0/src/quantbench/quant/algorithms/gptq.py +181 -0
  29. quantbench_engine-0.1.0/src/quantbench/quant/algorithms/smoothquant.py +132 -0
  30. quantbench_engine-0.1.0/src/quantbench/quant/blockwise.py +115 -0
  31. quantbench_engine-0.1.0/src/quantbench/quant/fp8.py +166 -0
  32. quantbench_engine-0.1.0/src/quantbench/quant/packing/__init__.py +27 -0
  33. quantbench_engine-0.1.0/src/quantbench/quant/packing/int4_pack.py +169 -0
  34. quantbench_engine-0.1.0/src/quantbench/quant/packing/sparse_pack.py +170 -0
  35. quantbench_engine-0.1.0/src/quantbench/quant/packing/ternary_pack.py +193 -0
  36. quantbench_engine-0.1.0/tests/test_algorithms.py +209 -0
  37. quantbench_engine-0.1.0/tests/test_eval_and_pareto.py +182 -0
  38. quantbench_engine-0.1.0/tests/test_packing.py +213 -0
  39. quantbench_engine-0.1.0/tests/test_primitives.py +206 -0
  40. quantbench_engine-0.1.0/tests/test_quant_linear.py +193 -0
  41. quantbench_engine-0.1.0/uv.lock +1204 -0
@@ -0,0 +1,35 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python-version: ["3.11", "3.12"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v5
22
+ with:
23
+ enable-cache: true
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ run: uv python install ${{ matrix.python-version }}
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --all-groups
30
+
31
+ - name: Run linter
32
+ run: uv run ruff check .
33
+
34
+ - name: Run test suite with coverage
35
+ run: uv run pytest
@@ -0,0 +1,43 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build package
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ with:
16
+ enable-cache: true
17
+ - name: Build sdist and wheel
18
+ run: uv build
19
+ - name: Store distributions
20
+ uses: actions/upload-artifact@v4
21
+ with:
22
+ name: python-package-distributions
23
+ path: dist/
24
+
25
+ publish-pypi:
26
+ name: Publish to PyPI
27
+ needs: [build]
28
+ runs-on: ubuntu-latest
29
+ environment:
30
+ name: pypi
31
+ url: https://pypi.org/p/quantbench
32
+ permissions:
33
+ id-token: write
34
+ steps:
35
+ - name: Download distributions
36
+ uses: actions/download-artifact@v4
37
+ with:
38
+ name: python-package-distributions
39
+ path: dist/
40
+ - name: Publish to PyPI
41
+ uses: pypa/gh-action-pypi-publish@release/v1
42
+ with:
43
+ skip-existing: true
@@ -0,0 +1,52 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ build/
7
+ develop-eggs/
8
+ dist/
9
+ downloads/
10
+ eggs/
11
+ .eggs/
12
+ lib/
13
+ lib64/
14
+ parts/
15
+ sdist/
16
+ var/
17
+ wheels/
18
+ share/python-wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual environments
25
+ .venv/
26
+ venv/
27
+ ENV/
28
+ env/
29
+
30
+ # IDE & Editor
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+
36
+ # Testing & Coverage
37
+ .pytest_cache/
38
+ .coverage
39
+ htmlcov/
40
+ .tox/
41
+ .ruff_cache/
42
+
43
+ # Artifacts & Local Weights
44
+ *.safetensors
45
+ *.bin
46
+ *.pt
47
+ *.onnx
48
+ models/
49
+ cache/
50
+ results/
51
+ decisions.md
52
+ flow.md
@@ -0,0 +1,146 @@
1
+ # Contributing to quantbench ⚖️
2
+
3
+ Thank you for your interest in contributing to `quantbench`!
4
+
5
+ `quantbench` is an open-source, first-principles quantization engine, bit-packing runtime, 2:4 sparsity toolkit, and Quality-vs-Speed Pareto evaluation benchmark written in pure Python and PyTorch. We welcome contributions that improve mathematical transparency, expand sub-byte compression layouts, add new post-training calibration algorithms, and bridge inference serving systems with precision engineering.
6
+
7
+ ---
8
+
9
+ ## 🛠️ Development Setup
10
+
11
+ We use [uv](https://docs.astral.sh/uv/) for Python environment and dependency management.
12
+
13
+ 1. **Clone the repository**:
14
+ ```bash
15
+ git clone https://github.com/Prajwal7-2002/quantbench.git
16
+ cd quantbench
17
+ ```
18
+
19
+ 2. **Sync dependencies and virtual environment**:
20
+ ```bash
21
+ uv sync
22
+ ```
23
+ This automatically installs all runtime, benchmark, and development dependencies into a isolated `.venv`.
24
+
25
+ ---
26
+
27
+ ## 🧪 Testing Protocol
28
+
29
+ We maintain high test coverage across mathematical primitives, sub-byte bit manipulation, neural network layers, and calibration algorithms.
30
+
31
+ 1. **Run the entire test suite**:
32
+ ```bash
33
+ uv run pytest
34
+ ```
35
+
36
+ 2. **Run with coverage report**:
37
+ ```bash
38
+ uv run pytest --cov=quantbench --cov-report=term-missing
39
+ ```
40
+
41
+ 3. **Run a specific test category**:
42
+ ```bash
43
+ # Test bit-packing roundtrip invariants
44
+ uv run pytest tests/test_packing.py
45
+
46
+ # Test calibration algorithms (SmoothQuant, AWQ, GPTQ)
47
+ uv run pytest tests/test_algorithms.py
48
+
49
+ # Test drop-in QuantLinear layers
50
+ uv run pytest tests/test_quant_linear.py
51
+ ```
52
+
53
+ ### Invariant Testing Rules
54
+ When contributing new quantization schemes or packing runtimes, you **must** include tests verifying:
55
+ - **Roundtrip Fidelity**: $x = \text{unpack}(\text{pack}(x))$ for all valid integer representations.
56
+ - **Mathematical Invariance**: Continuous exactness proofs (e.g. SmoothQuant $(X s^{-1})(s W) = XW$ within $10^{-5}$ drift).
57
+ - **Error Bounds**: Maximum absolute error bounded by $\frac{\Delta}{2}$ for uniform quantizers.
58
+ - **Extreme Inputs**: Subnormal values, exact zeros, all-positive, and all-negative tensor ranges.
59
+
60
+ ---
61
+
62
+ ## 🎨 Code Quality & Style
63
+
64
+ We enforce modern Python conventions, strict type hints, and clean code formatting via [ruff](https://docs.astral.sh/ruff/):
65
+
66
+ 1. **Lint and format checks**:
67
+ ```bash
68
+ uv run ruff check .
69
+ ```
70
+
71
+ 2. **Auto-fix formatting**:
72
+ ```bash
73
+ uv run ruff format .
74
+ ```
75
+
76
+ ### Architectural Principles
77
+
78
+ 1. **Zero Compiled C++/CUDA Dependencies**:
79
+ `quantbench` is designed for radical algorithmic transparency. Core quantization logic and bit-packing must run in pure Python and PyTorch without requiring NVCC or compiler toolchains.
80
+ 2. **Vectorized PyTorch Operations**:
81
+ Avoid Python `for` loops across tensor dimensions. Sub-byte bit-packing must be implemented via vectorized tensor operations (`&`, `|`, `>>`, `<<`) on `torch.uint8` containers.
82
+ 3. **Hardware Agnostic**:
83
+ All algorithms must run seamlessly on consumer CPUs, Apple Silicon, and CUDA GPUs without hardcoded device assumptions.
84
+ 4. **Honest Pareto Benchmarks**:
85
+ Never cherry-pick perplexity numbers. Always evaluate against standard validation corpora (WikiText-2, C4) using standardized sliding-window stride lengths.
86
+
87
+ ---
88
+
89
+ ## 🎯 High-Impact Areas for Contribution
90
+
91
+ We actively welcome contributions in the following domains:
92
+
93
+ ### 1. New Sub-Byte Formats & Precision Schemes (`src/quantbench/quant/`)
94
+ - [ ] **NVIDIA Blackwell NVFP4 Emulation**: Bit-exact emulation of 4-bit floating point formats (E2M1) with micro-scaling factors.
95
+ - [ ] **2-bit Non-Linear Quantization**: Quantization via Lloyd-Max optimal non-uniform codebooks.
96
+ - [ ] **NF4 (NormalFloat4)**: Quantile-based optimal representation for zero-mean normally distributed weights.
97
+
98
+ ### 2. Quantized KV-Cache Runtimes
99
+ - [ ] **INT4 / FP8 KV-Cache Page Allocator**: Interfacing with `mini-infer`'s paged memory manager to benchmark memory savings during multi-turn generation.
100
+ - [ ] **Dynamic Per-Token Key/Value Quantization**: Asymmetric scaling per token vector along the sequence dimension.
101
+
102
+ ### 3. Advanced Calibration & Optimization (`src/quantbench/quant/algorithms/`)
103
+ - [ ] **SqueezeLLM Clustering**: Non-uniform sensitivity-weighted k-means clustering with sparse outlier matrices.
104
+ - [ ] **QuIP# Vector Quantization**: Randomized Hadamard transform pre-processing to eliminate activation outliers.
105
+ - [ ] **HQQ (Half-Quadratic Quantization)**: Closed-form optimization without calibration data.
106
+
107
+ ### 4. Real-World Model Support (`src/quantbench/nn/`)
108
+ - [ ] **GGUF Dequantization Loader**: Direct parsing and loading of `.gguf` quantized tensors into `QuantLinear` modules.
109
+ - [ ] **SafeTensors Model Converter**: Auto-convert and shard Hugging Face SafeTensors checkpoints directly into disk-mapped quantized weights.
110
+
111
+ ---
112
+
113
+ ## 📬 Pull Request Rules & Submission Process
114
+
115
+ To keep `quantbench` reliable and maintainable, all contributions must follow these conventions:
116
+
117
+ ### 1. Branch Naming Conventions
118
+ Create a descriptive branch off `main`:
119
+ * `feat/short-feature-name` (e.g. `feat/nvfp4-packing`)
120
+ * `fix/short-bug-description` (e.g. `fix/ternary-base3-rounding`)
121
+ * `perf/short-perf-description` (e.g. `perf/vectorized-hessian-chol`)
122
+ * `docs/short-doc-description` (e.g. `docs/smoothquant-proof-derivation`)
123
+ * `test/short-test-description` (e.g. `test/gptq-corner-cases`)
124
+
125
+ ### 2. Conventional Commit Standards
126
+ Commits must follow the Conventional Commits specification:
127
+ ```
128
+ feat(quant): add NVIDIA NVFP4 analytical emulator and bit-packing runtime
129
+ fix(packing): correct uint8 mask overflow in sparse24 index condensation
130
+ docs(guide): add mathematical derivation of optimal brain surgeon Hessian update
131
+ test(eval): add sliding window perplexity regression test on small corpus
132
+ ```
133
+
134
+ ### 3. PR Verification Checklist
135
+ Before submitting a PR, ensure:
136
+ - [ ] `uv run pytest` passes 100% of tests.
137
+ - [ ] `uv run ruff check .` reports 0 errors.
138
+ - [ ] Test coverage does not decrease.
139
+ - [ ] Relevant documentation or examples are updated.
140
+ - [ ] Single author attribution is preserved.
141
+
142
+ ---
143
+
144
+ ## 📜 License
145
+
146
+ By contributing to `quantbench`, you agree that your contributions will be licensed under the [Apache 2.0 License](LICENSE).
@@ -0,0 +1,72 @@
1
+ # DEVLOG: quantbench
2
+
3
+ ## 2026-10-26: Project Inception & Phase 1 Mathematical Primitives
4
+
5
+ - Initialized Project #5 `quantbench` (Unified Quantization Engine & Quality-vs-Speed Pareto Benchmark).
6
+ - Architecture decision: Unified from-scratch quantization algorithms (`quantbench.quant`), drop-in PyTorch modules (`quantbench.nn`), and sliding-window Pareto evaluation (`quantbench.eval`, `quantbench.bench`) in a single zero-dependency-friction repository.
7
+ - Initialized Apache 2.0 license, `.gitignore`, and `pyproject.toml` with `hatchling` build backend and `uv` package manager.
8
+ - Implemented Phase 1 Mathematical Primitives:
9
+ - Affine asymmetric quantization ($s, z$) and symmetric AbsMax quantization ($s, z=0$) with dynamic per-tensor and per-channel scaling along arbitrary dimensions.
10
+ - Provable clamp invariants verifying $|x - \hat{x}| \le \frac{s}{2}$.
11
+ - Group-wise / block-wise quantization for group sizes $G \in \{32, 64, 128\}$ with arbitrary tensor padding and dequantization reconstruction.
12
+ - Bit-level simulation of OCP FP8 E4M3FN (range $\pm 448$, 3 mantissa bits) and E5M2 (range $\pm 57344$, 2 mantissa bits).
13
+ - 100% test coverage across mathematical invariants and error bounds.
14
+
15
+ ## 2026-10-26: Phase 2 — Integer Bit-Packing Runtimes (Sub-Byte Storage)
16
+
17
+ - Implemented vectorized sub-byte bit-packing runtimes in `quantbench.quant.packing`:
18
+ - `int4_pack.py`: Vectorized bit-shift packing of two INT4 values (unsigned $[0, 15]$ or signed two's complement $[-8, 7]$) into a single `uint8` byte container: `byte = (v0 & 0x0F) | ((v1 & 0x0F) << 4)`. Full support for odd dimension length padding and exact shape restoration.
19
+ - `ternary_pack.py`: BitNet 1.58b packing supporting both hardware-friendly 2-bit SIMD packing (4 weights/byte using biased offset $u = v + 1 \in \{0, 1, 2\}$) and theoretical maximal density Radix-3 base-3 packing (5 weights/byte via $3^5 = 243 < 256$).
20
+ - `sparse_pack.py`: NVIDIA Ampere/Ada/Hopper 2:4 structured sparsity layout. Automated row pruning, value condensation to $50\%$ storage ($M, N/2$), and 2-bit metadata column index packing into 4-bit nibbles ($M, N/8$). Decompression scatter preserves exact zeros and non-zero positions.
21
+ - Added CLI command `pack-inspect` to visualize sub-byte bit layouts and theoretical memory compression directly from the terminal.
22
+ - 22/22 unit tests passing with 93% test coverage in 2.18s. All Ruff checks passing.
23
+
24
+ ## 2026-10-26: Phase 3 — Drop-in Neural Layers (`QuantLinear`) & Model Conversion
25
+
26
+ - Created `QuantLinear` (`quantbench.nn.quant_linear`):
27
+ - A drop-in replacement for `torch.nn.Linear` storing compressed integer weights inside persistent buffers (`self.register_buffer("packed_weight", ...)`).
28
+ - Supports INT4 (groupwise and per-channel), INT8, BitNet Ternary, and 2:4 Structured Sparsity.
29
+ - Implements dynamic vector dequantization in `forward(x)`.
30
+ - Overrides `_load_from_state_dict` to dynamically bind serialized buffer tensors during checkpoint restoration.
31
+ - Computes exact layer parameter memory bytes and compression factor relative to FP16.
32
+ - Created `convert_model_to_quant` (`quantbench.nn.model_convert`):
33
+ - In-place recursive model converter traversing PyTorch module trees.
34
+ - Swaps targeted linear layers (`q_proj`, `k_proj`, `v_proj`, `o_proj`, `gate_proj`, `up_proj`, `down_proj`) while cleanly preserving sensitive layers (`lm_head`).
35
+ - Reports layer conversion counts, memory reduction statistics, and elapsed conversion duration.
36
+ ## 2026-10-26: Phase 4 — Advanced Calibration Algorithms (SmoothQuant, AWQ, GPTQ)
37
+
38
+ - Created `quantbench.quant.algorithms`:
39
+ - `smoothquant.py`: Implemented activation outlier channel profiling and per-channel migration scale computation ($Y = (X \cdot \text{diag}(s)^{-1}) \cdot (\text{diag}(s) \cdot W)$). Mathematical verification confirms exact continuous output invariance before discrete rounding.
40
+ - `awq.py`: Implemented Activation-aware Weight Quantization with mean activation channel profiling and grid-search over scale candidate $\alpha \in [0, 1]$ to minimize Frobenius reconstruction error $\| W X - \hat{W} X \|_F^2$.
41
+ - `gptq.py`: Implemented Accurate Post-Training Quantization for Generative Pre-trained Transformers using empirical activation Hessian ($H = 2 X X^T$), diagonal damping regularization ($H_{\text{damp}} = H + \lambda \cdot \text{mean}(\text{diag}(H)) \cdot I$), Cholesky decomposition inversion ($H^{-1} = L^{-T} L^{-1}$), Optimal Brain Surgeon (OBS) coordinate updates, and vectorized block GEMM updates ($W_{:, j+B:} \mathrel{-}= E_{\text{block}} \cdot [H^{-1}]_{j:j+B, j+B:}$).
42
+ - Added comprehensive unit tests in `tests/test_algorithms.py`:
43
+ - Outlier profiling and continuous mathematical invariance testing.
44
+ - AWQ reconstruction error reduction testing on synthetic salient channels.
45
+ - Hessian symmetry, positive semi-definiteness, and GPTQ OBS error reduction testing.
46
+ - 39/39 unit tests passing with 93% test coverage across the repository. All Ruff checks passing.
47
+
48
+ ## 2026-10-26: Phase 5 & 6 — Sliding-Window Perplexity, SQNR & Pareto Benchmarking
49
+
50
+ - Created `quantbench.eval`:
51
+ - `sqnr.py`: Implemented Signal-to-Quantization-Noise Ratio ($10 \log_{10}(P_{\text{signal}} / P_{\text{noise}})$) in decibels (dB) for layer-level numerical fidelity tracking without forward inference overhead.
52
+ - `perplexity.py`: Implemented statistically rigorous sliding-window causal language model evaluation engine. Strided contexts ($S < L$) eliminate context boundary collapse by evaluating loss strictly on trailing $S$ tokens.
53
+ - Created `quantbench.bench.pareto`:
54
+ - `ParetoBenchmark`: Automated sweep engine mapping (Compression Ratio, Footprint MB, Delta PPL, SQNR dB) across FP16 baseline, INT8, INT4 (G=128, G=64), BitNet Ternary, and 2:4 Structured Sparsity.
55
+ - Formats GitHub Markdown tables and ASCII terminal scatter plots.
56
+ - Added CLI commands `eval` and `pareto` in `quantbench.cli`.
57
+ - Added unit tests in `tests/test_eval_and_pareto.py`:
58
+ - 47/47 unit tests passing across entire repo with 95% test coverage in 3.33s. All Ruff checks passing.
59
+
60
+ ## 2026-10-26: Phase 7 — Public Learning Guide & Packaging Complete
61
+
62
+ - Authoring of `GUIDE.md`:
63
+ - Comprehensive educational engineering guide detailing arithmetic intensity rooflines, zero-preserving affine invariant derivation, banker's rounding drift, OCP FP8 specifications, vectorized sub-byte packing runtimes, SmoothQuant, AWQ, GPTQ second-order Hessian compensation, persistent buffer architecture, and dual-metric Pareto evaluation.
64
+ - Validated PyPI distribution packaging with `uv build`:
65
+ - Successfully produced source distribution (`.tar.gz`) and platform-independent wheel (`.whl`).
66
+ - Repository verified across 47 automated test suites with 95% line coverage. All Ruff checks passing.
67
+ - All 7 staged roadmap milestones in `README.md` completed.
68
+
69
+
70
+
71
+
72
+
@@ -0,0 +1,193 @@
1
+ # The Comprehensive Guide to LLM Quantization & Hardware Sparsity ⚡
2
+ **From First-Principles Mathematical Formulations to Vectorized Bit-Packing Runtimes and Pareto Evaluation**
3
+
4
+ *Author: Prajwal Pujari ([@Prajwal7-2002](https://github.com/Prajwal7-2002))*
5
+ *Project: [quantbench](https://github.com/Prajwal7-2002/quantbench)*
6
+
7
+ ---
8
+
9
+ ## 1. Introduction: Why Quantization is Mandatory in LLM Serving
10
+
11
+ When serving modern Generative Large Language Models (LLMs), the primary inference bottleneck during autoregressive token generation (the decoding phase) is **memory bandwidth, not compute capacity**.
12
+
13
+ ### The Arithmetic Intensity Bottleneck
14
+ In the autoregressive decode loop, the model processes tokens with batch size $B=1$ and query length 1:
15
+ * The GEMV (General Matrix-Vector multiplication) arithmetic intensity is:
16
+ $$\text{Arithmetic Intensity} \approx \frac{2 \cdot P \text{ FLOPs}}{2 \cdot P \text{ Bytes}} = 1.0 \text{ FLOP/Byte} \quad (\text{in FP16})$$
17
+ * On an NVIDIA A100 SXM (312 TFLOPS FP16 Tensor Core, 2,039 GB/s HBM2e bandwidth), the hardware ridge point is:
18
+ $$\text{Ridge Point} = \frac{312 \times 10^{12} \text{ FLOP/s}}{2,039 \times 10^9 \text{ B/s}} \approx 153 \text{ FLOPs/Byte}$$
19
+ * Since $1.0 \ll 153$, the GPU Tensor Cores sit **99.3% idle**, starved for weights streaming from high-bandwidth memory (HBM).
20
+
21
+ ### Memory Bandwidth Reduction = Linear Decode Acceleration
22
+ By compressing weights from 16-bit to 4-bit (INT4):
23
+ * Weight memory footprint is cut by $\mathbf{4.0\times}$.
24
+ * The byte volume transferred over the memory bus per generated token drops by $\mathbf{4.0\times}$.
25
+ * Autoregressive decoding throughput increases nearly linearly with the compression factor!
26
+
27
+ ---
28
+
29
+ ## 2. Mathematical Foundations of Quantization
30
+
31
+ ### 2.1. The Zero-Preserving Affine Invariant
32
+ Quantization maps continuous real numbers $x \in [\alpha, \beta]$ to a discrete integer grid $q \in [q_{\min}, q_{\max}]$.
33
+
34
+ $$\text{scale} = s = \frac{\beta - \alpha}{q_{\max} - q_{\min}}$$
35
+ $$\text{zero\_point} = z = \text{round}\left( - \frac{\alpha}{s} \right) + q_{\min}$$
36
+ $$q = \text{clamp}\left( \text{round}\left( \frac{x}{s} \right) + z, \; q_{\min}, \; q_{\max} \right)$$
37
+ $$\hat{x} = (q - z) \cdot s$$
38
+
39
+ #### Why Real $0.0$ Must Map Exactly to an Integer Zero-Point $z$:
40
+ In neural network operations:
41
+ 1. **Padded Tokens**: Sequences of varying lengths use zero-padding ($x = 0.0$).
42
+ 2. **ReLU / SwiGLU Zeros**: Non-linear activations introduce exact zero activations.
43
+ 3. If $x = 0.0$ did not map to an integer $z$:
44
+ $$\hat{x} = (\text{round}(0 + z_{\text{float}}) - z_{\text{float}}) \cdot s \ne 0.0$$
45
+ Padding tokens would leak non-zero bias signals across self-attention projections, corrupting transformer output logits!
46
+
47
+ ### 2.2. Symmetric AbsMax Quantization
48
+ When data distributions are symmetric around zero (e.g. weights centered at mean $0$):
49
+ * Restrict zero point to strictly $z = 0$.
50
+ * For signed $b$-bit integer ($q_{\max} = 2^{b-1} - 1$):
51
+ $$s = \frac{\max(|x|)}{2^{b-1} - 1}$$
52
+ $$q = \text{clamp}\left( \text{round}\left( \frac{x}{s} \right), \; -q_{\max}, \; q_{\max} \right)$$
53
+ $$\hat{x} = q \cdot s$$
54
+ * In symmetric AbsMax, dequantization simplifies from $(q - z) s$ to pure multiplication $q \cdot s$, eliminating subtraction instructions from GPU GEMM inner loops.
55
+
56
+ ### 2.3. Group-wise / Block-wise Quantization
57
+ Per-tensor quantization uses a single scale $s$ for the entire weight matrix. A single outlier value pushes $s$ up, severely degrading the precision of normal values.
58
+
59
+ Block-wise quantization slices the weight matrix into independent groups of size $G \in \{32, 64, 128\}$:
60
+ * Each block $k$ computes its own independent scale $s_k$ and zero-point $z_k$.
61
+ * **The Granularity Trade-off**:
62
+ * Smaller $G$ (e.g. 32): Higher precision, but scales consume $16 / 32 = 0.5$ bits/weight ($12.5\%$ metadata overhead).
63
+ * Larger $G$ (e.g. 128): Lower metadata overhead ($16 / 128 = 0.125$ bits/weight), but slightly reduced ability to isolate local outliers.
64
+ * In practice, **$G = 128$ or $G = 64$** represents the Pareto-optimal operating point for LLMs.
65
+
66
+ ---
67
+
68
+ ## 3. Modern FP8 Formats (OCP Standard)
69
+
70
+ The Open Compute Project (OCP) standardizes two distinct 8-bit floating point formats:
71
+
72
+ | Specification | OCP FP8 E4M3FN | OCP FP8 E5M2 |
73
+ |---|---|---|
74
+ | **Bit Layout** | 1 sign, 4 exponent, 3 mantissa | 1 sign, 5 exponent, 2 mantissa |
75
+ | **Exponent Bias** | 7 | 15 |
76
+ | **Max Absolute Value** | $\pm 448.0$ | $\pm 57344.0$ |
77
+ | **Mantissa Resolution** | High ($2^{-3} = 0.125$) | Low ($2^{-2} = 0.25$) |
78
+ | **Primary Use-Case** | **Forward GEMM** (Weights & Activations) | **KV Cache, Gradients, Optimizer States** |
79
+
80
+ ### Analytical Emulation on Older GPUs / CPUs
81
+ Hardware lacking native FP8 instructions (e.g. RTX 30-series, Apple Silicon, CPUs) cannot natively execute `torch.float8_e4m3fn`. `quantbench` provides a bit-exact software emulator that analytically simulates exponent bias, mantissa truncation, and saturation bounds:
82
+ ```python
83
+ # Analytical bit-level reconstruction
84
+ e = clamp(floor(log2(|x|)) + bias, 0, 2^exp_bits - 1)
85
+ m = round((|x| / 2^(e - bias) - 1.0) * 2^mantissa_bits)
86
+ x_hat = sign(x) * (1.0 + m / 2^mantissa_bits) * 2^(e - bias)
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 4. Sub-Byte Vectorized Bit-Packing Runtimes
92
+
93
+ Modern CPU and GPU memory subsystems are byte-addressable (minimum addressable boundary is **8 bits**). Storing 4-bit, 2-bit, or ternary weights requires sub-byte bit packing into `uint8` containers.
94
+
95
+ ### 4.1. Vectorized INT4 Packing
96
+ * Two 4-bit values $v_0$ and $v_1$ pack into 1 byte:
97
+ $$\text{byte} = (v_0 \& 0x0F) \mid ((v_1 \& 0x0F) \ll 4)$$
98
+ * Unpacking:
99
+ $$v_0 = \text{byte} \& 0x0F, \quad v_1 = (\text{byte} \gg 4) \& 0x0F$$
100
+ * **Signed Two's Complement Extension**:
101
+ If bit 3 is set ($v \ge 8$), sign-extend to negative: $v_{\text{signed}} = v - 16$.
102
+
103
+ ### 4.2. BitNet 1.58b Ternary Packing
104
+ Constrains weights strictly to $\{-1, 0, +1\}$:
105
+ 1. **2-bit Biased SIMD Packing (Fastest)**:
106
+ * Maps $u = v + 1 \in \{0, 1, 2\}$.
107
+ * 4 weights fit into 1 byte:
108
+ $$\text{byte} = u_0 \mid (u_1 \ll 2) \mid (u_2 \ll 4) \mid (u_3 \ll 6)$$
109
+ * Decodes via parallel SIMD bit shifts without integer division.
110
+ 2. **Radix-3 Base-3 Packing (Maximum Density)**:
111
+ * 5 weights fit into 1 byte since $3^5 = 243 \le 255$:
112
+ $$\text{byte} = u_0 + 3 u_1 + 9 u_2 + 27 u_3 + 81 u_4$$
113
+ * Achieves theoretical $\log_2(3) \approx 1.585 \text{ bits/weight}$.
114
+
115
+ ### 4.3. NVIDIA Ampere/Ada/Hopper 2:4 Structured Sparsity
116
+ NVIDIA Tensor Cores natively support 2:4 sparsity (in every 4 contiguous elements, at least 2 must be zero):
117
+ 1. **Condensed Matrix**: Compresses non-zeros into dense matrix $(M, N/2)$ (50% reduction).
118
+ 2. **Metadata Nibbles**: Records 2-bit column indices ($0..3$) for each non-zero element.
119
+ 3. Two 4-element blocks (8 dense elements, 4 non-zeros) pack into **1 metadata byte**:
120
+ $$\text{byte} = (idx_{A,0} \& 3) \mid ((idx_{A,1} \& 3) \ll 2) \mid ((idx_{B,0} \& 3) \ll 4) \mid ((idx_{B,1} \& 3) \ll 6)$$
121
+ 4. Metadata overhead is strictly **2 bits per non-zero value** (only 12.5% of FP16 weight size).
122
+
123
+ ---
124
+
125
+ ## 5. Advanced Post-Training Calibration Algorithms
126
+
127
+ ### 5.1. SmoothQuant: Activation Outlier Migration
128
+ * **Insight**: LLM activations have systematic outlier channels ($100\times$ normal values), while weights are smooth.
129
+ * **Invariant Transformation**:
130
+ $$Y = X W = (X \cdot \text{diag}(s)^{-1}) \cdot (\text{diag}(s) \cdot W)$$
131
+ * **Scale Derivation**:
132
+ $$s_j = \frac{\max(|X_j|)^\alpha}{\max(|W_j|)^{1 - \alpha}} \quad (\alpha=0.5 \text{ balances activation and weight})$$
133
+ * Scale vector $s$ is folded into preceding LayerNorm/RMSNorm weights, enabling standard INT8 Tensor Core GEMM.
134
+
135
+ ### 5.2. AWQ: Activation-Aware Weight Quantization
136
+ * **Insight**: Only top 1% salient weight channels preserve perplexity.
137
+ * Salience is determined by mean activation magnitude: $s_X = \frac{1}{N} \sum |X|$.
138
+ * Instead of keeping salient weights in FP16 (which ruins uniform SIMD kernels), AWQ applies a per-channel protection scale:
139
+ $$s = s_X^\alpha$$
140
+ where $\alpha \in [0, 1]$ is optimized via grid search on calibration tokens to minimize Frobenius reconstruction error:
141
+ $$\min_\alpha \| W X - \text{dequantize}(\text{quantize}(W \text{diag}(s))) \text{diag}(s)^{-1} X \|_F^2$$
142
+
143
+ ### 5.3. GPTQ: Second-Order Hessian Compensation
144
+ * Uses second-order Taylor expansion of quantization error:
145
+ $$E \approx \frac{1}{2} (w - \hat{w})^T H (w - \hat{w}), \quad H = 2 X X^T$$
146
+ * **Damping Regularization**:
147
+ $$H_{\text{damp}} = H + \lambda \cdot \text{mean}(\text{diag}(H)) \cdot I \quad (\lambda = 0.01)$$
148
+ * Inverts via Cholesky decomposition: $H = L L^T \implies H^{-1} = L^{-T} L^{-1}$.
149
+ * **Optimal Brain Surgeon (OBS) Update**:
150
+ When rounding column $q$, updates remaining columns $F$:
151
+ $$\Delta W_{:, F} = - \frac{W_{:, q} - \hat{W}_{:, q}}{[H^{-1}]_{qq}} \cdot [H^{-1}]_{q, F}$$
152
+ * **Block Updates**: Accumulates errors in blocks of $B$ columns (e.g. 128) and performs dense matrix multiplications (GEMM) to update the remaining matrix.
153
+
154
+ ---
155
+
156
+ ## 6. Drop-in PyTorch Architecture & In-Place Conversion
157
+
158
+ ### Why Persistent Buffers Beat `nn.Parameter` for Inference
159
+ 1. `nn.Parameter` forces float dtypes and triggers Autograd gradient tracking (`requires_grad=True`).
160
+ 2. If touched by an optimizer, it allocates momentum and gradient buffers ($2\times\text{--}3\times$ model size).
161
+ 3. `QuantLinear` stores packed weights as persistent buffers (`self.register_buffer("packed_weight", ...)`):
162
+ * Zero gradient tracking.
163
+ * Zero optimizer memory overhead.
164
+ * Automatically serializes into `state_dict()` and `safetensors`.
165
+ 4. **Dynamic Checkpoint Hook (`_load_from_state_dict`)**:
166
+ Overrides PyTorch's hook to register serialized buffer shapes dynamically before strict key validation runs.
167
+
168
+ ---
169
+
170
+ ## 7. Quality-vs-Speed Pareto Benchmarking
171
+
172
+ ### Dual-Metric Evaluation
173
+ 1. **Layer-Level SQNR (dB)**:
174
+ $$\text{SQNR (dB)} = 10 \cdot \log_{10} \left( \frac{\sum |W|^2}{\sum |W - \hat{W}|^2 + \epsilon} \right)$$
175
+ Diagnoses numerical reconstruction fidelity layer-by-layer without inference passes.
176
+ 2. **Model-Level Sliding-Window Perplexity**:
177
+ Uses context window $L$ with stride $S < L$, evaluating loss strictly on trailing $S$ tokens to eliminate chunk boundary context collapse.
178
+ 3. **Pareto Table Output**:
179
+ Maps configurations across (Compression Ratio, Footprint MB, Delta PPL, SQNR dB).
180
+
181
+ ---
182
+
183
+ ## 8. Summary Comparison of Quantization Schemes
184
+
185
+ | Scheme | Target Bits | Memory Reduction | Compute Speedup | Accuracy Impact | Recommended Use-Case |
186
+ |---|---|---|---|---|---|
187
+ | **FP16 Baseline** | 16-bit | $1.0\times$ | $1.0\times$ | Baseline | Reference quality |
188
+ | **FP8 (E4M3)** | 8-bit | $2.0\times$ | $1.8\times\text{--}2.0\times$ | Near zero ($\Delta \text{PPL} < 0.01$) | Standard serving on Ada/Hopper |
189
+ | **INT8 AbsMax** | 8-bit | $2.0\times$ | $1.7\times\text{--}1.9\times$ | Near zero ($\Delta \text{PPL} < 0.02$) | Universal CPU/GPU acceleration |
190
+ | **INT4 Blockwise** | 4-bit | $3.2\times\text{--}3.6\times$ | $2.5\times\text{--}3.5\times$ | Low ($\Delta \text{PPL} < 0.15$) | VRAM-constrained edge / consumer GPUs |
191
+ | **AWQ / GPTQ INT4** | 4-bit | $3.5\times$ | $3.0\times$ | Minimal ($\Delta \text{PPL} < 0.05$) | Production 4-bit LLM deployment |
192
+ | **Ampere 2:4 Sparse**| 8-bit eff. | $2.0\times$ | $2.0\times$ math | Negligible ($\Delta \text{PPL} < 0.08$) | Dense-throughput acceleration |
193
+ | **BitNet Ternary** | 1.58-bit | $7.5\times\text{--}8.0\times$ | $5.0\times\text{--}7.0\times$ | Requires fine-tuning | Ultra-low power / specialized silicon |