-
Notifications
You must be signed in to change notification settings - Fork 3
Evolution Loop Profiling
Jgocunha edited this page Aug 31, 2026
·
1 revision
Opt-in per-phase timing for Population::evolve(). Answers "which phase of a
generation is slow" instead of only knowing total run duration.
Build with the CMake cache option on:
cmake -B build -S neat-dnfs -DNEAT_DNFS_PROFILE=ON ...
Off by default. When off, the timer types compile to nothing — no storage, no locking, no clock reads, zero runtime cost.
Every evolution run writes profile.csv into the run's output directory
(data/<solutionName>/<timestamp>/profile.csv), one row per generation:
generation,evaluate,speciate,upkeep,reproduceAndSelect,save
1,0.02196,2.78e-05,0.0261534,0.0003992,0.0251842
2,0.0252292,8.9e-06,0.0262199,0.0004335,0.0252712
3,0.0267178,8.7e-06,0.0258752,0.0004648,0.0249319
Values are seconds. Columns:
| Column | What it times |
|---|---|
evaluate |
Running every genome's phenotype (parallelized internally) |
speciate |
Grouping genomes into species |
upkeep |
Bookkeeping + file I/O for the generation |
reproduceAndSelect |
Selection, crossover, mutation for the next generation |
save |
The file-I/O part of upkeep — timed separately for visibility |
upkeep includes save, it does not sit beside it. Columns do not sum to
the generation total; treat save as a breakdown of upkeep, not a sixth
phase.
- Run a representative evolution with
-DNEAT_DNFS_PROFILE=ON. - Open
profile.csvand look at which column dominates the row.-
evaluatedominating → the bottleneck is genome/phenotype simulation cost, or population size. Look at the task's DNF simulation, not the NEAT machinery. -
savedominating → file-I/O settings are the cost, not evolution itself. Checkconfig/neat_dnfs.json'ssaveXxxflags — turning off ones you don't need (e.g.saveSolutions) scales down with population size. -
speciateorreproduceAndSelectdominating → look at genome/species count and the NEAT operators themselves; this is unusual unless population size is large.
-
- Compare columns across generations, not just within one row — a phase that grows with generation number points at something accumulating (e.g. species count, genome size) rather than a fixed per-call cost.
- Re-run after a change and diff the new
profile.csvagainst the old one to confirm the fix actually moved the number you targeted.
- Only the main thread records.
evaluate()'s parallelstd::asyncworkers are deliberately uninstrumented, so this is safe under-DNEAT_DNFS_SANITIZER=thread. - Columns are a fixed, explicit set. A phase that didn't run in a given
generation reports
0.0rather than shifting later columns — rows always align with the header.