Merge branch 'dev'

main
Brett 2024-09-01 22:27:33 -04:00
commit d69c45a82b
7 changed files with 136 additions and 44 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.1.37) project(blt-gp VERSION 0.1.40)
include(CTest) include(CTest)

View File

@ -106,35 +106,15 @@ int main()
{ {
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation()); BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
BLT_TRACE("Creating next 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"); BLT_START_INTERVAL("Symbolic Regression", "Gen");
program.create_next_generation(); program.create_next_generation();
BLT_END_INTERVAL("Symbolic Regression", "Gen"); 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_TRACE("Move to next generation");
BLT_START_INTERVAL("Symbolic Regression", "Fitness"); BLT_START_INTERVAL("Symbolic Regression", "Fitness");
program.next_generation(); program.next_generation();
BLT_TRACE("Evaluate Fitness"); BLT_TRACE("Evaluate Fitness");
program.evaluate_fitness(); program.evaluate_fitness();
BLT_END_INTERVAL("Symbolic Regression", "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("----------------------------------------------"); BLT_TRACE("----------------------------------------------");
std::cout << std::endl; std::cout << std::endl;
} }
@ -164,6 +144,24 @@ int main()
#ifdef BLT_TRACK_ALLOCATIONS #ifdef BLT_TRACK_ALLOCATIONS
BLT_TRACE("Total Allocations: %ld times with a total of %s", blt::gp::tracker.getAllocations(), 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()); blt::byte_convert_t(blt::gp::tracker.getAllocatedBytes()).convert_to_nearest_type().to_pretty_string().c_str());
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<double>(crossover_allocations_v) / static_cast<double>(crossover_calls_v == 0 ? 1 : crossover_calls_v) * 100);
BLT_TRACE("Percent Mutation calls allocate? %lf%%",
static_cast<double>(mutation_allocations_v) / static_cast<double>(mutation_calls_v == 0 ? 1 : mutation_calls_v) * 100);
BLT_TRACE("Percent Reproduction calls allocate? %lf%%",
static_cast<double>(reproduction_allocations_v) / static_cast<double>(reproduction_calls_v == 0 ? 1 : reproduction_calls_v) * 100);
#endif #endif
return 0; return 0;

View File

@ -28,7 +28,15 @@
namespace blt::gp namespace blt::gp
{ {
#ifdef BLT_TRACK_ALLOCATIONS
inline allocation_tracker_t tracker; 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;
#endif
class gp_program; class gp_program;
@ -61,8 +69,13 @@ namespace blt::gp
template<typename T> template<typename T>
class tracked_allocator_t; class tracked_allocator_t;
#ifdef BLT_TRACK_ALLOCATIONS
template<typename T> template<typename T>
using tracked_vector = std::vector<T, tracked_allocator_t<T>>; using tracked_vector = std::vector<T, tracked_allocator_t<T>>;
#else
template<typename T>
using tracked_vector = std::vector<T>;
#endif
// using operation_vector_t = tracked_vector<op_container_t>; // using operation_vector_t = tracked_vector<op_container_t>;
// using individual_vector_t = tracked_vector<individual_t, tracked_allocator_t<individual_t>>; // using individual_vector_t = tracked_vector<individual_t, tracked_allocator_t<individual_t>>;

View File

@ -362,10 +362,6 @@ namespace blt::gp
#ifdef BLT_TRACK_ALLOCATIONS #ifdef BLT_TRACK_ALLOCATIONS
auto gen_alloc = blt::gp::tracker.start_measurement(); auto gen_alloc = blt::gp::tracker.start_measurement();
#endif #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 // should already be empty
thread_helper.next_gen_left.store(config.population_size, std::memory_order_release); thread_helper.next_gen_left.store(config.population_size, std::memory_order_release);
(*thread_execution_service)(0); (*thread_execution_service)(0);
@ -378,10 +374,6 @@ namespace blt::gp
void next_generation() 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); std::swap(current_pop, next_pop);
current_generation++; current_generation++;
} }
@ -406,6 +398,10 @@ namespace blt::gp
current_pop = config.pop_initializer.get().generate( current_pop = config.pop_initializer.get().generate(
{*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size}); {*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size});
next_pop = population_t(current_pop); 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) if (eval_fitness_now)
evaluate_fitness_internal(); evaluate_fitness_internal();
} }
@ -434,6 +430,10 @@ namespace blt::gp
current_pop = config.pop_initializer.get().generate( current_pop = config.pop_initializer.get().generate(
{*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size}); {*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size});
next_pop = population_t(current_pop); 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) if (config.threads == 1)
{ {
BLT_INFO("Starting with single thread variant!"); BLT_INFO("Starting with single thread variant!");
@ -593,7 +593,7 @@ namespace blt::gp
auto index = config.elites + begin; auto index = config.elites + begin;
tree_t& c1 = next_pop.get_individuals()[index].tree; tree_t& c1 = next_pop.get_individuals()[index].tree;
tree_t* c2 = nullptr; tree_t* c2 = nullptr;
if (index + 1 < end) if (begin + 1 < end)
c2 = &next_pop.get_individuals()[index + 1].tree; c2 = &next_pop.get_individuals()[index + 1].tree;
begin += func(args, crossover_selection, mutation_selection, reproduction_selection, c1, c2); begin += func(args, crossover_selection, mutation_selection, reproduction_selection, c1, c2);
} }

