ViuAI commited on
Commit
2ec913e
·
verified ·
1 Parent(s): 1c68440

Fix CUDA OOM on T4: cast model to amp_dtype directly, batch_size=2, safe RMSNorm

Browse files
model/configs/train_kaggle_t4.yaml CHANGED
@@ -13,23 +13,23 @@ curriculum: true
13
  curriculum_stages:
14
  - max_step: 50000
15
  seq_len: 512
16
- batch_size: 2
17
- grad_accum: 64 # 512 * 2 * 64 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
18
  - max_step: 200000
19
  seq_len: 1024
20
- batch_size: 2
21
- grad_accum: 32 # 1024 * 2 * 32 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
22
  - max_step: null
23
  seq_len: 2048
24
  batch_size: 1
25
- grad_accum: 32 # 2048 * 1 * 32 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
26
 
27
  seq_len: 1024
28
  train_split: 0.95
29
 
30
- # Kaggle T4 16GB VRAM: micro-batch 2 with SDPA and Gradient Checkpointing (~9GB peak VRAM)
31
- batch_size: 2
32
- grad_accum: 32
33
  target_global_batch: 128
34
  auto_tune: false
35
 
 
13
  curriculum_stages:
14
  - max_step: 50000
15
  seq_len: 512
16
+ batch_size: 1
17
+ grad_accum: 128 # 512 * 1 * 128 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
18
  - max_step: 200000
19
  seq_len: 1024
20
+ batch_size: 1
21
+ grad_accum: 64 # 1024 * 1 * 64 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
22
  - max_step: null
23
  seq_len: 2048
24
  batch_size: 1
25
+ grad_accum: 32 # 2048 * 1 * 32 = 65,536 tokens/step per GPU (x2 GPUs = 131,072 tok/step)
26
 
27
  seq_len: 1024
28
  train_split: 0.95
29
 
30
+ # Kaggle T4 16GB VRAM: micro-batch 1 with SDPA and Gradient Checkpointing (<11GB peak VRAM)
31
+ batch_size: 1
32
+ grad_accum: 64
33
  target_global_batch: 128
34
  auto_tune: false
35
 
model/scripts/train.py CHANGED
@@ -1798,6 +1798,8 @@ def main():
1798
  scaler.update()
1799
  else:
1800
  opt.step()
 
 
1801
  step += 1
1802
 
1803
  # Clean industry-standard pretraining logs: only essential metrics, no terminal garbling
 
1798
  scaler.update()
1799
  else:
1800
  opt.step()
1801
+ if device.type == "cuda":
1802
+ torch.cuda.empty_cache()
1803
  step += 1
1804
 
1805
  # Clean industry-standard pretraining logs: only essential metrics, no terminal garbling
model/scripts/viu_moe.py CHANGED
@@ -443,25 +443,46 @@ class Viu1MoE(nn.Module):
443
  total_aux = total_aux + aux
444
  usages.append(usage.detach())
445
  h = self.norm(x)
446
- logits = self.head(h)
447
- if self.final_softcap > 0:
448
- logits = self.final_softcap * torch.tanh(logits / self.final_softcap)
449
-
450
  loss, mt_loss = None, None
451
  if targets is not None:
452
- loss = F.cross_entropy(logits.view(-1, logits.size(-1)), targets.view(-1))
453
- del logits
454
- logits = None
455
- if self.mt_head is not None and T > 1:
456
- mt_logits = self.mt_head(h[:, :-1, :])
 
 
 
 
 
 
457
  if self.final_softcap > 0:
458
- mt_logits = self.final_softcap * torch.tanh(mt_logits / self.final_softcap)
459
- mt_tgt = targets[:, 1:]
460
- mt_loss = F.cross_entropy(mt_logits.reshape(-1, mt_logits.size(-1)), mt_tgt.reshape(-1))
461
- del mt_logits, mt_tgt
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  loss = loss + 0.1 * mt_loss
 
463
  if isinstance(total_aux, torch.Tensor):
464
  loss = loss + total_aux
 
 
 
 
 
465
  aux_info = {
466
  "moe_aux": float(total_aux.detach()) if isinstance(total_aux, torch.Tensor) else 0.0,
467
  "mt_loss": float(mt_loss.detach()) if isinstance(mt_loss, torch.Tensor) else 0.0,
 
443
  total_aux = total_aux + aux
444
  usages.append(usage.detach())
445
  h = self.norm(x)
 
 
 
 
446
  loss, mt_loss = None, None
447
  if targets is not None:
448
+ # Chunked cross entropy: computes head projection + loss in 256-token chunks
449
+ # Eliminates 300MB+ peak allocation at vocabulary projection on 16GB GPUs
450
+ flat_h = h.reshape(-1, self.args.dim)
451
+ flat_tgt = targets.reshape(-1)
452
+ chunk_size = 256
453
+ n_tokens = flat_tgt.numel()
454
+ total_loss = 0.0
455
+ for ci in range(0, n_tokens, chunk_size):
456
+ ch_h = flat_h[ci : ci + chunk_size]
457
+ ch_tgt = flat_tgt[ci : ci + chunk_size]
458
+ ch_logits = self.head(ch_h)
459
  if self.final_softcap > 0:
460
+ ch_logits = self.final_softcap * torch.tanh(ch_logits / self.final_softcap)
461
+ total_loss = total_loss + F.cross_entropy(ch_logits, ch_tgt, reduction="sum")
462
+ loss = total_loss / max(n_tokens, 1)
463
+
464
+ if self.mt_head is not None and T > 1:
465
+ flat_h_mt = h[:, :-1, :].reshape(-1, self.args.dim)
466
+ flat_tgt_mt = targets[:, 1:].reshape(-1)
467
+ n_tokens_mt = flat_tgt_mt.numel()
468
+ total_mt_loss = 0.0
469
+ for ci in range(0, n_tokens_mt, chunk_size):
470
+ ch_h_mt = flat_h_mt[ci : ci + chunk_size]
471
+ ch_tgt_mt = flat_tgt_mt[ci : ci + chunk_size]
472
+ ch_logits_mt = self.mt_head(ch_h_mt)
473
+ if self.final_softcap > 0:
474
+ ch_logits_mt = self.final_softcap * torch.tanh(ch_logits_mt / self.final_softcap)
475
+ total_mt_loss = total_mt_loss + F.cross_entropy(ch_logits_mt, ch_tgt_mt, reduction="sum")
476
+ mt_loss = total_mt_loss / max(n_tokens_mt, 1)
477
  loss = loss + 0.1 * mt_loss
478
+
479
  if isinstance(total_aux, torch.Tensor):
480
  loss = loss + total_aux
481
+ logits = None
482
+ else:
483
+ logits = self.head(h)
484
+ if self.final_softcap > 0:
485
+ logits = self.final_softcap * torch.tanh(logits / self.final_softcap)
486
  aux_info = {
487
  "moe_aux": float(total_aux.detach()) if isinstance(total_aux, torch.Tensor) else 0.0,
488
  "mt_loss": float(mt_loss.detach()) if isinstance(mt_loss, torch.Tensor) else 0.0,