N-Gram Memories at Two Bits: Quantizing Lookup Tables in Large Language Models
Organizations: Dnotitia Inc. · KAIST
Abstract
Conditional memory expands language-model capacity through selective lookup, but the full embedding table must remain available for every possible input. We introduce Conditional Program (CP), a compressed representation that reconstructs only the rows an input requests. CP represents each row by a short code and a local scale, with a reconstruction program shared across the table. We instantiate this representation with a Gaussian trellis, norm restoration and independently decodable row records. CP's two-bit code lowers output KL by 41--63% relative to 2-bit round-to-nearest. Analysis across three trained n-gram memory families shows that Gaussian-like coordinate statistics coexist with learned relationships among rows; at matched storage budgets, the shared trellis outperforms the fitted codebooks and low-rank residual variants we test. For DeepSeek, it reduces table storage from 203GB to 51GB, leaving room for larger workloads when the table is kept on GPU.
Figures & tables
| Task score | ||||||||||
| Method | Bits | Table GB | PopQA | TriviaQA | NQ | MMLU | Belebele | GSM8K | HumanEval | Overall |
| DeepSeek-V4.1-Flash | ||||||||||
| Original | — | 202.7 | 44.2 | 87.9 | 43.2 | 88.2 | 93.9 | 96.4 | 97.6 | 79.8 |
| w/o memory | — | 0.0 | 20.9 | 75.0 | 30.4 | 82.2 | 89.1 | 95.8 | 90.2 | 73.5 |
| RTN | 3 | 86.0 | 43.9 | 87.9 | 43.5 | 88.3 | 93.9 | 96.8 | 98.2 | 79.9 |
| 2 | 61.4 | 43.1 | 87.8 | 43.1 | 88.7 | 94.1 | 97.0 | 96.3 | 79.7 | |
| 2-gram table | Energy (%) | Gaussian ref. |
|---|---|---|
| DeepSeek, layer 1 | 19.1% | 6.25% |
| DeepSeek, layer 14 | 21.1% | 6.25% |
| Qwen | 33.3% | 10.0% |
| LongCat | 10.3% | 6.25% |
| Representation | bpp | KL |
|---|---|---|
| Shared trellis | 2.10 | 0.0198 |
| Fitted VQ, | 2.10 | 0.0238 |
| Fitted VQ, | 2.10 | 0.0226 |
| Mean + trellis | 2.10 | 0.0193 |
| Mean + four PCs + trellis | 2.50 | 0.0188 |
| Trellis reference † | 2.50 | 0.0144 |
| Output KL | ||||
|---|---|---|---|---|
| Rotate | Scale | DeepSeek | Qwen | LongCat |
| Yes | Global | 0.0414 | 0.0347 | 0.0468 |
| No | Global | 0.0416 | 0.0346 | 0.0473 |
| No | Row LS | 0.0404 | 0.0349 | 0.0462 |
| No | Row norm | 0.0401 | 0.0327 | 0.0426 |
| (a) Four GPUs: memory and latency | |||
| Metric / workload | FP8 | NVFP4 | CP 2-bit |
| Table memory (GB/GPU) | 50.7 | 27.6 | 12.7 |
| Prefill, k (s) | 64.66 2.49 | 13.26 0.28 | 13.27 0.22 |
| Decode, batch 8 (ms/step) | 795.7 11.1 | 788.9 10.0 | 792.9 6.3 |
| Decode, batch 512 (s/step) | OOM | 4.03 0.03 | 4.05 0.06 |
| Prefill, 64k tokens (s) | OOM | 59.81 4.75 | 18.23 0.01 |
Appendix figures & tables23 assets
Supplementary material from the paper’s appendix.
Appendix
| Model | Table | Rows | Row | Rows read | Original |
|---|---|---|---|---|---|
| params | dim | per token | format | ||
| DeepSeek a | 196.6B | 768.0M | 256 | 48 | FP8 b |
| Qwen | 51.2B | 320.0M | 160 | 16 | BF16 |
| LongCat | 31.4B | 122.7M | 256 | 12 | BF16 |
| Benchmark | Evaluation set | Items | Scoring |
|---|---|---|---|
| ARC-E / ARC-C | Test | 1000 / 1172 | Length-normalized likelihood |
| HellaSwag / PIQA | Validation | 1000 each | Length-normalized likelihood |
| WinoGrande / BoolQ | Validation | 1267 / 1000 | Likelihood accuracy |
| LAMBADA | English test | 1000 | Last-word token match |
| MMLU | Stratified test | 1000 | Five-shot choice accuracy |
| PopQA | Test, five popularity bins | 5000 | Lowercase answer contains-match |
| DeepSeek-V4.1-Flash | Qwen3.8-Flash-Next | LongCat-Flash-Lite | |||||||||||||||||||
| RTN | CP | RTN | CP | RTN | CP | ||||||||||||||||
| Task | Orig. | Rem. | 3 | 2 | QTIP | 2 | 1.5 | Orig. | Rem. | 3 | 2 | QTIP | 2 | 1.5 | Orig. | Rem. | 3 | 2 | QTIP | 2 | 1.5 |
| Commonsense | |||||||||||||||||||||
| ARC-E | .872 | .872 | .881 | .878 | .873 | .884 | .875 | .811 | .777 | .802 | .809 | .811 | .800 | .813 | .821 | .714 | .820 | .819 | .823 | .824 | .825 |
| ARC-C | .695 | .665 | .686 | .698 | .692 | .692 | .691 | .642 | .589 | .637 | .642 | .640 | .640 | .634 | .616 | .453 | .602 | .596 | .605 | .618 | .615 |
| HellaSwag | .883 | .828 | .882 | .880 | .886 | .880 | .888 | .890 | .889 | .888 | .892 | .895 | .894 | .892 | .810 | .614 | .822 | .816 | .815 | .826 | .809 |
| DeepSeek | Qwen | LongCat | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Setting | 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 4 | 5 |
| Original | .335 | .333 | .379 | .482 | .683 | .261 | .230 | .269 | .380 | .674 | .224 | .157 | .165 | .243 | .542 |
| Table removed | .133 | .096 | .108 | .190 | .520 | .188 | .132 | .149 | .253 | .606 | .149 | .080 | .067 | .065 | .228 |
| RTN 3-bit | .323 | .330 | .375 | .481 | .686 | .259 | .239 | .272 | .378 | .673 | .229 | .155 | .159 | .243 | .534 |
| RTN 2-bit | .310 | .312 | .367 | .470 | .694 | .245 | .215 | .254 | .376 | .663 | .228 | .153 | .153 | .239 | .534 |
| QTIP 2.0 | .323 | .332 | .370 | .478 | .689 | .254 | .232 | .262 | .380 | .676 | .224 | .159 | .155 | .246 | .537 |
| Task | CP 2 RTN 2 | CP 2 QTIP 2 | CP 1.5 QTIP 2 | CP 1.5 RTN 2 | |
|---|---|---|---|---|---|
| ARC-E | 1000 | +0.6 [-0.7, +1.9] | +1.1 [+0.0, +2.2] | +0.2 [-1.1, +1.5] | -0.3 [-1.6, +1.0] |
| ARC-C | 1172 | -0.6 [-2.2, +1.0] | +0.0 [-1.5, +1.5] | -0.1 [-1.7, +1.5] | -0.7 [-2.5, +1.2] |
| HellaSwag | 1000 | +0.0 [-0.9, +0.9] | -0.6 [-1.4, +0.2] | +0.2 [-0.6, +1.0] | +0.8 [-0.1, +1.7] |
| PIQA | 1000 | +0.9 [-0.1, +1.9] | +0.9 [-0.1, +2.0] | +0.4 [-0.7, +1.5] | +0.4 [-0.6, +1.4] |
| WinoGrande | 1267 | +0.5 [-1.1, +2.1] | +0.3 [-1.1, +1.7] | -0.6 [-2.1, +1.0] | -0.4 [-2.1, +1.3] |
| BoolQ | 1000 | +0.1 [-0.9, +1.1] | -0.3 [-1.2, +0.6] | +0.1 [-0.9, +1.1] | +0.5 [-0.5, +1.6] |
| Task | CP 2 RTN 2 | CP 2 QTIP 2 | CP 1.5 QTIP 2 | CP 1.5 RTN 2 | |
|---|---|---|---|---|---|
| ARC-E | 1000 | -0.9 [-2.5, +0.6] | -1.1 [-2.5, +0.3] | +0.2 [-1.3, +1.7] | +0.4 [-1.1, +1.9] |
| ARC-C | 1172 | -0.2 [-1.9, +1.5] | +0.0 [-1.7, +1.7] | -0.6 [-2.3, +1.0] | -0.8 [-2.5, +0.9] |
| HellaSwag | 1000 | +0.2 [-0.6, +1.0] | -0.1 [-0.8, +0.6] | -0.3 [-1.3, +0.6] | +0.0 [-1.0, +1.0] |
| PIQA | 1000 | -0.6 [-2.0, +0.8] | +0.8 [-0.4, +2.0] | +0.6 [-0.7, +2.0] | -0.8 [-2.2, +0.6] |
| WinoGrande | 1267 | -2.1 [-4.3, +0.2] | -0.9 [-2.8, +0.9] | +1.3 [-0.6, +3.2] | +0.2 [-1.8, +2.3] |
| BoolQ | 1000 | +0.2 [-1.4, +1.9] | +0.5 [-0.9, +2.0] | -0.3 [-1.8, +1.2] | -0.6 [-2.2, +1.0] |
| Task | CP 2 RTN 2 | CP 2 QTIP 2 | CP 1.5 QTIP 2 | CP 1.5 RTN 2 | |
|---|---|---|---|---|---|
| ARC-E | 1000 | +0.5 [-1.0, +2.0] | +0.1 [-1.2, +1.4] | +0.2 [-1.2, +1.6] | +0.6 [-0.9, +2.1] |
| ARC-C | 1172 | +2.1 [+0.4, +3.8] | +1.3 [-0.2, +2.7] | +1.0 [-0.5, +2.6] | +1.9 [+0.2, +3.6] |
| HellaSwag | 1000 | +1.0 [-0.3, +2.4] | +1.1 [-0.1, +2.3] | -0.6 [-2.0, +0.7] | -0.7 [-2.1, +0.6] |
| PIQA | 1000 | +0.9 [-0.8, +2.6] | -1.2 [-2.7, +0.3] | -1.4 [-2.9, +0.1] | +0.7 [-0.8, +2.3] |
| WinoGrande | 1267 | +0.4 [-2.3, +3.1] | +0.4 [-2.0, +2.7] | +1.1 [-1.4, +3.6] | +1.1 [-1.5, +3.8] |
| BoolQ | 1000 | +1.4 [+0.0, +2.9] | +0.7 [-0.5, +1.9] | +0.7 [-0.6, +2.0] | +1.4 [-0.1, +2.9] |
| DeepSeek-V4.1-Flash | Qwen3.8-Flash-Next | LongCat-Flash-Lite | |||||||||||||
| Setting | bpp | GB | KL | KL max | top-1 | bpp | GB | KL | KL max | top-1 | bpp | GB | KL | KL max | top-1 |
| Original | 8.25 | 202.7 | 0 | 0 | 1.000 | 16.00 | 102.4 | 0 | 0 | 1.000 | 16.00 | 62.8 | 0 | 0 | 1.000 |
| Table removed | 0 | 0 | .773 | 1.08 | .713 | 0 | 0 | .308 | .481 | .815 | 0 | 0 | 2.89 | 3.57 | .475 |
| Mean row | 0 | 0 | .517 | .743 | .775 | 0 | 0 | .310 | .477 | .819 | 0 | 0 | 3.44 | 4.07 | .446 |
| NVFP4 | 4.50 | 110.6 | .0199 | .0298 | .954 | 4.50 | 28.8 | .0166 | .0289 | .955 | 4.50 | 17.7 | .0111 | .0173 | .968 |
| MXFP4 | 4.25 | 104.4 | .0220 | .0347 | .952 | 4.25 | 27.2 | .0182 | .0274 | .953 | 4.25 | 16.7 | .0144 | .0216 | .964 |
| Setting | DeepSeek | Qwen | LongCat |
|---|---|---|---|
| Original | 2.611 | 4.671 | 13.316 |
| Table removed | 7.703 | 6.476 | 103.539 |
| RTN 3-bit | 2.835 | 4.757 | 13.681 |
| RTN 2-bit | 3.662 | 5.089 | 14.842 |
| QTIP 2.0 | 3.089 | 4.827 | 13.325 |
| CP, 2-bit code | 3.054 | 4.830 | 13.538 |
| Statistic | DeepSeek | Qwen | LongCat | Gaussian |
|---|---|---|---|---|
| 256 | 160 | 256 | 256/160 | |
| Kurtosis | 2.99 | 2.94–2.95 | 2.96–2.97 | 2.98/2.96 |
| Kurt. (read-wtd.) | 2.98–2.99 | 2.95 | 2.95–2.96 | 2.98/2.96 |
| Max/RMS | 3.00–3.01 | 2.84–2.85 | 2.99 | 3.00/2.86 |
| Cov. eff. rank | 239–250 | 152–158 | 253–254 | 256/160 |
| KLT gain (dB) | 0.10–0.25 | 0.18–0.53 | 0.04–0.21 | 0 |
| Representation | bpp | Qwen KL [95% CI] |
|---|---|---|
| Shared trellis | 2.1 | .0198 [.0163, .0234] |
| Fitted VQ, | 2.1 | .0238 [.0193, .0285] |
| Fitted VQ, | 2.1 | .0226 [.0184, .0269] |
| Mean + trellis | 2.1 | .0193 [.0160, .0229] |
| Mean + 4 PCs + trellis | 2.5 | .0188 [.0156, .0220] |
| Shared trellis curve | 2.5 | .0144 |
| Code | bpp | KL | KL max | top-1 |
|---|---|---|---|---|
| QuIP# E8P a | 2.00 | .0413 | .0605 | .934 |
| QuIP# E8P, norm restored b | 2.10 | .0373 | .0518 | .937 |
| AQLM c | 2.10 | .0385 | .0545 | .936 |
| AQLM , norm restored d | 2.10 | .0374 | .0518 | .937 |
| HIGGS c | 2.10 | .0404 | .0577 | .935 |
| HIGGS, norm restored d | 2.10 | .0391 | .0544 | .936 |
| DeepSeek | Qwen | LongCat | |||||||
| Step | bpp | KL | ratio [95% CI] | bpp | KL | ratio [95% CI] | bpp | KL | ratio [95% CI] |
| QTIP | 2.00 | .0414 | – | 2.00 | .0347 | – | 2.00 | .0468 | – |
| No rotation | 2.00 | .0416 | 1.005 [.995, 1.015] | 2.00 | .0346 | .999 [.974, 1.027] | 2.00 | .0473 | 1.010 [1.000, 1.020] |
| Row LS gain | 2.06 | .0404 | .972 [.964, .981] | 2.10 | .0349 | 1.008 [.984, 1.030] | 2.06 | .0462 | .977 [.974, .981] |
| Norm restoration | 2.06 | .0401 | .991 [.987, .995] | 2.10 | .0327 | .937 [.904, .970] | 2.06 | .0426 | .922 [.917, .928] |
| CP / QTIP | – | – | .968 [.959, .977] | – | – | .943 [.917, .969] | – | – | .910 [.900, .919] |
| Web | Code | Wikipedia | |
|---|---|---|---|
| LongCat | .904 | .940 | .904 |
| [.886, .923] | [.923, .958] | [.889, .918] | |
| Qwen | .983 | .944 | .988 |
| [.975, .992] | [.928, .958] | [.970, 1.005] | |
| DeepSeek | .997 | .997 | .988 |
| [.987, 1.006] | [.979, 1.014] | [.971, 1.004] |
| Tool | DeepSeek | Qwen | LongCat | Eval. |
|---|---|---|---|---|
| Rotation a | .999 | .993 | 1.008 | S |
| (Hadamard) | [.990, 1.008] | [.971, 1.015] | [.997, 1.019] | |
| Second-order | – | 1.46 | 1.11 | E |
| rounding | Lloyd–Max | GPTQ | ||
| Frequency | – | 1.044 b | – | S |
| allocation | [1.016, 1.076] |
| Tool | Motivation | Measurement | Evaluation setup |
|---|---|---|---|
| Rotation (random Hadamard within a row) | Gaussian-like row statistics motivate testing whether within-row rotation improves reconstruction. | KL ratio without/with rotation, both with norm restoration: DeepSeek .999 [.990, 1.008] † , Qwen .993 [.971, 1.015], LongCat 1.008 [.997, 1.019]. Table MSE ratio .998–1.001 on all 11 order tables. | KL: shared benchmark (six domains; token counts in Appendix A ), 2.06–2.10 bpp. MSE: CPU encode, 2,048–4,096 read-weighted rows per table. |
| Second-order rounding (GPTQ, LDLQ, metric-aware scalar) | A readout-only surrogate metric is : condition number 2.5 (LongCat), metric effective rank 243–254/256 and 155–158/160. This surrogate omits gates and subsequent layers. | KL with vs without the metric: LongCat GPTQ .128 vs .115 (vs RTN, 2.5 bpp); Qwen metric-whitened Lloyd–Max .1502 vs .1027 (2.1 bpp). Not tested on DeepSeek. | (E) Separate evaluation: about 32k web tokens, own baseline per row. |
| Low-rank decomposition | Covariance effective rank 239–254/256 and 152–158/160: high global rank; frequent-row structure is examined separately in Section 4.3 . | Global covariance alone does not determine compression value. A pure low-rank replacement was not evaluated end to end. A mean + 4 PCs + trellis residual was, at equal bytes (Section 4.3 ). | Qwen KL (Section 4.3 ) |
| Frequency-based bit allocation | Frequently read rows have the same distribution (read-weighted kurtosis), so equal rate gives equal relative error (LongCat: .0737 unread vs .0722 for 10–99 reads). | (S) Qwen, KL with / without tiers: trellis codes at 2.6/2.1/1.6 bpp by read count vs the 2-bit code alone, same mean rate: top tier 35% of rows (89% of web reads) 1.044 [1.016, 1.076]; web .915, code 1.074, multilingual 1.092–1.123. With top tier 10% of rows (72% of web reads) 1.012 [.980, 1.046]; web .929, code 1.027, multilingual 1.016–1.048. (E) Scalar code, 2.1 bpp, vs the same code at a uniform rate: web .0853 vs .1030 ( 17%), but 1.33–1.44 higher on code, Chinese and Japanese. | (S) Shared benchmark (six domains; token counts in Appendix A ), 2.10 bpp. (E) Separate evaluation (131,071 web tokens, plus code, Chinese, Japanese). |
| Start-of-sequence row protection | Protection tests whether repeatedly accessed start rows warrant additional precision. | Rows read at every sequence start kept at original precision (DeepSeek 24 per Engram layer, LongCat 27,811). KL ratio vs CP: DeepSeek .999 [.995, 1.002] (random-row control 1.000 [1.000, 1.000]); LongCat .991 [.988, .993] (control .999 [.997, 1.001]). | Shared benchmark (six domains; token counts in Appendix A ), on top of CP at 2.06 bpp. |
| Step | DeepSeek | Qwen | LongCat |
|---|---|---|---|
| Top-35% tiers / uniform | 1.010 | 1.044 | 1.006 |
| [1.000, 1.020] | [1.016, 1.076] | [.995, 1.017] | |
| Top-10% tiers / uniform | .991 | 1.012 | – |
| [.985, .997] | [.980, 1.046] | ||
| Start rows / uniform | – | 1.008 | – |
| [.980, 1.039] |
| Tier | Who needs it | What 2 bpp changes (measured) | What it does not change |
|---|---|---|---|
| GPU HBM, 4 GPUs | RL rollouts and public inference code that keep the table on the GPU | FP8 needs 50.7 GB/GPU and runs out of memory at decode batch 512 and at 64k-token prefill; in the representative setting its prefill takes 64.66 2.49 s (peak 147.0 GB). NVFP4 (27.6 GB/GPU) runs both, but its 64k-token prefill step takes 59.81 4.75 s. CP needs 12.7 GB/GPU, runs every workload, and prefills in 13.27 0.22 s (peak 109.5 GB) and 64k tokens in 18.23 0.01 s. | Decode step time (795.7 vs. 792.9 ms, representative setting) and prefill steps up to 16k tokens (within 0.9%). Prefill slows when a large table leaves little HBM (left). |
| GPU HBM, 8 GPUs | Same, with the model spread over a full node | Both fit (25.3 vs. 6.3 GB/GPU); CP leaves 19.0 GB/GPU more for KV cache and raises the per-step ceiling from decode batch 1024 to 2048 and from 96k to 128k prefill tokens. | Step time (within 2.4% at every point both ran). |
| Host DRAM | Several model replicas per node; hosts with little RAM | Table size: 202.7 50.7 GB; Peak node RSS 225 75 GB. Lookup alone at 64k tokens: 53.5 19.4 ms. Smallest host that holds the table (calc.): 256 GB 64 GB. | End-to-end time: the lookup is 0.8% of a forward step. |
| SSD | DRAM smaller than the table (long tail on SSD) | Nothing per read: each row is one 4 KB read in both formats, 48 reads per decoded token. | Lookup latency; with prefetch the exposed lookup at 16k-token prefill is 2.7 ms (FP8) and 1.5 ms (CP), vs. 199.2 ms without. |
| Hot-row cache (HBM) + SSD | Same, with spare HBM | At 12.9 GB the cache serves 50.6% 70.7% of reads; a 51.5 GB cache holds the whole 50.7 GB CP table and serves 100% of reads (FP8 rows: 70.7%). Simulated SSD reads/token at 32 GB: 19.4 2.7. | Decode still misses every step (FP8 with 12.9 GB cache: 20.8 SSD reads/token at batch 64), so the off-GPU round trip stays on the critical path. |
| HBM (ms) | DRAM (ms) | |||
| Layout | KB/token | decode | prefill | prefill |
| Rows (CP) | 3.2 | 0.0357 | 0.228 | 6.70 |
| Tiles, whole tile | 50.7 ( ) | 0.133 | 3.64 ( ) | 9.90 ( ) |
| + Hadamard, 256 rows | 811 ( ) | 1.66 | 101 ( ) | 187 ( ) |
| Fused gather and decode: mean of run medians | ||||
| Rows (CP) | 3.2 | 0.0252 | 0.19 | 6.54 |
| Tier | Capacity (node) | Bandwidth (measured) | Read unit | Latency | Lookup, 64k tok (ms) FP8 CP | What compression changes |
|---|---|---|---|---|---|---|
| GPU HBM | 1,128 GB (8 H200) | 4,579 GB/s read per GPU | 64 B a | – | 9.70 3.23 b | Whether the table fits next to the model weights. |
| DRAM | 2 TB | STREAM triad 191–315 GB/s c ; host GPU 55.2 GB/s | 64 B a | 1.16 s (PCIe round trip) | 53.5 19.4 | Host RAM per replica (202.7 50.7 GB) and PCIe traffic (12.7 3.2 KB per token). |
| Local SSD | 6 NVMe, RAID-0 | 4 KB random 2.56M IOPS; 64 KB reads 40 GB/s | 4 KB | 91 s (QD1) | 1,243 1,048 | Nothing on the read path: one 4 KB read per row in every format (16k-token prefill: reads 232 vs 228 ms). The gap is CPU-side row extraction (15.2 vs 1.0 ms). More rows fit in the same cache. |
| No rotation | Rotation | ||||
|---|---|---|---|---|---|
| Model | QTIP | +BOS | +top-100 | QTIP | +top-100 |
| E2B | .106 | .031 | .027 | .033 | .026 |
| E2B-it | .227 | .198 | .140 | .126 | .123 |
| E4B | .162 | .030 | .028 | .029 | .026 |
| E4B-it | .067 | .067 | .061 | .059 | .056 |
| 3n-E4B | .108 | .109 | .105 | .123 | .116 |