Comparison intermediate · 6 min read

bitsandbytes vs GPTQ: quantization for local LLM inference

Quick pick

Use bitsandbytes if you want dynamic quantization (8-bit, 4-bit NF4) with minimal setup overhead on any GPU. Use GPTQ if you need maximum speed and the smallest memory footprint with pre-quantized weights.

VERDICT

Use bitsandbytes for flexibility and ease: it quantizes models on-the-fly with one-line integration and works across NVIDIA/AMD/Intel GPUs. Use GPTQ if you prioritize inference speed and token throughput: GPTQ is 15-25% faster per token and reduces memory by 40-50% vs 8-bit quantization, but requires pre-quantized model weights and longer initialization. For production serving to multiple users, GPTQ wins on latency by 2-3x. For rapid experimentation or fine-tuning, bitsandbytes is faster to deploy.

Side-by-side comparison

DimensionbitsandbytesGPTQWinner
Quantization method Dynamic (int8, nf4, fp4) Static pre-quantized (int4, int3) GPTQ
Memory per 7B model ~5.5GB (8-bit), ~3.5GB (4-bit NF4) ~2.5GB (int4, GPTQ) GPTQ
Throughput (A100, tok/s) ~400-600 tok/s ~600-900 tok/s GPTQ
Setup complexity pip install + 1 line code change Download pre-quantized weights + integration bitsandbytes
Fine-tuning support Yes (QLoRA compatible) No (weights are frozen) bitsandbytes
GPU compatibility NVIDIA, AMD, Intel (broad) NVIDIA only (cuda-dependent) bitsandbytes
Supported frameworks Hugging Face Transformers, bitsandbytes standalone AutoGPTQ, GPTQ-for-LLaMA, vLLM Tie
Time to first token (7B) ~150-200ms ~80-120ms GPTQ
License MIT MIT Tie
Pre-quantized models available No (quantize at runtime) Yes (Hugging Face, 100+ models) GPTQ

Performance benchmarks

Inference throughput (Llama 2 7B, A100 40GB)

bitsandbytes ~500 tok/s (4-bit NF4)
GPTQ ~750 tok/s (GPTQ int4)

GPTQ achieves 50% higher throughput due to integer-only arithmetic and pre-optimized kernel usage. Bitsandbytes uses software quantization during forward pass.

Memory footprint (Llama 2 7B)

bitsandbytes ~3.5GB (NF4), ~5.5GB (int8)
GPTQ ~2.5GB (GPTQ int4)

GPTQ saves ~30% memory vs NF4, ~55% vs int8. Trade-off: GPTQ weights are immutable; bitsandbytes allows fine-tuning.

Model loading time (first inference, 7B)

bitsandbytes ~2-5 seconds (quantization on-the-fly)
GPTQ ~8-15 seconds (GPTQ weight loading + kernel setup)

bitsandbytes quantizes during load; GPTQ pre-quantized weights are larger and slower to deserialize. After warmup, GPTQ is faster per token.

Accuracy loss (Llama 2 7B, MMLU benchmark)

bitsandbytes ~1-2% (int8), ~2-3% (NF4)
GPTQ ~1-2% (GPTQ int4)

Both introduce negligible task loss. GPTQ uses Hessian-aware quantization; bitsandbytes 4-bit uses normalized float (NF4) which is similarly calibrated.

When to use each

bitsandbytes
  • ✓ You're fine-tuning with LoRA/QLoRA and need quantized base weights: bitsandbytes is QLoRA-native and handles gradient updates seamlessly.
  • ✓ You're experimenting with different models rapidly: bitsandbytes quantizes any Hugging Face model on-the-fly without hunting for pre-quantized variants.
  • ✓ You use AMD or Intel GPUs: bitsandbytes supports ROCm and oneAPI; GPTQ is CUDA-only.
  • ✓ You need maximum flexibility: bitsandbytes can switch quantization schemes (8-bit vs 4-bit NF4) without re-downloading weights.
  • ✓ You want simple deployment: 'pip install bitsandbytes' + model_id is all you need; no pre-quantized weight hunting.
GPTQ
  • ✓ You're serving 50+ concurrent inference requests: GPTQ's 50% throughput advantage makes a 2-3 second response SLA achievable.
  • ✓ Memory is your hardest constraint: GPTQ int4 uses 40-50% less VRAM than bitsandbytes 8-bit, critical on 8GB or 16GB GPUs.
  • ✓ You need sub-100ms time-to-first-token latency for interactive applications (chat, autocomplete): GPTQ achieves ~80ms vs bitsandbytes' ~150ms.
  • ✓ You're using vLLM or TensorRT-LLM in production: both have native GPTQ optimizations and hand-tuned kernels; bitsandbytes integration is slower.
  • ✓ Your model is in the GPTQ hub and you want battle-tested quantization: pre-quantized weights are audited across thousands of deployments.

Common misconceptions

bitsandbytes

✗ bitsandbytes NF4 (4-bit) is as fast as GPTQ int4

✓ bitsandbytes 4-bit uses software dequantization during every forward pass (2-3 GPU cycles per token). GPTQ int4 keeps data in int4 format through the entire compute graph, achieving 50% higher throughput. Speed difference compounds at batch size >1.

✗ bitsandbytes works seamlessly on all GPUs

✓ bitsandbytes requires NVIDIA CUDA Compute Capability 3.5+. AMD GPU support via ROCm has limited kernel coverage (some ops fall back to slow paths). Intel GPU support is experimental. Always test on your target hardware.

✗ bitsandbytes 8-bit is suitable for production inference servers

✓ int8 quantization adds 20-30% overhead vs fp16 due to frequent dequantization. For high-throughput serving, GPTQ or int4 is required to stay under latency SLAs. Use 8-bit for fine-tuning, not inference at scale.

GPTQ

✗ GPTQ weights are drop-in replacements for full-precision models

✓ GPTQ models must be loaded via AutoGPTQ or specific integrations (not standard from_pretrained()). You must use compatible inference code; naive implementations will see 5-10% accuracy drops or slower inference than claimed benchmarks.

✗ All GPTQ models on Hugging Face are equally fast

✓ GPTQ speedup depends on the quantization group size (gs), activation order, and target hardware. gs=128 is much slower than gs=32. AutoGPTQ + vLLM with flash-attention gives 3-5x the speed of naive GPTQ loading. Check model cards for group size and kernel optimization details.

✗ GPTQ is production-ready without tuning

✓ GPTQ requires proper calibration dataset (~100-1000 examples from the target domain). Generic quantization produces 2-5% accuracy loss on niche tasks. Recalibration is common in production.

Code examples

Task: Load a 7B LLM with 4-bit quantization and run inference.

bitsandbytes: quantized inference with QLoRA setup
python
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

# Configure 4-bit NF4 quantization via bitsandbytes
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_quant_type="nf4",  # Normalized Float 4-bit
    bnb_4bit_use_double_quant=True,  # Double quantization for even more compression
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b",
    quantization_config=bnb_config,  # bitsandbytes quantizes on-the-fly
    device_map="auto",
)

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b")
inputs = tokenizer("What is machine learning?", return_tensors="pt")
outputs = model.generate(**inputs, max_length=50)
print(tokenizer.decode(outputs[0]))

bitsandbytes quantizes the model as it loads: no pre-quantized weights needed. The NF4 config is applied in from_pretrained(), making this a one-config integration.

GPTQ: inference with pre-quantized weights
python
from transformers import AutoModelForCausalLM, AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM

# Load pre-quantized GPTQ model (weights are already quantized)
model = AutoGPTQForCausalLM.from_quantized(
    "TheBloke/Llama-2-7B-GPTQ",  # Must use GPTQ-quantized model repo
    use_safetensors=True,
    device="cuda:0",
    use_triton=True,  # Optional: faster kernels, requires Triton
)

tokenizer = AutoTokenizer.from_pretrained("TheBloke/Llama-2-7B-GPTQ")
inputs = tokenizer("What is machine learning?", return_tensors="pt")
outputs = model.generate(**inputs, max_length=50)
print(tokenizer.decode(outputs[0]))

GPTQ loads pre-quantized weights via AutoGPTQForCausalLM: no dynamic quantization. Requires models explicitly quantized with GPTQ (e.g., TheBloke variants). Slower loading but faster inference.

Migration path

  1. Switching from bitsandbytes to GPTQ:
  2. Download a pre-quantized GPTQ model (TheBloke repo or similar) matching your base model.
  3. Replace BitsAndBytesConfig with AutoGPTQForCausalLM.from_quantized().
  4. Change from_pretrained() → from_quantized(); update device_map logic.
  5. If using QLoRA, note GPTQ weights cannot be fine-tuned: freeze GPTQ and apply LoRA adapters if needed.
  6. Test inference speed: expect 50% throughput gain but ~2-3x longer model load time. Switching from GPTQ to bitsandbytes:
  7. Remove AutoGPTQForCausalLM and AutoGPTQ imports.
  8. Replace with standard from_pretrained() + BitsAndBytesConfig.
  9. Use base model repos (meta-llama, mistralai) instead of GPTQ forks.
  10. Accept 30-50% lower throughput but regain fine-tuning flexibility.
  11. No model re-download needed: quantization happens at runtime.

RECOMMENDATION

Use bitsandbytes for flexible, rapidly-iterated workloads (fine-tuning, multi-model experiments, AMD/Intel GPUs). Use GPTQ for production inference at scale: the 50% throughput gain and smaller memory footprint justify the pre-quantized model requirement and longer setup. For teams needing both, use bitsandbytes for development and switch to GPTQ-quantized versions at the inference gateway.
Verified 2026-04
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.