Andrej Karpathy commited on
Commit
07c4dd4
·
1 Parent(s): e8fec97

manually control the over-active garbage collector, save a small few minutes from a typical run

Browse files
Files changed (1) hide show
  1. scripts/base_train.py +12 -0
scripts/base_train.py CHANGED
@@ -11,6 +11,7 @@ If you are only on CPU/Macbook, you'll want to train a much much smaller LLM. Ex
11
  python -m scripts.base_train --depth=4 --max-seq-len=512 --device-batch-size=1 --eval-tokens=512 --core-metric-every=-1 --total-batch-size=512 --num-iterations=20
12
  """
13
 
 
14
  import os
15
  os.environ["PYTORCH_ALLOC_CONF"] = "expandable_segments:True"
16
  import argparse
@@ -429,8 +430,19 @@ while True:
429
  wandb_run.log(log_data)
430
 
431
  # state update
 
432
  step += 1
433
 
 
 
 
 
 
 
 
 
 
 
434
  # print a few more stats
435
  print0(f"Peak memory usage: {get_max_memory() / 1024 / 1024:.2f}MiB")
436
  print0(f"Total training time: {total_training_time/60:.2f}m")
 
11
  python -m scripts.base_train --depth=4 --max-seq-len=512 --device-batch-size=1 --eval-tokens=512 --core-metric-every=-1 --total-batch-size=512 --num-iterations=20
12
  """
13
 
14
+ import gc
15
  import os
16
  os.environ["PYTORCH_ALLOC_CONF"] = "expandable_segments:True"
17
  import argparse
 
430
  wandb_run.log(log_data)
431
 
432
  # state update
433
+ first_step_of_run = (step == 0) or (resuming and step == args.resume_from_step)
434
  step += 1
435
 
436
+ # The garbage collector is sadly a little bit overactive and for some poorly understood reason,
437
+ # it spends ~500ms scanning for cycles quite frequently, just to end up cleaning up very few tiny objects each time.
438
+ # So we manually manage and help it out here
439
+ if first_step_of_run:
440
+ gc.collect() # manually collect a lot of garbage from setup
441
+ gc.freeze() # immediately freeze all currently surviving objects and exclude them from GC
442
+ gc.disable() # nuclear intervention here: disable GC entirely except:
443
+ elif step % 5000 == 0: # every 5000 steps...
444
+ gc.collect() # manually collect, just to be safe for very, very long runs
445
+
446
  # print a few more stats
447
  print0(f"Peak memory usage: {get_max_memory() / 1024 / 1024:.2f}MiB")
448
  print0(f"Total training time: {total_training_time/60:.2f}m")