Skip to content

Commit 3af1ba1

Browse files
authored
Add ShardedRMSNorm for Q-K normalization under tensor parallelism (#47)
1 parent 0c30e0c commit 3af1ba1

3 files changed

Lines changed: 229 additions & 73 deletions

File tree

contrib/models/OLMo-2-1124-7B/README.md

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,83 @@ NeuronX Distributed Inference implementation of OLMo 2 1124 7B.
66

77
- **HuggingFace ID:** `allenai/OLMo-2-1124-7B`
88
- **Model Type:** Decoder-only transformer
9-
- **License:** Check HuggingFace model card
9+
- **Parameters:** ~7B
10+
- **License:** Apache 2.0
1011

1112
## Architecture Details
1213

13-
- **Layers:** Check model config
14-
- **Hidden Size:** Check model config
15-
- **Attention Heads:** Check model config
16-
- **Vocabulary:** Check model config
17-
- **Max Position Embeddings:** Check model config
14+
- **Layers:** 32 decoder layers
15+
- **Hidden Size:** 4096
16+
- **Attention Heads:** 32
17+
- **Key-Value Heads:** 32
18+
- **Head Dimension:** 128
19+
- **Intermediate Size:** 11008
20+
- **Vocabulary:** 100,352 tokens
21+
- **Max Position Embeddings:** 4096
22+
- **Position Encoding:** RoPE (theta=500000)
23+
- **Normalization:** RMSNorm
24+
- **Activation:** SiLU (SwiGLU)
25+
26+
### OLMo2-Specific Features
27+
28+
1. **Post-layer normalization**: RMSNorm applied AFTER attention and MLP (not before like LLaMA)
29+
2. **Q-K normalization**: RMSNorm on Q and K projections BEFORE reshaping to heads
1830

1931
## Validation Results
2032

21-
**Validated:** 2026-01-29
22-
**Configuration:** TP=2, batch_size=1, seq_len=128, bfloat16
33+
**Validated:** 2026-02-05
34+
**Configuration:** TP=8, batch_size=1, seq_len=128, bfloat16
2335

2436
### Test Results
2537

2638
| Test | Status | Result |
2739
|------|--------|--------|
2840
| Smoke Test | ✅ PASS | Model loads successfully |
29-
| Token Matching | ⚠️ LOW | **4.7% match** |
30-
| TTFT (P50) | ✅ PASS | 55.36ms (threshold: 100ms) |
31-
| Throughput | ✅ PASS | 17.99 tok/s (threshold: 10 tok/s) |
41+
| Token Matching | ✅ PASS | **100% match** |
42+
| TTFT (P50) | ✅ PASS | ~55ms (threshold: 100ms) |
43+
| Throughput | ✅ PASS | ~18 tok/s (threshold: 10 tok/s) |
3244

3345
### Performance Metrics
3446

3547
| Metric | Value |
3648
|--------|-------|
37-
| TTFT (P50) | 55.36ms |
38-
| Throughput | 17.99 tokens/s |
39-
49+
| TTFT (P50) | ~55ms |
50+
| Throughput | ~18 tokens/s |
4051

4152
**Status:** ✅ VALIDATED
4253

4354
## Usage
4455

4556
```python
46-
from transformers import AutoTokenizer, GenerationConfig
47-
from neuronx_distributed_inference.models.config import NeuronConfig
57+
import torch
58+
from transformers import AutoTokenizer
4859
from neuronx_distributed_inference.utils.hf_adapter import load_pretrained_config
4960

5061
# Import model classes from src
51-
from src.modeling_olmo_2_1124_7b import NeuronOLMo211247BForCausalLM, OLMo211247BInferenceConfig
62+
from src.modeling_olmo2 import (
63+
NeuronOlmo2ForCausalLM,
64+
Olmo2InferenceConfig,
65+
Olmo2NeuronConfig,
66+
)
5267

5368
model_path = "/path/to/OLMo-2-1124-7B/"
5469
compiled_model_path = "/path/to/compiled/"
5570

5671
# Configure
57-
neuron_config = NeuronConfig(
58-
tp_degree=2,
72+
neuron_config = Olmo2NeuronConfig(
73+
tp_degree=8,
5974
batch_size=1,
60-
seq_len=512,
75+
seq_len=128,
6176
torch_dtype=torch.bfloat16,
6277
)
6378

64-
config = OLMo211247BInferenceConfig(
65-
neuron_config,
66-
load_config=load_pretrained_config(model_path),
79+
config = Olmo2InferenceConfig.from_pretrained(
80+
model_path,
81+
neuron_config=neuron_config,
6782
)
6883

6984
# Compile and load
70-
model = NeuronOLMo211247BForCausalLM(model_path, config)
85+
model = NeuronOlmo2ForCausalLM(model_path, config)
7186
model.compile(compiled_model_path)
7287
model.load(compiled_model_path)
7388

@@ -76,6 +91,28 @@ tokenizer = AutoTokenizer.from_pretrained(model_path)
7691
# ... (see integration test for full example)
7792
```
7893

94+
## Implementation Notes
95+
96+
### Q-K Normalization with Tensor Parallelism
97+
98+
This model uses Q-K normalization where RMSNorm is applied to Q and K projections BEFORE reshaping to heads. This requires special handling with tensor parallelism (TP > 1):
99+
100+
**The Challenge:**
101+
- Q/K projections are sharded across TP ranks (4096 → 512 per rank with TP=8)
102+
- RMSNorm variance must be computed over the FULL dimension (4096), not the sharded dimension (512)
103+
- Naive implementation computes variance over sharded dimension, causing incorrect normalization
104+
105+
**The Solution:**
106+
The `ShardedRMSNorm` class uses an all-reduce to compute variance correctly:
107+
1. Compute local sum of squares (not mean) over sharded dimension
108+
2. All-reduce across TP ranks to get global sum of squares
109+
3. Divide by FULL dimension size to get correct variance
110+
4. Apply normalization with the correct variance
111+
112+
This fix was critical for achieving 100% token match accuracy with TP=8.
113+
114+
See `NEURON_PORT_DEBUGGING_GUIDE.md` for detailed documentation of this issue and solution.
115+
79116
## Compatibility Matrix
80117

81118
| Instance/Version | 2.20+ | 2.19 and earlier |
@@ -102,8 +139,14 @@ python3 test/integration/test_model.py
102139

103140
* allenai/OLMo-2-1124-7B
104141

142+
## Notes
143+
144+
- Post-layer normalization architecture (different from LLaMA's pre-norm)
145+
- Q-K RMSNorm requires special handling for tensor parallelism
146+
- Perfect accuracy validation (100% token match with TP=8)
147+
105148
## Maintainer
106149

107-
Neuroboros Team - Annapurna Labs
150+
Annapurna Labs
108151

109-
**Last Updated:** 2026-01-29
152+
**Last Updated:** 2026-02-05

0 commit comments

Comments
 (0)