Skip to main content

How Much GPU Memory Does NexusQuant Actually Save?

A concrete memory calculator: real GB numbers for A100, A10G, RTX 3090, with Python code for any model.

Published 5 min readMarkdown

How Much GPU Memory Does NexusQuant Actually Save?

KV cache compression numbers like "10x" sound impressive in a paper. But what does that mean in practice, for a real GPU, serving real users? Let me give you a concrete memory calculator so you can answer this for your own setup.

The KV Cache Formula

For any transformer, the KV cache size is:

KV_bytes = 2 × num_layers × num_heads × head_dim × seq_len × bytes_per_element

The 2 is for keys AND values. bytes_per_element is 2 for FP16, 4 for FP32.

For Mistral-7B (32 layers, 8 KV heads, head_dim=128, FP16):

KV_bytes = 2 × 32 × 8 × 128 × seq_len × 2
         = 131,072 × seq_len bytes
         ≈ 128 KB per token

At 128K tokens: 128 KB × 131,072 = 16.7 GB just for the KV cache.

GPU Memory Table

Here's what that means on real hardware:

GPUVRAMMax KV tokens (FP16, no NQ)With NexusQuant 10xWith NexusQuant 17xWith NexusQuant 33x
RTX 309024 GB~150K~1.5M~2.6M~5M
A10G24 GB~150K~1.5M~2.6M~5M
A100 40GB40 GB~256K~2.6M~4.4M~8.5M
A100 80GB80 GB~512K~5.1M~8.7M~17M
H100 80GB80 GB~512K~5.1M~8.7M~17M

Numbers leave 8 GB headroom for model weights and activations on 7B models.

Practical Scenarios

Scenario A: A10G serving 128K context

Without NexusQuant: 128K × 128 KB = 16.7 GB. With only 24 GB total and ~14 GB for the 7B model, you're OOM before the first token generates.

With NexusQuant 17x preset: 16.7 / 17 = 0.98 GB for KV. Fits comfortably. You can now serve 128K context on a single A10G.

Scenario B: A100 80GB, maximize throughput

A single request at 128K takes 16.7 GB KV. With 80 GB total and ~14 GB for weights, you have ~66 GB for KV — enough for about 4 concurrent sessions at 128K.

At 17x compression, each session uses ~1 GB of KV. You can serve ~66 concurrent sessions instead of 4. That's 16x more users per GPU.

Scenario C: Long context research

You want 1M token context on Mistral-7B. KV cache = 1M × 128 KB = 128 GB. Impossible on a single GPU.

At 17x: 7.5 GB. Fits on a single A100 40GB alongside the model weights.

Python Calculator

def kv_cache_gb(
    num_layers: int,
    num_kv_heads: int,
    head_dim: int,
    seq_len: int,
    dtype_bytes: int = 2,  # FP16
) -> float:
    """Returns KV cache size in GB."""
    total_bytes = 2 * num_layers * num_kv_heads * head_dim * seq_len * dtype_bytes
    return total_bytes / (1024 ** 3)


def savings_report(model_name: str, num_layers: int, num_kv_heads: int,
                   head_dim: int, seq_len: int, gpu_vram_gb: float,
                   model_weights_gb: float) -> None:
    base_gb = kv_cache_gb(num_layers, num_kv_heads, head_dim, seq_len)
    available = gpu_vram_gb - model_weights_gb

    print(f"\n=== {model_name} @ {seq_len:,} tokens ===")
    print(f"Base KV cache: {base_gb:.1f} GB")
    print(f"GPU available for KV (after weights): {available:.0f} GB")

    for ratio, label in [(10, "high quality"), (17, "balanced"), (33, "max")]:
        compressed_gb = base_gb / ratio
        concurrent = int(available / compressed_gb)
        fits = "YES" if base_gb / ratio < available else "NO"
        print(f"  {ratio}x ({label}): {compressed_gb:.2f} GB | fits={fits} | concurrent sessions={concurrent}")


# Mistral-7B examples
savings_report("Mistral-7B", 32, 8, 128, 128_000, 80, 14)
savings_report("Mistral-7B", 32, 8, 128, 1_000_000, 80, 14)

# Llama-3-8B
savings_report("Llama-3-8B", 32, 8, 128, 128_000, 40, 16)

# Llama-3-70B (multi-GPU: assume 160 GB total)
savings_report("Llama-3-70B", 80, 8, 128, 128_000, 160, 140)

Sample output:

=== Mistral-7B @ 128,000 tokens ===
Base KV cache: 16.7 GB
GPU available for KV (after weights): 66 GB
  10x (high quality): 1.67 GB | fits=YES | concurrent sessions=39
  17x (balanced): 0.98 GB | fits=YES | concurrent sessions=67
  33x (max): 0.51 GB | fits=YES | concurrent sessions=129

=== Mistral-7B @ 1,000,000 tokens ===
Base KV cache: 130.4 GB
GPU available for KV (after weights): 66 GB
  10x (high quality): 13.04 GB | fits=YES | concurrent sessions=5
  17x (balanced): 7.67 GB | fits=YES | concurrent sessions=8
  33x (max): 3.95 GB | fits=YES | concurrent sessions=16

=== Llama-3-8B @ 128,000 tokens ===
Base KV cache: 16.7 GB
GPU available for KV (after weights): 24 GB
  10x (high quality): 1.67 GB | fits=YES | concurrent sessions=14
  17x (balanced): 0.98 GB | fits=YES | concurrent sessions=24
  33x (max): 0.51 GB | fits=YES | concurrent sessions=47

The Model Weight Overhead

One thing papers often gloss over: the model itself takes memory. Here are real-world numbers:

ModelWeights (BF16/FP16)
TinyLlama-1.1B2.2 GB
Mistral-7B14 GB
Llama-3-8B16 GB
Llama-3-70B140 GB (2× A100 80GB)
Llama-3-405B~810 GB

At 70B+, KV cache compression becomes less about fitting the model and more about fitting the context. A 70B model with 128K context uses only ~2x its own weight in KV cache. NexusQuant is still valuable here, but the math changes — you're extending context headroom, not primarily enabling the model to load.

What We Measured

All numbers in NexusQuant are validated with torch.cuda.memory_allocated() before and after cache materialization. No estimate-only ratios. The paper's compression column includes all overhead: scales (FP16), lattice indices (packed uint8), and metadata. If it's not in memory, it's not in the ratio.

Repo: github.com/jagmarques/nexusquant

pip install nexusquant-kv
from nexusquant import nexusquant_evict

with nexusquant_evict(model, quality="balanced"):  # 17x
    output = model.generate(input_ids, max_new_tokens=512)

Best regards, João Marques

About the author

  • Founder of Asqav. Building AI agent governance - audit trails, policy enforcement, and compliance for autonomous AI systems.

No comments yet. Be the first to comment.

More from this blog