From dd144a199a8a38d25ecb5c2a04042e39082648d7 Mon Sep 17 00:00:00 2001 From: Brett Date: Sat, 31 Aug 2024 23:15:16 -0400 Subject: [PATCH 1/4] track allocations --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 39 ++++++++++---------- include/blt/gp/fwdecl.h | 6 ++++ include/blt/gp/selection.h | 43 +++++++++++++++------- include/blt/gp/stats.h | 62 ++++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b40123..967684f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.37) +project(blt-gp VERSION 0.1.38) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index 078316e..69eac6d 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -104,35 +104,15 @@ int main() { BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation()); BLT_TRACE("Creating next generation"); - -#ifdef BLT_TRACK_ALLOCATIONS - auto gen_alloc = blt::gp::tracker.start_measurement(); -#endif - BLT_START_INTERVAL("Symbolic Regression", "Gen"); program.create_next_generation(); BLT_END_INTERVAL("Symbolic Regression", "Gen"); - -#ifdef BLT_TRACK_ALLOCATIONS - blt::gp::tracker.stop_measurement(gen_alloc); - BLT_TRACE("Generation Allocated %ld times with a total of %s", gen_alloc.getAllocationDifference(), - blt::byte_convert_t(gen_alloc.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); - auto fitness_alloc = blt::gp::tracker.start_measurement(); -#endif - BLT_TRACE("Move to next generation"); BLT_START_INTERVAL("Symbolic Regression", "Fitness"); program.next_generation(); BLT_TRACE("Evaluate Fitness"); program.evaluate_fitness(); BLT_END_INTERVAL("Symbolic Regression", "Fitness"); - -#ifdef BLT_TRACK_ALLOCATIONS - blt::gp::tracker.stop_measurement(fitness_alloc); - BLT_TRACE("Fitness Allocated %ld times with a total of %s", fitness_alloc.getAllocationDifference(), - blt::byte_convert_t(fitness_alloc.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); -#endif - BLT_TRACE("----------------------------------------------"); std::cout << std::endl; } @@ -162,6 +142,25 @@ int main() #ifdef BLT_TRACK_ALLOCATIONS BLT_TRACE("Total Allocations: %ld times with a total of %s", blt::gp::tracker.getAllocations(), blt::byte_convert_t(blt::gp::tracker.getAllocatedBytes()).convert_to_nearest_type().to_pretty_string().c_str()); + auto crossover_calls = blt::gp::crossover_calls.get_calls(); + auto crossover_allocations = blt::gp::crossover_allocations.get_calls(); + auto mutation_calls = blt::gp::mutation_calls.get_calls(); + auto mutation_allocation = blt::gp::mutation_allocations.get_calls(); + auto reproduction_calls = blt::gp::reproduction_calls.get_calls(); + auto reproduction_allocation = blt::gp::reproduction_allocations.get_calls(); + BLT_TRACE("Total Crossover Calls: %ld", crossover_calls); + BLT_TRACE("Total Mutation Calls: %ld", mutation_calls); + BLT_TRACE("Total Reproduction Calls: %ld", reproduction_calls); + BLT_TRACE("Total Crossover Allocations: %ld", crossover_allocations); + BLT_TRACE("Total Mutation Allocations: %ld", mutation_allocation); + BLT_TRACE("Total Reproduction Allocations: %ld", reproduction_allocation); + + BLT_TRACE("Percent Crossover calls allocate? %lf%%", + static_cast(crossover_allocations) / static_cast(crossover_calls == 0 ? 1 : crossover_calls) * 100); + BLT_TRACE("Percent Mutation calls allocate? %lf%%", + static_cast(mutation_allocation) / static_cast(mutation_calls == 0 ? 1 : mutation_calls) * 100); + BLT_TRACE("Percent Reproduction calls allocate? %lf%%", + static_cast(reproduction_allocation) / static_cast(reproduction_calls == 0 ? 1 : reproduction_calls) * 100); #endif return 0; diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index 24319e0..8311bac 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -29,6 +29,12 @@ namespace blt::gp { inline allocation_tracker_t tracker; + inline call_tracker_t crossover_calls; + inline call_tracker_t mutation_calls; + inline call_tracker_t reproduction_calls; + inline call_tracker_t crossover_allocations; + inline call_tracker_t mutation_allocations; + inline call_tracker_t reproduction_allocations; class gp_program; diff --git a/include/blt/gp/selection.h b/include/blt/gp/selection.h index a3c3856..bf1cc71 100644 --- a/include/blt/gp/selection.h +++ b/include/blt/gp/selection.h @@ -88,7 +88,9 @@ namespace blt::gp // everyone gets a chance once per loop. if (random.choice(config.crossover_chance)) { -// auto state = tracker.start_measurement(); +#ifdef BLT_TRACK_ALLOCATIONS + auto state = tracker.start_measurement(); +#endif // crossover const tree_t* p1; const tree_t* p2; @@ -97,37 +99,54 @@ namespace blt::gp p1 = &crossover_selection.select(program, current_pop); p2 = &crossover_selection.select(program, current_pop); } while (!config.crossover.get().apply(program, *p1, *p2, c1, *c2)); -// tracker.stop_measurement(state); -// BLT_TRACE("Crossover Allocated %ld times with a total of %s", state.getAllocationDifference(), -// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); +#ifdef BLT_TRACK_ALLOCATIONS + tracker.stop_measurement(state); + crossover_calls.call(); + if (state.getAllocationDifference() != 0) + crossover_allocations.call(state.getAllocatedByteDifference()); +#endif return 2; } break; case 1: if (random.choice(config.mutation_chance)) { -// auto state = tracker.start_measurement(); +#ifdef BLT_TRACK_ALLOCATIONS + auto state = tracker.start_measurement(); +#endif // mutation const tree_t* p; do { p = &mutation_selection.select(program, current_pop); } while (!config.mutator.get().apply(program, *p, c1)); -// tracker.stop_measurement(state); -// BLT_TRACE("Mutation Allocated %ld times with a total of %s", state.getAllocationDifference(), -// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); +#ifdef BLT_TRACK_ALLOCATIONS + tracker.stop_measurement(state); + mutation_calls.call(); + if (state.getAllocationDifference() != 0) + { + mutation_allocations.call(state.getAllocatedByteDifference()); + } +#endif return 1; } break; case 2: if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance)) { -// auto state = tracker.start_measurement(); +#ifdef BLT_TRACK_ALLOCATIONS + auto state = tracker.start_measurement(); +#endif // reproduction c1 = reproduction_selection.select(program, current_pop); -// tracker.stop_measurement(state); -// BLT_TRACE("Reproduction Allocated %ld times with a total of %s", state.getAllocationDifference(), -// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); +#ifdef BLT_TRACK_ALLOCATIONS + tracker.stop_measurement(state); + reproduction_calls.call(); + if (state.getAllocationDifference() != 0) + { + reproduction_allocations.call(state.getAllocatedByteDifference()); + } +#endif return 1; } break; diff --git a/include/blt/gp/stats.h b/include/blt/gp/stats.h index 64b3f13..9fda502 100644 --- a/include/blt/gp/stats.h +++ b/include/blt/gp/stats.h @@ -129,6 +129,68 @@ namespace blt::gp std::atomic_uint64_t deallocated_bytes = 0; }; + class call_tracker_t + { + public: + struct call_data_t + { + blt::u64 start_calls = 0; + blt::u64 start_value = 0; + blt::u64 end_calls = 0; + blt::u64 end_value = 0; + + [[nodiscard]] inline auto get_call_difference() const + { + return end_calls - start_calls; + } + + [[nodiscard]] inline auto get_value_difference() const + { + return end_value - start_value; + } + }; + + void value(blt::u64 value) + { + secondary_value += value; + } + + void call() + { + primary_calls++; + } + + void call(blt::u64 v) + { + primary_calls++; + value(v); + } + + [[nodiscard]] auto get_calls() const + { + return primary_calls.load(); + } + + [[nodiscard]] auto get_value() const + { + return secondary_value.load(); + } + + call_data_t start_measurement() + { + return {primary_calls.load(), 0}; + } + + void stop_measurement(call_data_t& data) + { + data.end_calls = primary_calls.load(); + } + + private: + std::atomic_uint64_t primary_calls = 0; + std::atomic_uint64_t secondary_value = 0; + }; + } #endif //BLT_GP_STATS_H From c89e2967ba12d024daa97430f92397bd06e0ae4f Mon Sep 17 00:00:00 2001 From: Brett Date: Sun, 1 Sep 2024 21:55:29 -0400 Subject: [PATCH 2/4] cleanup and allocations --- examples/symbolic_regression.cpp | 31 +++++++++++++++---------------- include/blt/gp/program.h | 18 +++++++++--------- include/blt/gp/selection.h | 6 +++--- lib/blt | 2 +- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index 69eac6d..44ce977 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -142,25 +142,24 @@ int main() #ifdef BLT_TRACK_ALLOCATIONS BLT_TRACE("Total Allocations: %ld times with a total of %s", blt::gp::tracker.getAllocations(), blt::byte_convert_t(blt::gp::tracker.getAllocatedBytes()).convert_to_nearest_type().to_pretty_string().c_str()); - auto crossover_calls = blt::gp::crossover_calls.get_calls(); - auto crossover_allocations = blt::gp::crossover_allocations.get_calls(); - auto mutation_calls = blt::gp::mutation_calls.get_calls(); - auto mutation_allocation = blt::gp::mutation_allocations.get_calls(); - auto reproduction_calls = blt::gp::reproduction_calls.get_calls(); - auto reproduction_allocation = blt::gp::reproduction_allocations.get_calls(); - BLT_TRACE("Total Crossover Calls: %ld", crossover_calls); - BLT_TRACE("Total Mutation Calls: %ld", mutation_calls); - BLT_TRACE("Total Reproduction Calls: %ld", reproduction_calls); - BLT_TRACE("Total Crossover Allocations: %ld", crossover_allocations); - BLT_TRACE("Total Mutation Allocations: %ld", mutation_allocation); - BLT_TRACE("Total Reproduction Allocations: %ld", reproduction_allocation); - + auto crossover_calls_v = blt::gp::crossover_calls.get_calls(); + auto crossover_allocations_v = blt::gp::crossover_allocations.get_calls(); + auto mutation_calls_v = blt::gp::mutation_calls.get_calls(); + auto mutation_allocations_v = blt::gp::mutation_allocations.get_calls(); + auto reproduction_calls_v = blt::gp::reproduction_calls.get_calls(); + auto reproduction_allocations_v = blt::gp::reproduction_allocations.get_calls(); + BLT_TRACE("Total Crossover Calls: %ld Bytes %s", crossover_calls_v, blt::byte_convert_t(blt::gp::crossover_calls.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); + BLT_TRACE("Total Mutation Calls: %ld Bytes %s", mutation_calls_v, blt::byte_convert_t(blt::gp::mutation_calls.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); + BLT_TRACE("Total Reproduction Calls: %ld Bytes %s", reproduction_calls_v, blt::byte_convert_t(blt::gp::reproduction_calls.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); + BLT_TRACE("Total Crossover Allocations: %ld Bytes %s", crossover_allocations_v, blt::byte_convert_t(blt::gp::crossover_allocations.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); + BLT_TRACE("Total Mutation Allocations: %ld Bytes %s", mutation_allocations_v, blt::byte_convert_t(blt::gp::mutation_allocations.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); + BLT_TRACE("Total Reproduction Allocations: %ld Bytes %s", reproduction_allocations_v, blt::byte_convert_t(blt::gp::reproduction_allocations.get_value()).convert_to_nearest_type().to_pretty_string().c_str()); BLT_TRACE("Percent Crossover calls allocate? %lf%%", - static_cast(crossover_allocations) / static_cast(crossover_calls == 0 ? 1 : crossover_calls) * 100); + static_cast(crossover_allocations_v) / static_cast(crossover_calls_v == 0 ? 1 : crossover_calls_v) * 100); BLT_TRACE("Percent Mutation calls allocate? %lf%%", - static_cast(mutation_allocation) / static_cast(mutation_calls == 0 ? 1 : mutation_calls) * 100); + static_cast(mutation_allocations_v) / static_cast(mutation_calls_v == 0 ? 1 : mutation_calls_v) * 100); BLT_TRACE("Percent Reproduction calls allocate? %lf%%", - static_cast(reproduction_allocation) / static_cast(reproduction_calls == 0 ? 1 : reproduction_calls) * 100); + static_cast(reproduction_allocations_v) / static_cast(reproduction_calls_v == 0 ? 1 : reproduction_calls_v) * 100); #endif return 0; diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index d682ee5..8c3c1e3 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -362,10 +362,6 @@ namespace blt::gp #ifdef BLT_TRACK_ALLOCATIONS auto gen_alloc = blt::gp::tracker.start_measurement(); #endif - BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size, - ("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str()); - BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size, - ("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str()); // should already be empty thread_helper.next_gen_left.store(config.population_size, std::memory_order_release); (*thread_execution_service)(0); @@ -378,10 +374,6 @@ namespace blt::gp void next_generation() { - BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size, - ("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str()); - BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size, - ("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str()); std::swap(current_pop, next_pop); current_generation++; } @@ -406,6 +398,10 @@ namespace blt::gp current_pop = config.pop_initializer.get().generate( {*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size}); next_pop = population_t(current_pop); + BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size, + ("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str()); + BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size, + ("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str()); if (eval_fitness_now) evaluate_fitness_internal(); } @@ -434,6 +430,10 @@ namespace blt::gp current_pop = config.pop_initializer.get().generate( {*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size}); next_pop = population_t(current_pop); + BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size, + ("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str()); + BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size, + ("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str()); if (config.threads == 1) { BLT_INFO("Starting with single thread variant!"); @@ -593,7 +593,7 @@ namespace blt::gp auto index = config.elites + begin; tree_t& c1 = next_pop.get_individuals()[index].tree; tree_t* c2 = nullptr; - if (index + 1 < end) + if (begin + 1 < end) c2 = &next_pop.get_individuals()[index + 1].tree; begin += func(args, crossover_selection, mutation_selection, reproduction_selection, c1, c2); } diff --git a/include/blt/gp/selection.h b/include/blt/gp/selection.h index bf1cc71..958a676 100644 --- a/include/blt/gp/selection.h +++ b/include/blt/gp/selection.h @@ -101,7 +101,7 @@ namespace blt::gp } while (!config.crossover.get().apply(program, *p1, *p2, c1, *c2)); #ifdef BLT_TRACK_ALLOCATIONS tracker.stop_measurement(state); - crossover_calls.call(); + crossover_calls.call(state.getAllocatedByteDifference()); if (state.getAllocationDifference() != 0) crossover_allocations.call(state.getAllocatedByteDifference()); #endif @@ -122,7 +122,7 @@ namespace blt::gp } while (!config.mutator.get().apply(program, *p, c1)); #ifdef BLT_TRACK_ALLOCATIONS tracker.stop_measurement(state); - mutation_calls.call(); + mutation_calls.call(state.getAllocatedByteDifference()); if (state.getAllocationDifference() != 0) { mutation_allocations.call(state.getAllocatedByteDifference()); @@ -141,7 +141,7 @@ namespace blt::gp c1 = reproduction_selection.select(program, current_pop); #ifdef BLT_TRACK_ALLOCATIONS tracker.stop_measurement(state); - reproduction_calls.call(); + reproduction_calls.call(state.getAllocatedByteDifference()); if (state.getAllocationDifference() != 0) { reproduction_allocations.call(state.getAllocatedByteDifference()); diff --git a/lib/blt b/lib/blt index 79e080c..ab482f1 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit 79e080cfd34fb47342f67f19b95ffa27efb0f715 +Subproject commit ab482f1a1c5782bd3501428f26c02f0bb4729946 From 5cf148191412c58766c78f6e5b422d341c620af7 Mon Sep 17 00:00:00 2001 From: Brett Date: Sun, 1 Sep 2024 22:15:32 -0400 Subject: [PATCH 3/4] silyl --- CMakeLists.txt | 2 +- include/blt/gp/fwdecl.h | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 967684f..2c01ac4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.38) +project(blt-gp VERSION 0.1.39) include(CTest) diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index 8311bac..5e751e2 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -28,6 +28,7 @@ namespace blt::gp { +#ifdef BLT_TRACK_ALLOCATIONS inline allocation_tracker_t tracker; inline call_tracker_t crossover_calls; inline call_tracker_t mutation_calls; @@ -35,6 +36,7 @@ namespace blt::gp inline call_tracker_t crossover_allocations; inline call_tracker_t mutation_allocations; inline call_tracker_t reproduction_allocations; +#endif class gp_program; @@ -66,9 +68,14 @@ namespace blt::gp template class tracked_allocator_t; - + +#ifdef BLT_TRACK_ALLOCATIONS template using tracked_vector = std::vector>; +#else + template + using tracked_vector = std::vector; +#endif // using operation_vector_t = tracked_vector; // using individual_vector_t = tracked_vector>; From ddcad0cbdb655daf4b8a0f1c314184a77827d0ef Mon Sep 17 00:00:00 2001 From: Brett Date: Sun, 1 Sep 2024 22:27:18 -0400 Subject: [PATCH 4/4] veryify program correctness --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c01ac4..e552fbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.39) +project(blt-gp VERSION 0.1.40) include(CTest)