kimi-k3-in-c: How a C99 Engine Turns RAM Into a Dial for a 2.78T-Parameter Model

A zero-dependency inference engine streams weights, caches experts, and keeps outputs reproducible, even when the model is far larger than memory.

8 to 10 min read View on GitHub More from FareedKhan-dev

A giant mechanical inference engine rises in stacked tiers, with a narrow compute deck above and a tall streaming storage rack below. A small RAM reservoir sits beside it like a control knob, showing that memory is a variable rather than a wall. The scene explains the project's core idea: scale is managed by moving weights through tiers on demand.
The engine does not try to fit the whole model in memory. It treats RAM, cache, and storage as a controllable ladder.
Key Takeaways

The headline feat is not just that Kimi K3 can run locally. It is that the engine reframes a 2.78T-parameter MoE model as a storage and scheduling problem, not a raw-memory problem. That shift is what makes the project interesting to systems people, not just local AI hobbyists.

The Model That Refuses to Fit

Kimi K3 ships as a checkpoint that would normally be too large to treat as a single resident object. `kimi-k3-in-c` accepts that constraint and makes it movable. The dense trunk streams from disk, the routed experts come and go through cache, and the output stays byte-identical across very different RAM budgets.

That is the core thesis: the project does not ask how to shrink the model until it fits. It asks how to control what must be resident, what can be prefetched, and what can stay on NVMe without changing the result.

The Memory Ladder, Not the Memory Floor

A token does not traverse one monolithic model blob. It moves through routing, cache lookup, streaming, and dequantization as separate steps that can be tuned independently.

The best way to understand the repo is as a ladder. Spend more RAM, and more of the hot path stays resident. Spend less RAM, and the engine leans harder on asynchronous I/O and streaming. The model's behavior does not change, but the shape of the pipeline does.

That is a more useful abstraction than a simple yes-or-no fit test. It turns the hardware question into a policy choice: how much memory do you want to buy back with latency?

The entire frontier MoE runs by streaming experts from disk. active experts get loaded. Everything else stays on NVMe. Byte-identical output whether you give it 8 GB or 224 GB, This shouldn't be possible yet it is.

Fareed Khan, Project Creator / AI Researcher · kimi-k3-in-c README

Inside the Trunk

The trunk is the dense part of the model, and it is the part most systems would rather avoid. In this repo, the trunk is streamed layer by layer from storage, with background prefetch hiding I/O behind compute. That matters because the trunk is big enough that a naive load strategy would dominate the whole runtime budget.

// Simplified shape of the trunk path
prefetch_next_layer_async(layer + 1);
run_current_layer(layer, activations);
wait_for_prefetch_if_needed(layer + 1);

// Dense weights never need to stay fully resident.
// The pipeline is built around overlap, not bulk loading.

This is why the project feels more like a storage engine than a traditional model runner. The unit of work is not just a tensor. It is a weight page arriving just in time for compute.

Inside the Expert Cache

The MoE side is where the sparsity pays off. Only 16 of 896 experts activate per token, so the engine can keep a small hot set in RAM and push the rest to disk. The LRU cache then becomes the real control surface for throughput.

A close-up of a routing mechanism selects a handful of drawers from a large grid of expert slots. Some drawers are lit and open in the foreground while most remain closed and dark, and a thin strip of dequantized weight tiles slides from storage into a compact compute chamber. The scene explains how sparse expert selection, caching, and on-the-fly dequantization work together.
The router only activates a small subset of experts, so cache policy matters almost as much as math kernel speed.
// Expert path, simplified
expert_id = route(token);
if (cache_hit(expert_id)) {
    weights = cache_get(expert_id);
} else {
    weights = stream_from_nvme(expert_id);
    cache_put_lru(expert_id, weights);
}
weights = dequantize_mxfp4(weights);
matmul_with_active_token(weights, hidden_state);

The important detail is that dequantization happens on the path to use, not as a separate staging step. That keeps bandwidth pressure down and avoids turning the cache into a second model loader.

Why the Math Has to Be Exact

The project is unusually strict about correctness. It uses configuration guards that refuse missing fields, disables floating-point contraction, and keeps double accumulators where precision could drift. The fast path and the scalar path are designed to agree, not merely to approximate each other.

That discipline changes the feel of the repo. It is not a demo that got lucky. It is an engineering artifact that treats reproducibility as part of the product.

// Conceptual invariants the engine protects
// 1. No guessing when config fields are missing.
// 2. No compiler-created FMA surprises.
// 3. No divergence between scalar and AVX2 reduction trees.
// 4. No silent changes in output when memory budgets change.

What It Is Better Than

The closest comparisons clarify the niche. `llama2.c` is the spiritual ancestor, but it lives in a far smaller world. AirLLM solves a neighboring problem on GPUs. WASTE and deltafin explore storage-bound inference too, but with different language choices and tradeoffs. `kimi-k3-in-c` sits in a very specific corner: CPU-first, C99, zero-dependency, exact-output inference for a frontier MoE model.

ProjectLanguageHardware targetWhat is streamedMain trickMain tradeoff
kimi-k3-in-cC99CPU, RAM-starved systemsDense trunk and routed expertsMemory as a dial, exact-output streaming, custom kernelsVery slow at the smallest RAM budgets
WASTECCPU and storage-bound systemsExperts and weightsStreaming plus aggressive compressionDifferent fidelity and speed profile
deltafinRustCPU-focused systemsModel weights and runtime stateSafer systems rewrite of the same ideaLess minimal than C, different runtime philosophy
llama2.cCSmall local setupsNo large-scale storage streamingUltra-minimal full-stack inferenceMuch smaller scale and model scope
AirLLMPython / GPU stackSmall GPU VRAMLayersLayer-wise offload on GPUsNot CPU-only, different bottleneck

The comparison does not crown a winner. It makes the category visible. This repo is what happens when you optimize for exactness, not just convenience.

Why This Repo Matters

`kimi-k3-in-c` argues that frontier inference is not always blocked by a single scarce resource. Sometimes the bottleneck is the discipline to move weights intelligently, keep math stable, and expose memory as a policy knob. That is a bigger lesson than one model, one machine, or one benchmark number.

If the project has a lasting contribution, it is this: it shows that a huge model can be treated as a pipeline of managed state. Once that clicks, RAM stops being a wall and starts being one more variable in the system.