tompoper commited on
Commit
ccbee60
Β·
verified Β·
1 Parent(s): 08c127d

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +240 -0
README.md CHANGED
@@ -1,3 +1,243 @@
1
  ---
2
  license: mit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: mit
3
+ language:
4
+ - en
5
+ library_name: cflow
6
+ tags:
7
+ - moe
8
+ - cpu-inference
9
+ - rust
10
+ - custom-architecture
11
+ - pipeline-native
12
+ - avx-512
13
+ datasets:
14
+ - roneneldan/TinyStories
15
+ - HuggingFaceFW/fineweb-edu
16
+ pipeline_tag: text-generation
17
+ model-index:
18
+ - name: arch2_4_combined
19
+ results:
20
+ - task:
21
+ type: text-generation
22
+ dataset:
23
+ name: TinyStories
24
+ type: roneneldan/TinyStories
25
+ metrics:
26
+ - name: Test Perplexity (114M, 10K steps)
27
+ type: perplexity
28
+ value: 6.50
29
+ - name: Top-1 Accuracy (114M, 10K steps)
30
+ type: accuracy
31
+ value: 56.8
32
+ - name: Val Perplexity (8.34B, 10K steps)
33
+ type: perplexity
34
+ value: 4.52
35
+ - name: Top-1 Accuracy (8.34B, 10K steps)
36
+ type: accuracy
37
+ value: 61.4
38
  ---
