main
md 145 lines 6.96 KB
Rendered Raw
1 # Engram: conditional memory via n-gram lookups
2
3 Engram is a *conditional memory* module attached to specific layers of a
4 transformer backbone. At each position, the preceding few tokens are hashed
5 into large static embedding tables, and the retrieved rows are fused into the
6 hidden state, gated by how well they match it. Where Mixture-of-Experts scales
7 capacity through conditional computation, Engram scales it through conditional
8 memory: parameters that are never computed over, only looked up, so capacity
9 grows at O(1) per-token cost. The mechanism and its design rationale are
10 described in [Conditional Memory via Scalable Lookup: A New Axis of Sparsity
11 for Large Language Models](https://arxiv.org/abs/2601.07372).
12
13 vLLM enables Engram automatically whenever the checkpoint declares Engram
14 layers, so basic serving needs no extra flags. This page explains what Engram
15 does and how to control its memory footprint and multi-GPU topology.
16
17 ## Supported models
18
19 Engram layers are declared by the checkpoint, not chosen at serve time:
20
21 | Architecture | HF config field | Notes |
22 | --- | --- | --- |
23 | `DeepseekV41ForCausalLM` | `engram_layer_ids` | e.g. `deepseek-ai/DeepSeek-V4.1-Flash` |
24 | `Qwen4ExpForCausalLM` / `Qwen4ExpForConditionalGeneration` | `ple_layer_ids` | same mechanism, called PLE |
25
26 Passing `--engram-config` for a model without n-gram embedding layers fails at
27 startup, as does running on a non-CUDA-alike platform.
28
29 ## How it works
30
31 Engram processes each position in two phases: *retrieval* and *fusion*.
32
33 **Retrieval** maps the local token context to static table rows:
34
35 1. **Tokenizer compression.** At startup, vLLM builds a many-to-one map from
36 the tokenizer that collapses tokens which normalize alike (NFKC, accent
37 stripping, lowercasing, whitespace collapsing), so `" The"`, `"the"` and
38 `"THE"` hash identically. This concentrates semantic density into a much
39 smaller id space; its size must match `engram_compressed_vocab_size` from
40 the checkpoint, or startup fails — every hash multiplier derives from it.
41 2. **Multi-head hashing.** For each n-gram order `n` (up to
42 `engram_max_ngram_size - 1`), several hash heads each apply an independent
43 multiplicative-XOR hash over the compressed suffix n-gram. Every (n-gram
44 order, head) pair indexes its own prime-sized bucket range in the layer's
45 table — disjoint across pairs, so collisions cannot collide twice — and
46 the retrieved rows are concatenated into one memory vector per position.
47
48 **Fusion** turns the retrieved rows into a context-aware contribution to the
49 hidden state. The rows are context-independent priors and may be noisy (hash
50 collisions, polysemy), so they are gated: a `wkv` projection produces one key
51 per hyper-connection branch plus a shared value, and each branch computes a
52 sigmoid gate over the normalized dot product between its hidden state —
53 which has already aggregated global context through preceding attention —
54 and its key. If the retrieved memory contradicts the current context, the
55 gate tends toward zero and suppresses it. The gated value is added
56 residually into the branch's stream (`hidden + gate * value`); positions that
57 take no part in an n-gram (e.g. image spans) are masked so they pass through
58 untouched.
59
60 Engram sits only on the layers listed in the checkpoint. Placement is a
61 deliberate hardware-algorithm trade-off: early enough that the backbone is
62 relieved from reconstructing static patterns in its first layers, deep enough
63 that vLLM can hide table lookups behind the compute of the preceding layers
64 (see below).
65
66 In vLLM, hashing, lookup, and gating run as fused Triton kernels over FP8
67 rows with ue8m0 block scales. The layer layout — table sizes, n-gram size,
68 head count — is fixed by the checkpoint and is not user-configurable. Only the
69 storage and sharding described below are configurable, via
70 `--engram-config`, which takes a JSON object and can also be set field by
71 field as `--engram-config.<field>`
72 ([CLI reference](../cli/serve.md#-engram-config)).
73
74 ## CPU offload
75
76 Engram tables dwarf typical embedding weights: [DeepSeek-V4.1-Flash](https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash)
77 carries two Engram layers of roughly 384M table rows each, with 256-byte FP8
78 entries plus their ue8m0 block scales — about 200 GB of table weights alone.
79 Because lookups are deterministic — the indices are known from the token ids
80 alone, before the forward pass — the tables need not sit in GPU memory at
81 all. By default vLLM stores them in **pinned host memory** and serves lookups
82 directly from the Triton kernel through unified virtual addressing (UVA),
83 prefetching on a side CUDA stream so transfers overlap with the compute of
84 preceding layers. The freed GPU memory goes to the KV cache.
85
86 `cpu_offload` defaults to `true` (on)
87
88 To keep the tables resident on GPU instead (e.g. when host memory is
89 scarce):
90
91 ```bash
92 vllm serve deepseek-ai/DeepSeek-V4.1-Flash \
93 --engram-config.cpu_offload false
94 ```
95
96 CPU offload requires a GPU with UVA support;
97 vLLM fails fast when it is unavailable.
98
99 ## Data-parallel topologies (DeepSeek V4.1)
100
101 By default (`embedding_across_dp: false`), each DP replica keeps its own
102 TP-sharded copy of the tables — no cross-replica communication, but one host
103 copy per replica.
104
105 With `embedding_across_dp: true`, the hash heads are sharded across all
106 TP × DP ranks into a single table copy. Each step gathers the hash ids of
107 every co-located DP replica, each rank looks up the heads it owns, and the
108 rows are exchanged back. This trades per-step DP collectives for a much
109 smaller table footprint:
110
111 ```bash
112 vllm serve deepseek-ai/DeepSeek-V4.1-Flash \
113 --tensor-parallel-size 2 --data-parallel-size 4 \
114 --engram-config '{"embedding_across_dp": true}'
115 ```
116
117 `embedding_across_dp` is not supported with elastic expert parallelism yet.
118 Qwen4Exp PLE tables are ETP-sharded instead and honor `cpu_offload` only.
119
120 ## Sharing host tables across DP replicas
121
122 When the tables are CPU-offloaded and DP replicas are co-located on one node,
123 `dp_shared_memory` stores **one copy of each TP shard in `/dev/shm`**, shared
124 by all co-located replicas through `cudaHostRegister`. Each replica then
125 prefetches only its own tokens — no per-step Engram DP collectives — and host
126 memory drops from one table copy per replica to one per node.
127
128 `dp_shared_memory` defaults to enabled whenever the other settings allow it,
129 and falls back to per-replica (or DP-sharded) tables with a warning when:
130
131 - the DP replicas are not co-located on a single node,
132 - `/dev/shm` cannot hold the full tables — in containers, raise the limit
133 with `--shm-size` or `--ipc=host`,
134 - expert parallelism is elastic, which is unsupported.
135
136 Requirements: `cpu_offload` enabled, `--data-parallel-size > 1`, and a shared
137 IPC namespace across the co-located replicas.
138
139 ## Limitations
140
141 - CUDA-alike platforms only.
142 - DeepSeek V4.1 Engram does not support DBO or microbatching; disable
143 `--enable-dbo` and set `--ubatch-size 0`.
144 - `dp_shared_memory` requires `cpu_offload`, `data_parallel_size > 1`, and is
145 unsupported with elastic expert parallelism.