<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brandon Brooks</title>
    <description>The latest articles on DEV Community by Brandon Brooks (@brandon_brooks_51075f6d22).</description>
    <link>https://dev.to/brandon_brooks_51075f6d22</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2319090%2F1d521e5c-471c-45bb-8e0b-ffc15f2f5a44.jpg</url>
      <title>DEV Community: Brandon Brooks</title>
      <link>https://dev.to/brandon_brooks_51075f6d22</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brandon_brooks_51075f6d22"/>
    <language>en</language>
    <item>
      <title>Budgeting memory for a local language model: weights, KV cache, and room to run</title>
      <dc:creator>Brandon Brooks</dc:creator>
      <pubDate>Sun, 18 Oct 2026 00:01:51 +0000</pubDate>
      <link>https://dev.to/brandon_brooks_51075f6d22/budgeting-memory-for-a-local-language-model-weights-kv-cache-and-room-to-run-397f</link>
      <guid>https://dev.to/brandon_brooks_51075f6d22/budgeting-memory-for-a-local-language-model-weights-kv-cache-and-room-to-run-397f</guid>
      <description>&lt;p&gt;An “8B, 4-bit” label gives you a starting estimate for weight storage. A useful memory budget also needs the conversation cache, the runtime's allocations, and the workload you intend to serve.&lt;/p&gt;

&lt;p&gt;Here is a calculation you can adapt before downloading weights or choosing a context length. The numbers below are arithmetic estimates, not measurements of a running model.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with the weight payload
&lt;/h2&gt;

&lt;p&gt;For P scalar parameters stored uniformly at b bits each:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;weight bytes = P × b / 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A hypothetical model with exactly 8 billion parameters would have these idealized payloads:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16 bits: 16,000,000,000 bytes ≈ 14.90 GiB
 8 bits:  8,000,000,000 bytes ≈  7.45 GiB
 4 bits:  4,000,000,000 bytes ≈  3.73 GiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;One GiB is 2^30 bytes; one decimal GB is 10^9 bytes. Keep units consistent when comparing a download, a memory monitor and a hardware specification.&lt;/p&gt;

