Skip to content

Speed ups for training - #75

Draft
treeform wants to merge 7 commits into
mainfrom
training-speedups
Draft

treeform wants to merge 7 commits into
mainfrom
training-speedups

Conversation

@treeform

Copy link
Copy Markdown
Contributor

Makes GotA training faster in two ways: the simulation runs about 1.55x faster per core with identical results, and a new lockstep training API lets trainers use every CPU.

Simulation speedups (game results unchanged)

A full 28,800-tick match with fixed actions gives the same state hash before and after (5CD704D815D34746), at 1,274 ticks/s on main and 1,972 ticks/s on this branch (Apple M-series, one core).

  • No deep copies in read-only loops. for x in world.footmen and let x = world.footmen[i] copied each Footman, including its movePath seq, many times per tick. Those read-only locals are now {.cursor.} over indexed loops.
  • One sorted object list per team. ensureScriptObjects rebuilt and sorted the visible-object list for every hero, but during a decision frame it only depends on the team. It is now cached per team while observations are frozen.
  • Cheaper vision cache checks. revealVisionCached compared two height grids element by element every rebuild; that is now one equalMem, and the blocker grid is copied with copyMem.
  • A path cache.* Creep and hero paths are cached per navigationRevision, which already bumps whenever building occupancy changes, so results are the same.
  • visible() unrolled over its up to four sight cells instead of going through the sightTiles iterator; it runs for every unit pair.

Bug fix in training.nim

A lane releases the process lock mid-tick while it waits for the trainer's action. Another lane then ticks and repoints the navigationWorld global at its own match, and when the first lane resumed, its heroes pathed against the other match's buildings. The lane now calls bindNavigation(game.world) after it wakes, next to the existing activeGame = game. Single-lane results are unchanged; multi-lane results change because of the fix.

Lockstep training API (lockstep.nim)

training.nim gives each lane a worker thread that blocks inside chooseAction, and all lanes share one process lock, so a trainer gets one core per process and one lane decision at a time. lockstep.nim is a second API alongside it:

  • Every policy hero is an agent. chooseAction records the hero's newest features and returns the action the trainer last set, so scripts never block and no threads are needed.
  • step applies one action per agent, runs actionTicks ticks of every lane, and returns rewards, terminals, and per-lane stats. Finished lanes restart inside the step.
  • selfPlay runs the policy on both teams (10 agents per lane); otherwise one team plays a bundled opponent (5 per lane).
  • Three reward modes: the hosted leaderboard score (zero for non-winners), team XP change, and XP plus a win/loss bonus.
  • C exports: gota_create/agents/reset/step/close.

Library state is still process-global, so the external PufferLib env loads one copy of the library per env to run envs in parallel. With that, a PufferLib 5 trainer measured 33–36K steps/s on 128 CPUs of a b300 node, against about 370 with training.nim.

Testing

  • New tests/test_gota_lockstep.nim (added to CI): agent counts, seats, determinism, lane restarts, and every reward mode.
  • Ran locally with POLYWORLD_DEPS=tmp/coworld/deps: tests/tests.nim and every GotA step in build.yml pass (events, controls, camps, phases, portals, potions, progression, drafts, gen_replays gota, test_gota_sim, test_gota_training, test_gota_lockstep, test_recordings -d:recordGota).
  • Same-hash check above for the simulation changes.

🤖 Generated with Claude Code

treeform and others added 7 commits September 25, 2026 07:19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@treeform
treeform marked this pull request as draft September 25, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant