Skip to content

Commit 2369cba

Browse files
Merge pull request #119 from drunkenbot-ai/develop
update dimentions related issue
2 parents feb5de7 + 8d9c964 commit 2369cba

5 files changed

Lines changed: 90 additions & 5 deletions

File tree

engine

interface/screens/training_estimation.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ def _update_architecture_advisor(
109109
label = "Advisor: balanced"
110110
notes.append(f"Token budget is about {tokens_per_param:.1f} tokens per parameter.")
111111
if model_config is not None:
112+
head_dim = model_config.embedding_size // max(1, model_config.head_count)
113+
if head_dim % 8 != 0:
114+
notes.append(
115+
f"Head dimension d_k = {head_dim} (n_embd={model_config.embedding_size} / n_head={model_config.head_count}) "
116+
"is not divisible by 8. FlashAttention will fall back to slow Math attention. Recommended: 64 or 128 (e.g. n_embd: 512, n_head: 8)."
117+
)
118+
label = f"Advisor: d_k={head_dim} (slow)"
112119
if model_config.context_length >= 2048 and model_config.embedding_size <= 256:
113120
notes.append("Long context with a small embedding can be memory-heavy without adding much capacity.")
114121
if model_config.attention_type in {"grouped_query", "multi_query"}:

interface/screens/training_run.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,19 @@ def _run_training_preflight(self, model_config: ModelConfig, training_config: Tr
193193
warnings.append("Free disk space is close to the estimated training storage need.")
194194
if checkpoint_count > 50:
195195
warnings.append("Save interval may create many checkpoints. Increase Save every or clean old checkpoints.")
196+
head_dim = model_config.embedding_size // max(1, model_config.head_count)
197+
if head_dim % 8 != 0:
198+
warnings.append(
199+
f"Head dimension d_k = {head_dim} (n_embd={model_config.embedding_size} / n_head={model_config.head_count}) "
200+
"is not divisible by 8. PyTorch FlashAttention will fall back to slow Math attention. "
201+
"For 10x-20x faster training, adjust settings so d_k is 64 or 128 (e.g. n_embd: 512, n_head: 8)."
202+
)
203+
if training_config.compile_model and training_config.activation_checkpointing:
204+
warnings.append(
205+
"Both Torch compile and Activation checkpointing are enabled. "
206+
"Activation checkpointing forces extra forward passes and can slow down compilation. "
207+
"Disable Activation checkpointing unless GPU memory is nearly exhausted."
208+
)
196209

197210
log.clear()
198211
log.append("Training checklist")

interface/tabs/training_tab.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,23 @@ def build_training_tab(window) -> QWidget:
8787
"Leave checked unless you are deliberately experimenting with this.",
8888
)
8989
window.n_embd = window._spin(32, 4096, 128)
90-
window._tip(window.n_embd, "Embedding size, also called n_embd. Larger values increase model capacity and memory usage.")
90+
window._tip(
91+
window.n_embd,
92+
"Embedding size (n_embd). Larger values increase capacity and memory usage. "
93+
"For maximum GPU FlashAttention speed, ensure (n_embd / n_head) is a multiple of 8, "
94+
"ideally 64 or 128 (e.g. 512, 768).",
95+
)
9196
window.architecture_style.currentTextChanged.connect(
9297
lambda text: window.rope_theta.setEnabled(text == "Llama-like")
9398
)
9499
window.rope_theta.setEnabled(window.architecture_style.currentText() == "Llama-like")
95100
window.n_head = window._spin(1, 64, 4)
96-
window._tip(window.n_head, "Attention head count. More heads can model varied relationships, but n_embd must divide evenly by n_head.")
101+
window._tip(
102+
window.n_head,
103+
"Attention head count. n_embd must divide evenly by n_head. "
104+
"For fast GPU FlashAttention, head dimension (n_embd / n_head) must be a multiple of 8, "
105+
"ideally 64 or 128 (e.g. 512 / 8 = 64, 768 / 12 = 64).",
106+
)
97107
window.attention_type = QComboBox()
98108
window.attention_type.addItems(["Multi-head", "Grouped-query", "Multi-query"])
99109
window.attention_type.setMaximumWidth(260)

tests/test_pretraining_fixes.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from interface.core.project_state import ProjectStateMixin
1111
from interface.core.project_state_apply import ProjectStateApplyMixin
1212

13-
from engine.config import DatasetConfig
13+
from engine.config import DatasetConfig, ModelConfig, TrainingConfig
1414
from engine.data import Document
1515
from engine.dataset_corpus import _StreamingCorpusBuilder
1616
from engine.dataset_mixture import (
@@ -25,7 +25,7 @@
2525
token_dtype_for_vocab,
2626
train_tokenizer,
2727
)
28-
from engine.training import TokenDataset
28+
from engine.training import TokenDataset, train_model
2929

3030

3131
class DiversityFilterTests(unittest.TestCase):
@@ -181,5 +181,60 @@ def test_validation_stride_equals_context_length(self) -> None:
181181
self.assertEqual(y1.tolist(), list(range(65, 129)))
182182

183183

184+
class TrainingDiagnosticsAndTelemetryTests(unittest.TestCase):
185+
"""Tests for preflight warnings and telemetry emission enhancements."""
186+
187+
def test_head_dim_not_divisible_by_eight_detected(self) -> None:
188+
model_config = ModelConfig(
189+
vocab_size=32,
190+
context_length=16,
191+
embedding_size=560,
192+
head_count=8,
193+
layer_count=2,
194+
)
195+
head_dim = model_config.embedding_size // model_config.head_count
196+
self.assertEqual(head_dim, 70)
197+
self.assertNotEqual(head_dim % 8, 0)
198+
199+
def test_milestone_step_emits_event(self) -> None:
200+
with tempfile.TemporaryDirectory() as tmp_dir:
201+
model_config = ModelConfig(
202+
vocab_size=16,
203+
context_length=8,
204+
embedding_size=16,
205+
head_count=2,
206+
layer_count=1,
207+
dropout=0.0,
208+
)
209+
training_config = TrainingConfig(
210+
output_dir=Path(tmp_dir),
211+
epochs=1,
212+
batch_size=1,
213+
learning_rate=1e-3,
214+
sample_stride=8,
215+
warmup_steps=0,
216+
eval_interval=0,
217+
save_interval=0,
218+
use_amp=False,
219+
precision="fp32",
220+
device="cpu",
221+
resume=False,
222+
early_stopping=False,
223+
)
224+
events: list[dict] = []
225+
train_model(
226+
model_config,
227+
training_config,
228+
[index % 16 for index in range(32)],
229+
[],
230+
pad_token_id=-1,
231+
progress=events.append,
232+
)
233+
step_events = [e for e in events if e.get("event_type") == "step"]
234+
self.assertGreaterEqual(len(step_events), 1)
235+
self.assertIn("Step 1", step_events[0]["message"])
236+
237+
184238
if __name__ == "__main__":
185239
unittest.main()
240+

0 commit comments

Comments
 (0)