File size: 5,411 Bytes
a8f07a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# spec100m β€” Ultra-fast speculative-decoding language model

A ~480M-parameter transformer + Medusa speculative-decoding architecture optimized for **maximum throughput** on a single GPU. Built from scratch to explore how fast speculative decoding can go when you stop rejecting drafts and accept everything.

## Results

### Inference (A6000, bf16, 480M params)

| Configuration | tok/s | step (ms) | Notes |
|---|---:|---:|---|
| Baseline generation (no n-gram) | 138,607 | 28.9 | Model only, K+1=4096 tokens/step |
| N-gram M=4096 | 266,218 | 28.9 | 1.9x speedup |
| N-gram M=16384 | 491,148 | 40.7 | 3.5x speedup |
| **N-gram M=32768** | **581,646** | 57.3 | **4.2x β€” exceeds 500k target** |
| **Compile + N-gram M=32768** | **599,716** | 55.6 | **Best result** |
| N-gram potential M=65536 | 686,305 | β€” | Projected from real-text test |

### Training (A6000, bf16, 271M trainable)

| Config | tok/s | Notes |
|---|---:|---|
| Original (CPU data loading) | 14,267 | Per-step CPU→GPU copy |
| GPU-resident data | 18,068 | Data stays on GPU |
| **GPU data + batch=32** | **38,427** | **2.7x speedup** |

### Long-context prefill (A6000, 20M tokens)

| Version | tok/s | Notes |
|---|---:|---|
| v4 (228M, 1 layer) | 971,092 | Weight-bandwidth bound |
| v5 (480M, 8 layers) | 123,873 | Full stack: MoBA + FP8 + compression |

## Architecture

### Base model (270M params)
- **d_model**: 1024
- **Layers**: 8
- **Heads**: 16 query, 1 KV (MQA)
- **FFN**: SwiGLU, mult=8 (8192 hidden)
- **Vocab**: 50257 (GPT-2 BPE, tiktoken)
- **Max context**: 20M tokens (MoBA block-sparse)
- **Position**: RoPE
- **Norm**: RMSNorm, tied embeddings

### Medusa speculative heads (210M params)
- **K**: 4095 heads (4096 tokens per step)
- **Rank**: 1 (precomputed argmax trick)
- **Batched**: [K, d, 1] and [K, 1, V] weight tensors
- **Precomputed argmax**: `argmax(s * w) = argmax(w) if s > 0 else argmin(w)` β€” skips the 410MB medusa-out einsum + argmax entirely

### KV cache stack (16x reduction)
1. **MQA**: 1 KV head shared across 16 query heads (4x)
2. **Learned compression**: every 4 tokens β†’ 1 KV entry (4x)
3. **FP8 storage**: E4M3 format (2x)
4. **MoBA**: top-3 block selection via Q @ mean(K_block)
5. **Within-block sparse**: every 4th compressed entry

### N-gram draft extension (0 params)
- 5-gram lookup table trained on 2.4M tokens of Wikipedia
- Self-sustaining: predicts from its own previous predictions
- Adds up to 32768 free tokens per step (no forward pass)
- 4.2x throughput improvement

### Training controller
- Cosine LR schedule with warmup
- Plateau detection (reduce LR on stall)
- Grad norm instability detection
- Convergence prediction (linear extrapolation of loss trajectory)

## Training phases

### Phase 1: Base model (current)
- Train 270M base params only (Medusa frozen)
- Next-token cross-entropy loss
- Goal: produce coherent English
- Status: loss 11.0 β†’ 3.83 in 500 steps on WikiText-2

### Phase 2: Medusa + compression (next)
- Freeze base model
- Train Medusa heads (multi-position loss)
- Train compression params (consistency loss)
- Goal: speculative decoding produces useful drafts

## File layout

| File | Purpose |
|---|---|
| `config.py` | Config dataclass, param counter, VRAM estimator |
| `model.py` | SpecModel: transformer + Medusa + MoBA + compression |
| `inference.py` | V5Engine: compressed MoBA + n-gram + compile + prefill |
| `ngram.py` | NGramModel: 5-gram lookup for free draft tokens |
| `train.py` | Phase 1 training (base only, with controller) |
| `data_pipeline.py` | Download + tokenize WikiText-2 |
| `generate.py` | Generate text from checkpoint |
| `bench_v5_1.py` | Inference benchmark (n-gram + compile) |
| `profile_v5.py` | Step profiling (FFN vs SDPA vs QKVO) |
| `profile_train_speed.py` | Training speed profiling |
| `test_v5_train.py` | Training compatibility test |

## Next steps

1. **Complete Phase 1 training** β€” run 5000+ steps on WikiText-103 (100M tokens) until loss < 3.0 and output is fluent English
2. **Phase 2: train Medusa heads** β€” freeze base, train 4095 heads with multi-position loss. Sample 16 heads/step to fit memory. Train compression params with consistency loss.
3. **Evaluate n-gram integration** β€” after Phase 2, model output should look like real text, so n-gram predictions should be much longer and more accurate. Measure real acceptance rate (not accept-all).
4. **Quality investigation** β€” the rank-1 Medusa trick limits each head to 2 possible tokens (argmax or argmin). Evaluate whether rank-2 or rank-4 heads are needed for quality, and whether the parameter budget allows it.
5. **Weight quantization** β€” int8 weights would ~2x memory bandwidth, potentially doubling prefill throughput. Untested.
6. **Larger corpus** β€” WikiText-2 (2.4M tokens) is too small for a 270M model. Move to WikiText-103 (100M) or OpenWebText for real training.
7. **CUDA graph capture for training** β€” the training loop has Python overhead that CUDA graphs could eliminate. Requires static shapes (already satisfied).
8. **Fused SwiGLU kernel** β€” FFN is 65% of inference step time. A custom Triton kernel for SwiGLU could reduce this.

## Environment

- **Remote**: NVIDIA RTX A6000 (48 GB VRAM), PyTorch 2.14.0+cu130, Python 3.10
- **Local**: NVIDIA RTX 3060 (12 GB VRAM), PyTorch 2.6.0+cu124, Python 3.13
- **Dtype**: bfloat16
- **Tokenizer**: tiktoken GPT-2 BPE (50257 vocab)

## License

MIT