View File

@ -88,7 +88,9 @@ namespace blt::gp
// everyone gets a chance once per loop. // everyone gets a chance once per loop.
if (random.choice(config.crossover_chance)) if (random.choice(config.crossover_chance))
{ {
// auto state = tracker.start_measurement(); #ifdef BLT_TRACK_ALLOCATIONS
auto state = tracker.start_measurement();
#endif
// crossover // crossover
const tree_t* p1; const tree_t* p1;
const tree_t* p2; const tree_t* p2;
@ -97,37 +99,54 @@ namespace blt::gp
p1 = &crossover_selection.select(program, current_pop); p1 = &crossover_selection.select(program, current_pop);
p2 = &crossover_selection.select(program, current_pop); p2 = &crossover_selection.select(program, current_pop);
} while (!config.crossover.get().apply(program, *p1, *p2, c1, *c2)); } while (!config.crossover.get().apply(program, *p1, *p2, c1, *c2));
// tracker.stop_measurement(state); #ifdef BLT_TRACK_ALLOCATIONS
// BLT_TRACE("Crossover Allocated %ld times with a total of %s", state.getAllocationDifference(), tracker.stop_measurement(state);
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); crossover_calls.call(state.getAllocatedByteDifference());
if (state.getAllocationDifference() != 0)
crossover_allocations.call(state.getAllocatedByteDifference());
#endif
return 2; return 2;
} }
break; break;
case 1: case 1:
if (random.choice(config.mutation_chance)) if (random.choice(config.mutation_chance))
{ {
// auto state = tracker.start_measurement(); #ifdef BLT_TRACK_ALLOCATIONS
auto state = tracker.start_measurement();
#endif
// mutation // mutation
const tree_t* p; const tree_t* p;
do do
{ {
p = &mutation_selection.select(program, current_pop); p = &mutation_selection.select(program, current_pop);
} while (!config.mutator.get().apply(program, *p, c1)); } while (!config.mutator.get().apply(program, *p, c1));
// tracker.stop_measurement(state); #ifdef BLT_TRACK_ALLOCATIONS
// BLT_TRACE("Mutation Allocated %ld times with a total of %s", state.getAllocationDifference(), tracker.stop_measurement(state);
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); mutation_calls.call(state.getAllocatedByteDifference());
if (state.getAllocationDifference() != 0)
{
mutation_allocations.call(state.getAllocatedByteDifference());
}
#endif
return 1; return 1;
} }
break; break;
case 2: case 2:
if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance)) 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 // reproduction
c1 = reproduction_selection.select(program, current_pop); c1 = reproduction_selection.select(program, current_pop);
// tracker.stop_measurement(state); #ifdef BLT_TRACK_ALLOCATIONS
// BLT_TRACE("Reproduction Allocated %ld times with a total of %s", state.getAllocationDifference(), tracker.stop_measurement(state);
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str()); reproduction_calls.call(state.getAllocatedByteDifference());
if (state.getAllocationDifference() != 0)
{
reproduction_allocations.call(state.getAllocatedByteDifference());
}
#endif
return 1; return 1;
} }
break; break;

View File

@ -129,6 +129,68 @@ namespace blt::gp
std::atomic_uint64_t deallocated_bytes = 0; 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 #endif //BLT_GP_STATS_H

@ -1 +1 @@
Subproject commit 79e080cfd34fb47342f67f19b95ffa27efb0f715 Subproject commit ab482f1a1c5782bd3501428f26c02f0bb4729946