From 5a048bf4694478acdde2ab1bffbd55c46ff918cc Mon Sep 17 00:00:00 2001 From: Seth Hamilton Date: Tue, 9 Sep 2025 19:57:27 -0500 Subject: [PATCH] Running. Only tested single thread version. Stats are looking nice. Needs more validation --- debug.rad | 5 +++- inc/genetic.h | 81 ++++++++++++++++++++++++++------------------------- inc/util.h | 53 +++++++++++++++++++++++++++++++++ src/main.cpp | 10 +++++-- 4 files changed, 105 insertions(+), 44 deletions(-) create mode 100644 inc/util.h diff --git a/debug.rad b/debug.rad index d555d4d..a3ec9c9 100644 --- a/debug.rad +++ b/debug.rad @@ -1,8 +1,11 @@ // raddbg 0.9.21 project file recent_file: path: "inc/genetic.h" -recent_file: path: "d:/os/obj/amd64fre/minkernel/crts/ucrt/src/appcrt/misc/mt/objfre/amd64/minkernel/crts/ucrt/src/appcrt/misc/invalid_parameter.cpp" +recent_file: path: "inc/sync.h" recent_file: path: "src/main.cpp" +recent_file: path: "../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/include/vector" +recent_file: path: "d:/os/obj/amd64fre/minkernel/crts/ucrt/src/appcrt/misc/mt/objfre/amd64/minkernel/crts/ucrt/src/appcrt/misc/invalid_parameter.cpp" +recent_file: path: "../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/include/xmemory" recent_file: path: "../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.42.34433/include/algorithm" recent_file: path: "../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.42.34433/include/xutility" target: diff --git a/inc/genetic.h b/inc/genetic.h index 6512155..f97a741 100644 --- a/inc/genetic.h +++ b/inc/genetic.h @@ -2,8 +2,8 @@ #include #include -#include +#include "util.h" #include "sync.h" #include "rand.h" @@ -11,7 +11,6 @@ using namespace sync; namespace genetic { -template struct Array; template struct Stats; template struct Strategy; struct CellTracker; @@ -22,12 +21,15 @@ template struct Strategy { // Number of worker threads that will be evaluating cell fitness int num_threads; - float stats_print_period; + // Period of print statements (in seconds) + float stats_print_period_s; + + // Size of the population pool per sim thread + int num_cells_per_thread; + + // Number of times (epochs) to run the algorithm + int num_generations; - int batch_size; // Number of cells a worker thread tries to work on in a row - // before accessing/locking the work queue again. - int num_cells_per_thread; // Size of the population pool per sim thread - int num_generations; // Number of times (epochs) to run the algorithm bool test_all; // Sets whether or not every cell's fitness is evaluated every // generation float test_chance; // Chance to test any given cell's fitness. Relevant only @@ -60,21 +62,17 @@ template struct Strategy { }; template struct Stats { - std::vector best_cell; - std::vector best_cell_fitness; + DynArray best_cells; + DynArray best_cell_fitness; int gen; bool done; TimeSpan start, end; - TimeSpan total_crossover_time; int total_crossovers; - TimeSpan total_mutate_time; int total_mutates; - TimeSpan total_fitness_time; int total_evaluations; - TimeSpan total_sorting_time; int total_sorts; @@ -86,26 +84,12 @@ struct CellTracker { int cellid; }; -template struct Array { - T *data; - int len; - - T &operator[](int i) { return data[i]; } -}; - -template Array make_array(int len) { - return { - .data = (T*)malloc(sizeof(T)*len), - .len = len - }; -} - template struct WorkerThreadArgs { Strategy strat; Array cells; Array trackers; - Stats &stats; + Stats *stats; }; template T* _cellp(Array cells, CellTracker tracker) { return &cells[tracker.cellid]; } @@ -116,7 +100,7 @@ template DWORD worker(LPVOID args) { Strategy strat = worker_args->strat; Array cells = worker_args->cells; Array trackers = worker_args->trackers; - Stats &stats = worker_args->stats; + Stats &stats = *worker_args->stats; // Prepare crossover operations as these will be the same every time except // for the exact cell pointers @@ -192,8 +176,8 @@ template DWORD worker(LPVOID args) { stats.total_sorting_time = stats.total_sorting_time + (now() - start); stats.total_sorts++; - stats.best_cell.push_back(cells[trackers[0].cellid]); - stats.best_cell_fitness.push_back(trackers[0].score); + append(stats.best_cells, cells[trackers[0].cellid]); + append(stats.best_cell_fitness, trackers[0].score); stats.gen++; unlock(stats.m); } @@ -217,8 +201,21 @@ template T run(Strategy strat) { for (int i = 0; i < strat.num_threads; i++) { stats[i] = { - .gen=0, - .m=make_mutex() + .best_cells=make_dynarray(strat.num_generations), + .best_cell_fitness=make_dynarray(strat.num_generations), + .gen=0, + .done=false, + .start=from_s(0), + .end=from_s(0), + .total_crossover_time=from_s(0), + .total_crossovers=0, + .total_mutate_time=from_s(0), + .total_mutates=0, + .total_fitness_time=from_s(0), + .total_evaluations=0, + .total_sorting_time=from_s(0), + .total_sorts=0, + .m=make_mutex() }; Array tcells = { &cells[i*strat.num_cells_per_thread], strat.num_cells_per_thread }; Array ttrackers = { &trackers[i*strat.num_cells_per_thread], strat.num_cells_per_thread }; @@ -226,7 +223,7 @@ template T run(Strategy strat) { args[i].strat=strat; args[i].cells=tcells; args[i].trackers=ttrackers; - args[i].stats=stats[i]; + args[i].stats=&stats[i]; threads[i] = make_thread(worker, &args[i]); } @@ -234,7 +231,7 @@ template T run(Strategy strat) { // We are the stats thread bool complete = false; while (!complete) { - sleep(from_s(strat.stats_print_period)); + sleep(from_s(strat.stats_print_period_s)); printf("**********************\n"); float g_avg_crossover_time = 0; @@ -242,6 +239,7 @@ template T run(Strategy strat) { float g_avg_fitness_time = 0; float g_avg_sorting_time = 0; float g_progress_per = 0; + float g_best_fitness = strat.higher_fitness_is_better ? 0.0 : 999999999999999999.9; complete = true; @@ -259,13 +257,16 @@ template T run(Strategy strat) { float progress_per = static_cast(stats[i].gen) / static_cast(strat.num_generations) * 100; + float best_score = back(stats[i].best_cell_fitness); + g_avg_crossover_time += avg_crossover_time; g_avg_mutate_time += avg_mutate_time; g_avg_fitness_time += avg_fitness_time; g_avg_sorting_time += avg_sorting_time; g_progress_per += progress_per; + g_best_fitness = strat.higher_fitness_is_better ? max(best_score, g_best_fitness) : min(best_score, g_best_fitness); - printf("THREAD %d, Progress %.1f%, Average Crossover Time/Cell %.5f (s), Average Mutate Time/Cell: %.5f (s), Average Fitness Time/Cell: %.5f (s), Average Sorting Time: %.5f (s)\n", i, progress_per, avg_crossover_time, avg_mutate_time, avg_fitness_time, avg_sorting_time); + printf("THREAD %d, Progress %.1f\%, Top Score %.5e, Cross %.5f (s), Mutate: %.5f (s), Fitness: %.5f (s), Sorting: %.5f (s)\n", i, progress_per, best_score, avg_crossover_time, avg_mutate_time, avg_fitness_time, avg_sorting_time); unlock(stats[i].m); } @@ -275,18 +276,18 @@ template T run(Strategy strat) { g_avg_sorting_time /= stats.len; g_progress_per /= stats.len; - printf("OVERALL, Progress %.1f%, Average Crossover Time/Cell %.5f (s), Average Mutate Time/Cell: %.5f (s), Average Fitness Time/Cell: %.5f (s), Average Sorting Time: %.5f (s)\n", g_progress_per, g_avg_crossover_time, g_avg_mutate_time, g_avg_fitness_time, g_avg_sorting_time); + printf("OVERALL, Progress %.1f\%, Top Score: %.5e, Cross %.5f (s), Mutate: %.5f (s), Fitness: %.5f (s), Sorting: %.5f (s)\n", g_progress_per, g_best_fitness, g_avg_crossover_time, g_avg_mutate_time, g_avg_fitness_time, g_avg_sorting_time); if (complete) break; } T best_cell; // TODO: bad - float best_score = strat.higher_fitness_is_better ? 999999999999999999.9 : 0.0; + float best_score = strat.higher_fitness_is_better ? 0.0 : 999999999999999999.9; for (int i = 0; i < stats.len; i++) { - float score = stats[i].best_cell_fitness.back(); + float score = back(stats[i].best_cell_fitness); if (strat.higher_fitness_is_better ? score > best_score : score < best_score) { - best_cell = stats[i].best_cell.back(); + best_cell = back(stats[i].best_cells); best_score = score; } } diff --git a/inc/util.h b/inc/util.h new file mode 100644 index 0000000..ed8326a --- /dev/null +++ b/inc/util.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#define min(A, B) ((A < B) ? (A) : (B)) +#define max(A, B) ((A > B) ? (A) : (B)) + +template struct Array { + T *data; + int len; + + T &operator[](int i) { return data[i]; } +}; + + +template Array make_array(int len) { + return { + .data=(T*)malloc(sizeof(T)*len), + .len=len + }; +} + +template struct DynArray { + T* _data; + int end; + int cap; + + T &operator[](int i) { return _data[i]; } +}; + +template DynArray make_dynarray(int cap) { + return { + ._data=(T*)malloc(sizeof(T)*cap), + .end=0, + .cap=cap + }; +} + +template void resize(DynArray &a, int new_cap) { + T* old = a._data; + a._data = (T*)malloc(sizeof(T)*new_cap); + memcpy(a._data, old, min(sizeof(T)*a.end, sizeof(T)*new_cap)); + a.cap = new_cap; + free(old); +} + +template void append(DynArray &a, T el) { + if (a.end == a.cap) resize(a, min(1, a.cap*2)); + a[a.end++] = el; +} + +template T& back(DynArray &a) { return a._data[a.end-1]; } +template T& front(DynArray &a) { return a._data[0]; } + diff --git a/src/main.cpp b/src/main.cpp index 16e0317..77f1d91 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include "genetic.h" #include "rand.h" +#include "sync.h" using namespace genetic; @@ -54,11 +55,11 @@ float fitness(const Array &cell) { } int main(int argc, char **argv) { - int num_gens = 2000; + int num_gens = 1000; Strategy> strat { .num_threads = 1, - .batch_size = 1, - .num_cells_per_thread = 100000, + .stats_print_period_s = 2, + .num_cells_per_thread = 10000, .num_generations = num_gens, .test_all = true, .test_chance = 0.0, // doesn't matter @@ -76,7 +77,9 @@ int main(int argc, char **argv) { .fitness=fitness }; + TimeSpan start = now(); auto best_cell = run(strat); + TimeSpan runtime = now() - start; float sum = 0; float product = 1; @@ -90,4 +93,5 @@ int main(int argc, char **argv) { printf("\n"); printf("Final Sum: %f\n", sum); printf("Final Product: %f\n", product); + printf("Execution Time %d (min) %f (s)\n", static_cast(sync::to_min(runtime)), fmod(to_s(runtime), 60) ); }