Перейти к содержанию

Параллельные мутации на CPU

Для крупных популяций структурные мутации родителей выносятся в отдельные процессы, обходя GIL. Задействованы cnn_neat/mutation_mp.py и cnn_neat/runtime_cpu.py; они работают в связке с breeding cone (cone отвечает за пропускную способность eval, MP-мутации — за CPU-сторону структурных изменений).

runtime_cpu — размер пула

Аналог runtime_gpu для CPU:

Функция Поведение
cpu_count() max(1, os.cpu_count() or 4)
resolve_cpu_workers(configured) configured <= 0 → все логические CPU; иначе max(1, configured)

Используется и в mutation_mp, и в breeding_cone для насыщения ProcessPool.

mutation_mp — ProcessPool по родителям

Символ Роль
propose_parents_mp(jobs, max_workers=0, topology_only=False) Запуск заданий мутаций в ProcessPool → список dict-результатов
shutdown_pools() Снос кэшированных пулов (тесты / восстановление)

Внутренние (picklable) воркеры:

  • _propose_topology_job — topology-only (~КиБ на потомка): воркер мутирует «безвесового» родителя, а evolver.py затем переприкрепляет conv-снимки родителя к вернувшимся детям. Это рабочий путь.
  • _propose_parent_job — полный round-trip state_dict (медленнее, legacy).

Особенности:

  • Одно задание на пару (parent, mutation_type); crossover-задания несут топологию партнёра.
  • Внутри воркера мутация применяется последовательно (parallel_workers=1).
  • ProcessPoolExecutor кэшируется по числу воркеров (на Windows spawn стоит ~2.6 с на воркер).
  • При BrokenProcessPool — откат на последовательный путь и сброс кэша пулов.
  • Сериализация генома — breeding_cone_mp.genome_to_payload / genome_from_payload.

Конфигурация

Поле ExperimentConfig Default Смысл
mutation_propose_parallel 0 Число процессов (0 = все CPU)
mutation_propose_max_children 8 Максимум детей на родителя за предложение

См. также батч-предложение propose_batch в операторах мутации.