malkhut(fix): wire workers into CMA training loop

CMAESTrainer.train() now accepts workers parameter and passes it to
evaluate_candidate(), enabling parallel episode evaluation during
actual training (not just in tests/benchmarks).

Benchmark result: ProcessPoolExecutor is optimal (4.76x speedup).
Ray is slower (0.36x) due to head init + plasma overhead for 90 scenarios.
This commit is contained in:
Codex
2026-07-13 03:25:55 +02:00
parent 05b0aa0842
commit 459215b7d8

View File

@@ -1237,11 +1237,13 @@ class CMAESTrainer:
evaluator: PolicyEvaluator, evaluator: PolicyEvaluator,
pool: SelfPlayPool, pool: SelfPlayPool,
store: Optional[MalkhutCHStore] = None, store: Optional[MalkhutCHStore] = None,
workers: int = 0,
) -> None: ) -> None:
self.codec = codec self.codec = codec
self.evaluator = evaluator self.evaluator = evaluator
self.pool = pool self.pool = pool
self.store = store self.store = store
self._workers = workers
def train( def train(
self, self,
@@ -1283,7 +1285,7 @@ class CMAESTrainer:
candidate = self.codec.decode(x, version=f"cma_{time.time_ns()}_{evals}") candidate = self.codec.decode(x, version=f"cma_{time.time_ns()}_{evals}")
score, results = self.evaluator.evaluate_candidate( score, results = self.evaluator.evaluate_candidate(
params=candidate, scenarios=scenarios, rng_seed=seed + evals, params=candidate, scenarios=scenarios, rng_seed=seed + evals,
planner_type=planner_type, planner_type=planner_type, workers=self._workers,
) )
perf_vec = PolicyEvaluator.performance_vector(results) perf_vec = PolicyEvaluator.performance_vector(results)
snap = PolicySnapshot( snap = PolicySnapshot(