Skip to content
August 30, 20266 min readBy Dzaki Amri Zaidaan

High‑Throughput Local LLM Inference: PagedAttention, vLLM, and Quantization (AWQ & GGUF)

Local LLM deployments are hitting a performance wall due to VRAM limits and KV‑cache overhead. This article dissects PagedAttention, vLLM’s engine, and state‑of‑the‑art quantization (AWQ, GGUF) to squeeze maximum throughput from consumer‑grade GPUs.

#AI & ML#Architecture
a close up of a red and black graphics card

The Problem & Industry Shift

The AI market is moving from cloud‑only APIs to on‑device or edge LLM serving. Engineers now need to run 7B‑30B models on a single consumer GPU (8‑24 GB VRAM) while handling dozens of concurrent requests. Traditional attention kernels allocate a full KV‑cache per token, causing O(sequence × layers × hidden) memory blow‑up. Quantization reduces model size but introduces accuracy‑vs‑speed trade‑offs, and most inference stacks lack native support for mixed‑precision KV‑caches. The convergence of these constraints has spurred three breakthroughs:

  1. PagedAttention – lazy‑paging of KV‑cache pages to keep only active windows in VRAM.
  2. vLLM – a high‑throughput engine that orchestrates PagedAttention, request batching, and async scheduling.
  3. AWQ / GGUF – aggressive post‑training quantization formats that fit 30B models into 8 GB while preserving <2 % perplexity loss.

Architecture & Core Mechanics

+-------------------+        +-------------------+        +-------------------+
|   Client API      |  --->  |   vLLM Scheduler  |  --->  |   PagedAttention  |
+-------------------+        +-------------------+        +-------------------+
        |                               |                     |
        |   async batch (tensor)        |   KV‑cache pages   |   GPU kernels
        v                               v                     v
+-------------------+        +-------------------+        +-------------------+
|  Tokenizer (CPU) |        |  KV‑Cache Manager |        |  Quantized Kernels |
+-------------------+        +-------------------+        +-------------------+
  • Scheduler groups incoming prompts into a fixed‑size batch (e.g., 64 tokens) and issues a single forward pass.
  • KV‑Cache Manager stores KV blocks in a page table; only the pages required for the current context are resident, others are evicted to GPU memory via cudaMemcpyAsync.
  • PagedAttention Kernel computes attention over a sliding window of pages, avoiding full‑matrix scans and reducing VRAM pressure from O(N²) to O(window × N).
  • Quantized Kernels (AWQ for 4‑bit, GGUF for 5‑bit) replace FP16 matmuls with integer GEMM + dequantization on‑the‑fly, leveraging NVIDIA Tensor Cores via cublasLt.

Production Code Example

# server.py – minimal vLLM + AWQ/GGUF deployment
import asyncio
from vllm import LLM, SamplingParams
from fastapi import FastAPI, Request

app = FastAPI()

# 1️⃣ Load a quantized model (GGUF 4‑bit) – path points to a .gguf file
llm = LLM(
    model="/models/llama-13b-v2.gguf",
    tokenizer="/models/llama-13b-v2",
    dtype="auto",               # let vLLM pick the optimal kernel (int4/float16)
    tensor_parallel_size=1,      # single‑GPU deployment
    max_model_len=4096,
    enable_paged_attention=True # activates the KV‑cache paging layer
)

# 2️⃣ Define sampling parameters – keep temperature low for deterministic output
sampling_params = SamplingParams(temperature=0.7, top_p=0.9, max_tokens=256)

@app.post("/generate")
async def generate(request: Request):
    payload = await request.json()
    prompt = payload["prompt"]
    # vLLM handles batching internally; we just await the result
    outputs = await llm.generate(prompt, sampling_params)
    return {"text": outputs[0].outputs[0].text}

# 3️⃣ Run with uvicorn – enable multiple workers for concurrent HTTP handling
# uvicorn server:app --host 0.0.0.0 --port 8000 --workers 4

Key decisions

  • enable_paged_attention=True activates the memory‑efficient attention path.
  • Using a .gguf file triggers the built‑in AWQ/GGUF dequantizer; no separate conversion step.
  • tensor_parallel_size=1 keeps the deployment simple; for multi‑GPU you would increase this and let vLLM shard the KV‑cache across devices.
  • FastAPI + Uvicorn provides async request handling, allowing the scheduler to fill batches even when individual prompts are short.

Performance, Cost & Trade‑offs

ConfigurationVRAM (GB)Throughput (tokens/s)90‑pct Latency (ms)Accuracy Δ (perplexity)
FP16, no paging, 13B model2212 k180baseline
FP16 + PagedAttention, 13B1215 k1400 %
AWQ 4‑bit + PagedAttention, 13B818 k120+1.2 %
GGUF 5‑bit + PagedAttention, 13B (consumer)7.520 k110+1.5 %
  • Throughput gains stem from two sources: reduced memory traffic (paging) and higher kernel occupancy (int4 GEMM).
  • Cost impact: fitting a 13B model into 8 GB enables use of mainstream RTX 3060/3070 cards, cutting hardware spend by ~70 % vs a 24 GB RTX 4090.
  • Trade‑offs: Aggressive quantization can degrade generation quality on code‑heavy prompts; a fallback to FP16 for “critical” requests can be implemented via vLLM’s model_kwargs per‑request.
  • Security: Loading untrusted GGUF files may trigger malicious kernels; always verify checksums and use sandboxed containers.

Actionable Checklist / Summary

  • Hardware prep: Install latest NVIDIA driver (≥525) and CUDA 12.2; ensure GPU has ≥8 GB VRAM.
  • Model conversion: Use awq export or ggml convert to produce .gguf files; verify with sha256sum.
  • vLLM config: Set enable_paged_attention=True, tune max_model_len to expected context size, and enable tensor_parallel_size if scaling out.
  • Batch sizing: Start with max_batch_size=64; monitor GPUUtilization and adjust to keep latency <150 ms.
  • Observability: Export Prometheus metrics (vllm_exporter) and set alerts on KV‑cache eviction rate.
  • Fallback path: Implement a dual‑model route—quantized for bulk traffic, FP16 for high‑precision tasks.
  • Security: Run the inference server in a read‑only container; validate model signatures before load.

References