~/fba-lab/lab/qwen-c/03-buffers

FBALab

Code · architecture · study mode

AboutRoadmapSpeedrun
FBALab

Study mode — no GPU required.

Interactive LLM training & inference lab.

Qwen CAboutContactTermsPrivacyCookiesCommunity

© 2026 FBA Lab

Contact · contact@bubblspace.com · +91 75061 55016

INFERENCE SIMULATION

Qwen3 Pure C — 3 · Buffers

running
◷run_viz.c▸Scratch buffers◎learner⌁03-buffers$no GPU
weights
Load the model
The 4 GB weight file is mapped into memory in milliseconds. No copying — the OS pages in only what inference needs.
run_viz.c · stage 01–02
load
active
runtime
Run inference
Your prompt flows through 28 layers of attention and computation, one token at a time.
stage 03–04
forward
output
Generate text
The model scores all 151,936 possible next words and picks one. Then repeats.
stage 05–06
1/4
Blocks
Quick summary

Every time the model processes a token, it needs temporary workspace — these buffers are that workspace, allocated once at startup and reused for every single token without ever being reallocated.

Full explanation below the code →

fba-lab — run_viz.c · Scratch buffersexecuting
$ calloc(dim) × scratch buffersx, xb, hb, q, k, v, att, logitsper-forward arena allocated ✓
Explanation

Processing a token requires a lot of intermediate calculations — normalizing activations, projecting into query/key/value space, computing attention scores, running through the FFN. Each of these produces numbers that are only needed for that one token's processing. Allocating and freeing fresh memory for each token would be slow and fragmented. Instead, malloc_run_state() allocates a set of reusable buffers once at startup. Every token reuses the same memory — the previous values are simply overwritten.

What each buffer does in plain English: - x holds the current token's representation as it flows through each layer (1024 numbers — the "residual stream") - xb, xb2, xb3 are temporary copies of that representation used during normalization and attention - q, k, v hold the query, key, and value projections for the current layer - att holds the attention scores — how much each past position contributes to the current one - logits is the final output — 151,936 scores, one per possible next token - hb and hb2 are FFN workspace — they hold the expanded intermediate representation during the FFN's up-projection step

All buffers are calloc'd (zero-initialized) rather than malloc'd. This ensures clean starting state for debugging and prevents mysterious failures from uninitialized memory.

Why it matters

Reusing scratch avoids malloc/free per token — allocation happens once at startup.

Think about

Why allocate all these buffers once at startup rather than fresh for each token?

// architecture

Live diagram

100%
Per-forward scratch (reused each token)x / xb / hbdimq / k / vattn dimsattn_heads×seqlogitsvocabPersistent KV cachekey_cachen_layers × seq × kv_dimvalue_cachesame shapecalloc guardexit on failfree_run_stateteardown
← 2 · Load weights4 · Forward pass →
Step 3 of 10Skill: Model & Memory
01Blueprint02Load weights03Buffers04Forward pass05Tokenizer06Generate loop07GEMV, not GEMM08Every op a kernel09Attention & memory10Prefill vs decode