&lt;p&gt;Those figures assume every parameter uses the same representation. Real quantized artifacts can include scales, other metadata and tensors retained at higher precision. For example, the Transformers bitsandbytes documentation distinguishes quantized linear layers from other modules and separates weight storage from compute dtype. Check the exact artifact and runtime rather than treating every “4-bit” label as an identical format. [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Add the conversation's KV cache
&lt;/h2&gt;

&lt;p&gt;During autoregressive generation, a transformer can reuse previously computed keys and values. The cache contains per-layer tensors and grows with the cached sequence. [2]&lt;/p&gt;

&lt;p&gt;For conventional full-attention decoder layers with equal key and value head dimensions, an uncompressed cache estimate is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KV bytes = 2 × L × Hkv × D × T × C × S

2   = keys and values
L   = attention layers
Hkv = key/value heads per layer
D   = dimension per key/value head
T   = cached tokens per sequence, including processed prompt and output
C   = bytes per cached element (2 for FP16/BF16)
S   = independently stored sequences of that length
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Use KV heads, not query heads. For differing sequence lengths, sum the token counts; the simple multiplication assumes equal lengths and no shared prefix storage. Beam search or concurrent requests can introduce more independently cached sequences.&lt;/p&gt;

&lt;p&gt;The official Qwen/Qwen3-8B config lists 36 layers, 8 KV heads and head dimension 128, with sliding-window attention disabled. [3] At 8,192 cached tokens, two-byte cache elements and one sequence, the calculation is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 × 36 × 8 × 128 × 8,192 × 2 × 1
= 1,207,959,552 bytes
= 1.125 GiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Under those same assumptions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4,096 tokens, one sequence: 0.5625 GiB
8,192 tokens, one sequence: 1.1250 GiB
16,384 tokens, one sequence: 2.2500 GiB
8,192 tokens, four independent sequences: 4.5000 GiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;These are tensor payload estimates. They do not establish total memory use, speed or whether a particular machine can run the checkpoint.&lt;/p&gt;

&lt;p&gt;The formula needs adjustment for other architectures and cache implementations. Sliding-window layers may retain a bounded window. Static caches can reserve their configured maximum, while dynamic caches grow with use. Cache quantization and offloading change memory placement and precision, with performance tradeoffs. Weight quantization does not automatically set the KV-cache dtype. Check your backend's supported cache behavior. [4]&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Leave room for execution and loading
&lt;/h2&gt;

&lt;p&gt;A planning worksheet is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resident weights + KV cache + runtime/workload overhead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Check both loading and generation peaks. Accelerate's documentation describes how loading can create extra weight copies, how sharded loading can reduce that pressure, and how CUDA initialization consumes memory beyond the weights. CPU or disk offload changes placement and introduces transfers; fitting with offload does not establish acceptable latency. [5]&lt;/p&gt;

&lt;p&gt;For your runtime, inspect temporary workspaces, prefill allocations, allocator reservations and any additional models or modalities. There is no universal overhead percentage in this worksheet. Measure the exact workload and retain headroom for its observed peaks and other processes.&lt;/p&gt;

&lt;p&gt;On Apple silicon, MLX uses unified memory shared by CPU and GPU. [6] Budget that shared capacity once, leaving room for the operating system and other applications. Do not add the same unified pool once as RAM and again as VRAM.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Turn the estimate into a reproducible check
&lt;/h2&gt;

&lt;p&gt;Record the exact repository, checkpoint revision and quantization artifact; runtime version and backend; cache dtype and strategy; prompt/output token limits; and concurrent sequences. Start with a modest workload, then increase context and concurrency separately. Record loading peak, generation peak, time to first token and generation rate using the runtime's supported measurement tools. State how memory was measured, including whether it is allocated or reserved memory.&lt;/p&gt;

&lt;p&gt;This is a proposed measurement procedure. No results from it are presented here, and this article makes no “runs comfortably on my laptop” claim.&lt;/p&gt;

&lt;p&gt;Finally, inspect the license for the exact release. The official Qwen/Qwen3-8B repository used for the architecture example carries Apache License 2.0. [7] Do not generalize that license to another Qwen release, a conversion, or an unrelated model. Record the applicable model and runtime licenses alongside the revision and deployment configuration.&lt;/p&gt;

&lt;p&gt;The useful outcome is a budget whose assumptions you can change: shorter context reduces this conventional cache estimate; lower weight precision changes the weight budget; more independent sequences increase cache demand. The measurements then tell you where the estimate stops matching your actual runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;Primary documentation checked live 2026-10-17 UTC&lt;br&gt;
[1] &lt;a href="https://huggingface.co/docs/transformers/quantization/bitsandbytes" rel="noopener noreferrer"&gt;Transformers bitsandbytes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] &lt;a href="https://huggingface.co/docs/transformers/cache_explanation" rel="noopener noreferrer"&gt;Transformers cache structure&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] &lt;a href="https://huggingface.co/Qwen/Qwen3-8B/blob/main/config.json" rel="noopener noreferrer"&gt;Official Qwen3-8B config&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;File-history short revision displayed: 47719a2. Main is mutable; pin the exact full checkpoint revision when running an experiment.&lt;br&gt;
[4] &lt;a href="https://huggingface.co/docs/transformers/kv_cache" rel="noopener noreferrer"&gt;Transformers cache strategies&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] &lt;a href="https://huggingface.co/docs/accelerate/concept_guides/big_model_inference" rel="noopener noreferrer"&gt;Accelerate loading and placement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] &lt;a href="https://ml-explore.github.io/mlx/build/html/usage/unified_memory.html" rel="noopener noreferrer"&gt;MLX unified memory&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] &lt;a href="https://huggingface.co/Qwen/Qwen3-8B/blob/main/LICENSE" rel="noopener noreferrer"&gt;Exact example release license&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosure
&lt;/h2&gt;

&lt;p&gt;Prepared primarily by an AI agent for Brandon Brooks of Bright AI Future, from the primary sources linked above, and reviewed by Brandon. No model inference benchmarks were performed for this article.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