39
+
40
+ # arch2_4_combined β€” Pipeline-Native MoE for CPU Inference
41
+
42
+ A custom decoder-only transformer with delayed dense FFN + delayed MoE experts,
43
+ designed so its inter-layer dependency graph permits vertical pipelining on CPU.
44
+ Part of the **cflow** project β€” a CPU-first streaming inference engine written in
45
+ Rust.
46
+
47
+ ## Key Results
48
+
49
+ | Metric | Value |
50
+ |---|---|
51
+ | CPU decode throughput (8.34B, Q4, 32 threads) | **5.94 tok/s** |
52
+ | Effective memory bandwidth | 61 GB/s (30% of 204.8 GB/s peak) |
53
+ | Bandwidth reduction from pipelining | **2.00x** (16.50 β†’ 4.50 MB/token) |
54
+ | Test perplexity (114M, TinyStories, 10K steps) | 6.50 |
55
+ | Test perplexity (8.34B, TinyStories, 10K steps) | 4.52 |
56
+
57
+ ### CPU Decode Benchmark (AWS r6i.8xlarge, Ice Lake Xeon, 256 GB DDR4)
58
+
59
+ | Engine | Model | Quant | tok/s |
60
+ |---|---|---|---|
61
+ | **cflow** | arch2_4_8k_16l (8.34B MoE, ~3–4B active) | Q4 | **5.94** |
62
+ | Ollama (llama.cpp) | Qwen2.5-32B (32B dense) | Q4 GGUF | 4.75 |
63
+ | vLLM CPU | Qwen2.5-32B-Instruct (32B dense) | GPTQ-Int4 | 1.65 |
64
+
65
+ > **Note:** cflow and the baselines run different models β€” cflow's 8.34B MoE has
66
+ > ~3–4B active params per token vs 32B dense. The cflow number shows what a
67
+ > co-designed architecture + streaming runtime achieves.
68
+
69
+ ## Model Description
70
+
71
+ **arch2_4_combined** is a pre-norm decoder-only transformer with a parallel dense
72
+ FFN + sparse MoE block per layer, using delayed residual injection:
73
+
74
+ - The **dense FFN** reads from a delayed residual (1 layer behind)
75
+ - The **MoE experts** are routed on the current residual but injected 2 layers later
76
+ - This creates a dependency DAG where dense and expert weight reads for layer N
77
+ can overlap with compute for layer N-1, reducing critical-path memory bandwidth
78
+
79
+ The architecture was selected from a screen of 5 pipeline-native candidates. It
80
+ is the only design that achieves a measured bandwidth reduction (2.00x) while
81
+ maintaining competitive perplexity.
82
+
83
+ ### Architecture Details
84
+
85
+ | Parameter | 114M (screening) | 8.34B (scaled) |
86
+ |---|---|---|
87
+ | Hidden dim | 512 | 8,192 |
88
+ | Layers | 6 | 16 |
89
+ | Attention heads | 8 | 128 |
90
+ | Head dim | 64 | 64 |
91
+ | Dense FFN hidden | 2,048 | 32,768 |
92
+ | Expert FFN hidden | 512 | 4,096 |
93
+ | Experts / top-k | 8 / 2 | 8 / 2 |
94
+ | Dense delay | 1 | 1 |
95
+ | Expert delay | 2 | 2 |
96
+ | Vocab | 50,257 (GPT-2 BPE) | 50,257 (GPT-2 BPE) |
97
+ | Max seq len | 512 | 2,048 |
98
+
99
+ ### Per-Layer Forward Pass
100
+
101
+ ```
102
+ attn_out = attention(attn_norm(x))
103
+ x = x + attn_out # residual connection
104
+ x = x + dense_ffn(ffn_norm(delayed_x)) # dense reads DELAYED residual
105
+ if queued_expert: x = x + queued_expert # inject expert from 2 layers ago
106
+ expert_out = moe(ffn_norm(x)) # router sees CURRENT residual
107
+ # expert_out queued for injection at layer + expert_delay
108
+ ```
109
+
110
+ ### Components
111
+
112
+ - **Attention:** Multi-head (not GQA), Q/K/V/O projections (no bias), standard
113
+ RoPE (base=10000, half-interleave), causal masking, KV cache
114
+ - **Dense FFN:** GeGLU β€” `down(gelu(gate(x)) * up(x))`
115
+ - **MoE:** Linear router β†’ top-k selection β†’ softmax over selected β†’ per-expert
116
+ GeGLU FFN β†’ weighted sum. No auxiliary/load-balancing loss.
117
+ - **Normalization:** RMSNorm (eps=1e-6) at attn input, FFN input, and pre-lm_head
118
+ - **Combine style:** `DelayedSum` β€” dense and router share `ffn_norm` but read
119
+ different residual snapshots
120
+
121
+ ## Training
122
+
123
+ ### 114M Screening (5 architectures)
124
+
125
+ | | |
126
+ |---|---|
127
+ | Dataset | TinyStories (431M train tokens, 24M test tokens) |
128
+ | Tokenizer | GPT-2 BPE (50,257 vocab) |
129
+ | Sequence length | 512 |
130
+ | Optimizer | AdamW (betas=0.9/0.95, eps=1e-8, weight_decay=0.1) |
131
+ | Learning rate | 3e-4 with linear warmup (200 steps) + cosine decay to 1e-5 |
132
+ | Gradient clipping | Global norm 1.0 |
133
+ | Batch size | 8 |
134
+ | Steps | 10,000 |
135
+ | Precision | float32 |
136
+ | Hardware | RTX 3060 12 GB |
137
+
138
+ ### 8.34B Scale-Up
139
+
140
+ | | |
141
+ |---|---|
142
+ | Dataset | TinyStories (same splits) |
143
+ | Optimizer | 8-bit AdamW (bitsandbytes) |
144
+ | Learning rate | 1e-4 with linear warmup (500 steps) + cosine decay to 1e-6 |
145
+ | Batch size | 4 per GPU (global 32) |
146
+ | Steps | 10,000 |
147
+ | Precision | bf16 |
148
+ | Parallelism | FSDP (FULL_SHARD / ZeRO-3) |
149
+ | Gradient checkpointing | Per `DelayedMoELayer`, non-reentrant |
150
+ | Hardware | 8x A100 SXM4 80 GB (Lambda Cloud) |
151
+
152
+ ### Architecture Comparison (114M, TinyStories, 10K steps)
153
+
154
+ | Architecture | dense_delay | expert_delay | Test PPL | Top-1 Acc | BW Reduction |
155
+ |---|---|---|---|---|---|
156
+ | arch1_decoupled_streams | 0 | 0 | 7.21 | 54.9% | 1.00x |
157
+ | **arch2_4_combined** | **1** | **2** | **6.50** | **56.8%** | **2.00x** |
158
+ | arch3_pipeline_registers | 0 | 0 | 7.24 | 55.1% | 1.00x |
159
+ | arch4_async_experts | 0 | 2 | **6.26** | **57.6%** | 1.00x |
160
+ | arch5_fixed_point | 0 | 0 | 6.77 | 56.2% | 1.00x |
161
+
162
+ **Key insight:** Dense delay is the bandwidth knob; expert delay is the quality
163
+ knob. arch4_async_experts gets the best perplexity by routing off pre-dense
164
+ activations (cleaner router signal) but sacrifices the bandwidth win that
165
+ arch2_4 achieves by also delaying the dense read.
166
+
167
+ ## Inference with cflow
168
+
169
+ cflow is a Rust inference engine that reads `.cflow` (per-layer streaming) or
170
+ `.vflow` (vertical pipeline) weight files. Weights are stored as pre-tiled Q4
171
+ (128x256 tiles, ~18 KB each, sized to fit L2 cache).
172
+
173
+ ```bash
174
+ # Build
175
+ cargo build --release --bin cflow-run
176
+
177
+ # Convert safetensors β†’ .cflow
178
+ cargo run --release --bin cflow-convert -- \
179
+ --input checkpoint.safetensors \
180
+ --output model.cflow \
181
+ --model arch2_4
182
+
183
+ # Run inference
184
+ CFLOW_THREADS=32 ./target/release/cflow-run \
185
+ model.cflow 32 \
186
+ --prompt "Once upon a time" \
187
+ --tokenizer tokenizer.json \
188
+ --temperature 0.8
189
+ ```
190
+
191
+ ### SIMD Support
192
+
193
+ The runtime auto-detects and dispatches to the best available instruction set:
194
+
195
+ | ISA | Kernel | Notes |
196
+ |---|---|---|
197
+ | AVX-512 + VNNI | Q4Γ—Q8 `vpdpbusd` | Best path (Ice Lake+) |
198
+ | AVX-512F | Q4Γ—f32 FMA | Skylake-X+ |
199
+ | AVX2 + FMA | Q4Γ—f32 FMA | Haswell+ |
200
+ | AVX + SSE4.1 | Q4Γ—f32 | Sandy Bridge+ |
201
+ | Scalar | Q4Γ—f32 | Fallback |
202
+
203
+ ## Limitations
204
+
205
+ - **Not a general-purpose LLM.** Trained on TinyStories / FineWeb-Edu subsets at
206
+ 10K steps β€” this is an architecture and runtime research artifact, not a
207
+ production language model.
208
+ - **Custom architecture.** Cannot be loaded in Hugging Face Transformers, vLLM,
209
+ or llama.cpp without adaptation. Requires the cflow Rust runtime or the
210
+ PyTorch reference in `pipeline_native/`.
211
+ - **CPU-only.** The runtime targets x86-64 CPUs with AVX2 or AVX-512. No GPU
212
+ backend.
213
+ - **Single-token decode optimized.** Batch/prefill throughput is not the focus.
214
+
215
+ ## Thesis Scorecard
216
+
217
+ The cflow project tests 8 claims about CPU inference optimization:
218
+
219
+ | # | Claim | Result |
220
+ |---|---|---|
221
+ | 1 | Conditional expert reading (top-k only) | **Proven** |
222
+ | 2 | Tile-streaming L1/L2 cache locality | **Proven** (7.29x fewer L1-d misses, PMU-measured) |
223
+ | 3 | AVX2/AVX-512 Q4 SIMD kernels | **Proven** |
224
+ | 4 | Fused QKV and gate+up projections | **Proven** |
225
+ | 5 | Compute-order file layout | **Proven** |
226
+ | 6 | Software prefetch (`_mm_prefetch`) | **Disproven** (no benefit; slightly harmful) |
227
+ | 7 | Vertical pipeline via delayed dependencies | **Validated** (2.00x bandwidth reduction) |
228
+ | 8 | Stage-major disk layout readahead | **Disproven** (no isolated benefit) |
229
+
230
+ ## Citation
231
+
232
+ ```bibtex
233
+ @software{poperszky2026cflow,
234
+ author = {Poperszky, Tom},
235
+ title = {cflow: CPU-First Streaming Inference for Pipeline-Native Transformers},
236
+ year = {2026},
237
+ url = {https://github.com/tpoperszky/cflow}
238
+ }
239
+ ```
240
+
241
+ ## License
242
+
243
+ MIT