Compare commits

...

2 Commits

Author SHA1 Message Date
Brett e5966789be annoying 2024-08-25 18:08:23 -04:00
Brett 95b88aeebf shared memory? 2024-08-25 17:01:06 -04:00
10 changed files with 87 additions and 40 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.23) project(blt-gp VERSION 0.1.26)
include(CTest) include(CTest)

View File

@ -170,6 +170,11 @@ int main()
BLT_PRINT_PROFILE("Symbolic Regression", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL); BLT_PRINT_PROFILE("Symbolic Regression", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL);
#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());
#endif
// BLT_TRACE("Allocations:"); // BLT_TRACE("Allocations:");
// auto h = static_cast<blt::ptrdiff_t>(blt::gp::hello.load()); // auto h = static_cast<blt::ptrdiff_t>(blt::gp::hello.load());
// auto u = static_cast<blt::ptrdiff_t>(blt::gp::unhello.load()); // auto u = static_cast<blt::ptrdiff_t>(blt::gp::unhello.load());

View File

@ -51,7 +51,7 @@ namespace blt::gp
class tree_generator_t class tree_generator_t
{ {
public: public:
virtual tree_t generate(const generator_arguments& args) = 0; virtual void generate(tree_t& out, const generator_arguments& args) = 0;
virtual ~tree_generator_t() = default; virtual ~tree_generator_t() = default;
}; };
@ -59,13 +59,13 @@ namespace blt::gp
class grow_generator_t : public tree_generator_t class grow_generator_t : public tree_generator_t
{ {
public: public:
tree_t generate(const generator_arguments& args) final; void generate(tree_t& out, const generator_arguments& args) final;
}; };
class full_generator_t : public tree_generator_t class full_generator_t : public tree_generator_t
{ {
public: public:
tree_t generate(const generator_arguments& args) final; void generate(tree_t& out, const generator_arguments& args) final;
}; };
class population_initializer_t class population_initializer_t

View File

@ -123,7 +123,6 @@ namespace blt::gp
static thread_local evaluation_context results{}; static thread_local evaluation_context results{};
results.values.reset(); results.values.reset();
results.values.reserve(largest); results.values.reserve(largest);
// BLT_DEBUG("%ld stored %ld", largest, results.values.internal_storage_size());
blt::size_t total_so_far = 0; blt::size_t total_so_far = 0;
@ -301,7 +300,7 @@ namespace blt::gp
template<typename... Operators, size_t... operator_ids> template<typename... Operators, size_t... operator_ids>
static inline void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, static inline void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack,
std::integer_sequence<size_t, operator_ids...>, Operators&... operators) std::integer_sequence<size_t, operator_ids...>, Operators& ... operators)
{ {
if (op >= sizeof...(operator_ids)) if (op >= sizeof...(operator_ids))
{ {
@ -502,22 +501,16 @@ namespace blt::gp
while (thread_helper.next_gen_left > 0) while (thread_helper.next_gen_left > 0)
{ {
blt::size_t size = 0; blt::size_t size = 0;
blt::size_t begin = 0;
blt::size_t end = thread_helper.next_gen_left.load(std::memory_order_relaxed); blt::size_t end = thread_helper.next_gen_left.load(std::memory_order_relaxed);
do do
{ {
size = std::min(end, config.evaluation_size); size = std::min(end, config.evaluation_size);
begin = end - size;
} while (!thread_helper.next_gen_left.compare_exchange_weak(end, end - size, } while (!thread_helper.next_gen_left.compare_exchange_weak(end, end - size,
std::memory_order::memory_order_relaxed, std::memory_order::memory_order_relaxed,
std::memory_order::memory_order_relaxed)); std::memory_order::memory_order_relaxed));
//auto measure = tracker.start_measurement(); while (new_children.size() < size)
for (blt::size_t i = begin; i < end; i++)
func(args, crossover_selection, mutation_selection, reproduction_selection); func(args, crossover_selection, mutation_selection, reproduction_selection);
//tracker.stop_measurement(measure);
//BLT_TRACE("Allocated %ld times with a total of %s", measure.getAllocationDifference(),
// blt::byte_convert_t(measure.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
{ {
std::scoped_lock lock(thread_helper.thread_generation_lock); std::scoped_lock lock(thread_helper.thread_generation_lock);
@ -548,6 +541,7 @@ namespace blt::gp
void next_generation() void next_generation()
{ {
BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size, ("pop size: " + std::to_string(next_pop.get_individuals().size())).c_str());
current_pop = std::move(next_pop); current_pop = std::move(next_pop);
current_generation++; current_generation++;
} }

View File

@ -24,6 +24,7 @@
#include <blt/gp/config.h> #include <blt/gp/config.h>
#include <blt/gp/random.h> #include <blt/gp/random.h>
#include <blt/std/assert.h> #include <blt/std/assert.h>
#include "blt/std/format.h"
namespace blt::gp namespace blt::gp
{ {
@ -84,6 +85,7 @@ 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();
// crossover // crossover
auto& p1 = crossover_selection.select(program, current_pop, current_stats); auto& p1 = crossover_selection.select(program, current_pop, current_stats);
auto& p2 = crossover_selection.select(program, current_pop, current_stats); auto& p2 = crossover_selection.select(program, current_pop, current_stats);
@ -94,24 +96,36 @@ namespace blt::gp
if (results) if (results)
{ {
next_pop.push_back(std::move(results->child1)); next_pop.push_back(std::move(results->child1));
next_pop.push_back(std::move(results->child2)); if (next_pop.size() != config.population_size)
next_pop.push_back(std::move(results->child2));
} }
// 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());
} }
break; break;
case 1: case 1:
if (random.choice(config.mutation_chance)) if (random.choice(config.mutation_chance))
{ {
// auto state = tracker.start_measurement();
// mutation // mutation
auto& p = mutation_selection.select(program, current_pop, current_stats); auto& p = mutation_selection.select(program, current_pop, current_stats);
next_pop.push_back(std::move(config.mutator.get().apply(program, p))); next_pop.push_back(std::move(config.mutator.get().apply(program, p)));
// 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());
} }
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();
// reproduction // reproduction
auto& p = reproduction_selection.select(program, current_pop, current_stats); auto& p = reproduction_selection.select(program, current_pop, current_stats);
next_pop.push_back(p); next_pop.push_back(p);
// 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());
} }
break; break;
default: default:

View File

@ -121,7 +121,7 @@ namespace blt::gp
return getAllocatedBytes() - getDeallocatedBytes(); return getAllocatedBytes() - getDeallocatedBytes();
} }
allocation_data_t start_measurement() [[nodiscard]] allocation_data_t start_measurement() const
{ {
allocation_data_t data{}; allocation_data_t data{};
data.start_allocations = allocations; data.start_allocations = allocations;
@ -131,7 +131,7 @@ namespace blt::gp
return data; return data;
} }
void stop_measurement(allocation_data_t& data) void stop_measurement(allocation_data_t& data) const
{ {
data.end_allocations = allocations; data.end_allocations = allocations;
data.end_deallocations = deallocations; data.end_deallocations = deallocations;

View File

@ -57,6 +57,8 @@ namespace blt::gp
public: public:
explicit tree_t(gp_program& program); explicit tree_t(gp_program& program);
void clear(gp_program& program);
struct child_t struct child_t
{ {
blt::ptrdiff_t start; blt::ptrdiff_t start;

View File

@ -49,11 +49,10 @@ namespace blt::gp
} }
template<typename Func> template<typename Func>
inline tree_t create_tree(Func&& perChild, const generator_arguments& args) inline void create_tree(tree_t& tree, Func&& perChild, const generator_arguments& args)
{ {
std::stack<stack> tree_generator = get_initial_stack(args.program, args.root_type); std::stack<stack> tree_generator = get_initial_stack(args.program, args.root_type);
blt::size_t max_depth = 0; blt::size_t max_depth = 0;
tree_t tree{args.program};
while (!tree_generator.empty()) while (!tree_generator.empty())
{ {
@ -77,13 +76,11 @@ namespace blt::gp
for (const auto& child : info.argument_types) for (const auto& child : info.argument_types)
std::forward<Func>(perChild)(args.program, tree_generator, child, top.depth + 1); std::forward<Func>(perChild)(args.program, tree_generator, child, top.depth + 1);
} }
return tree;
} }
tree_t grow_generator_t::generate(const generator_arguments& args) void grow_generator_t::generate(tree_t& tree, const generator_arguments& args)
{ {
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) { return create_tree(tree, [args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
if (new_depth >= args.max_depth) if (new_depth >= args.max_depth)
{ {
if (program.get_type_terminals(type).empty()) if (program.get_type_terminals(type).empty())
@ -99,9 +96,9 @@ namespace blt::gp
}, args); }, args);
} }
tree_t full_generator_t::generate(const generator_arguments& args) void full_generator_t::generate(tree_t& tree, const generator_arguments& args)
{ {
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) { return create_tree(tree, [args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
if (new_depth >= args.max_depth) if (new_depth >= args.max_depth)
{ {
if (program.get_type_terminals(type).empty()) if (program.get_type_terminals(type).empty())
@ -119,7 +116,11 @@ namespace blt::gp
population_t pop; population_t pop;
for (auto i = 0ul; i < args.size; i++) for (auto i = 0ul; i < args.size; i++)
pop.get_individuals().emplace_back(grow.generate(args.to_gen_args())); {
tree_t tree{args.program};
grow.generate(tree, args.to_gen_args());
pop.get_individuals().emplace_back(tree);
}
return pop; return pop;
} }
@ -129,7 +130,11 @@ namespace blt::gp
population_t pop; population_t pop;
for (auto i = 0ul; i < args.size; i++) for (auto i = 0ul; i < args.size; i++)
pop.get_individuals().emplace_back(full.generate(args.to_gen_args())); {
tree_t tree{args.program};
full.generate(tree, args.to_gen_args());
pop.get_individuals().emplace_back(tree);
}
return pop; return pop;
} }
@ -140,10 +145,12 @@ namespace blt::gp
for (auto i = 0ul; i < args.size; i++) for (auto i = 0ul; i < args.size; i++)
{ {
tree_t tree{args.program};
if (args.program.get_random().choice()) if (args.program.get_random().choice())
pop.get_individuals().emplace_back(full.generate(args.to_gen_args())); full.generate(tree, args.to_gen_args());
else else
pop.get_individuals().emplace_back(grow.generate(args.to_gen_args())); grow.generate(tree, args.to_gen_args());
pop.get_individuals().emplace_back(tree);
} }
return pop; return pop;
@ -160,22 +167,26 @@ namespace blt::gp
{ {
for (auto i = 0ul; i < per_step; i++) for (auto i = 0ul; i < per_step; i++)
{ {
tree_t tree{args.program};
if (args.program.get_random().choice()) if (args.program.get_random().choice())
pop.get_individuals().emplace_back(full.generate({args.program, args.root_type, args.min_depth, depth})); full.generate(tree, {args.program, args.root_type, args.min_depth, depth});
else else
pop.get_individuals().emplace_back(grow.generate({args.program, args.root_type, args.min_depth, depth})); grow.generate(tree, {args.program, args.root_type, args.min_depth, depth});
pop.get_individuals().emplace_back(tree);
} }
} }
for (auto i = 0ul; i < remainder; i++) for (auto i = 0ul; i < remainder; i++)
{ {
tree_t tree{args.program};
if (args.program.get_random().choice()) if (args.program.get_random().choice())
pop.get_individuals().emplace_back(full.generate(args.to_gen_args())); full.generate(tree, args.to_gen_args());
else else
pop.get_individuals().emplace_back(grow.generate(args.to_gen_args())); grow.generate(tree, args.to_gen_args());
pop.get_individuals().emplace_back(tree);
} }
blt_assert(pop.get_individuals().size() == args.size); BLT_ASSERT(pop.get_individuals().size() == args.size);
return pop; return pop;
} }

View File

@ -27,6 +27,15 @@
namespace blt::gp namespace blt::gp
{ {
grow_generator_t grow_generator;
inline tree_t& get_static_tree_tl(gp_program& program)
{
static thread_local tree_t new_tree{program};
new_tree.clear(program);
return new_tree;
}
inline blt::size_t accumulate_type_sizes(detail::op_iter begin, detail::op_iter end) inline blt::size_t accumulate_type_sizes(detail::op_iter begin, detail::op_iter end)
{ {
blt::size_t total = 0; blt::size_t total = 0;
@ -47,8 +56,6 @@ namespace blt::gp
return buffer.data(); return buffer.data();
} }
grow_generator_t grow_generator;
mutation_t::config_t::config_t(): generator(grow_generator) mutation_t::config_t::config_t(): generator(grow_generator)
{} {}
@ -228,7 +235,8 @@ namespace blt::gp
auto begin_itr = ops_r.begin() + begin_point; auto begin_itr = ops_r.begin() + begin_point;
auto end_itr = ops_r.begin() + end_point; auto end_itr = ops_r.begin() + end_point;
auto new_tree = config.generator.get().generate({program, type_info.return_type, config.replacement_min_depth, config.replacement_max_depth}); auto& new_tree = get_static_tree_tl(program);
config.generator.get().generate(new_tree, {program, type_info.return_type, config.replacement_min_depth, config.replacement_max_depth});
auto& new_ops_r = new_tree.get_operations(); auto& new_ops_r = new_tree.get_operations();
auto& new_vals_r = new_tree.get_values(); auto& new_vals_r = new_tree.get_values();
@ -364,7 +372,8 @@ namespace blt::gp
if (index < current_func_info.argument_types.size() && val.id != current_func_info.argument_types[index].id) if (index < current_func_info.argument_types.size() && val.id != current_func_info.argument_types[index].id)
{ {
// TODO: new config? // TODO: new config?
auto tree = config.generator.get().generate( auto& tree = get_static_tree_tl(program);
config.generator.get().generate(tree,
{program, val.id, config.replacement_min_depth, config.replacement_max_depth}); {program, val.id, config.replacement_min_depth, config.replacement_max_depth});
auto& child = children_data[children_data.size() - 1 - index]; auto& child = children_data[children_data.size() - 1 - index];
@ -445,7 +454,8 @@ namespace blt::gp
for (blt::ptrdiff_t i = static_cast<blt::ptrdiff_t>(replacement_func_info.argc.argc) - 1; for (blt::ptrdiff_t i = static_cast<blt::ptrdiff_t>(replacement_func_info.argc.argc) - 1;
i >= current_func_info.argc.argc; i--) i >= current_func_info.argc.argc; i--)
{ {
auto tree = config.generator.get().generate( auto& tree = get_static_tree_tl(program);
config.generator.get().generate(tree,
{program, replacement_func_info.argument_types[i].id, config.replacement_min_depth, {program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
config.replacement_max_depth}); config.replacement_max_depth});
blt::size_t total_bytes_for = tree.total_value_bytes(); blt::size_t total_bytes_for = tree.total_value_bytes();
@ -518,7 +528,8 @@ namespace blt::gp
blt::size_t start_index = c_node; blt::size_t start_index = c_node;
for (blt::ptrdiff_t i = new_argc - 1; i > static_cast<blt::ptrdiff_t>(arg_position); i--) for (blt::ptrdiff_t i = new_argc - 1; i > static_cast<blt::ptrdiff_t>(arg_position); i--)
{ {
auto tree = config.generator.get().generate( auto& tree = get_static_tree_tl(program);
config.generator.get().generate(tree,
{program, replacement_func_info.argument_types[i].id, config.replacement_min_depth, {program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
config.replacement_max_depth}); config.replacement_max_depth});
blt::size_t total_bytes_for = tree.total_value_bytes(); blt::size_t total_bytes_for = tree.total_value_bytes();
@ -531,7 +542,8 @@ namespace blt::gp
vals.copy_from(combined_ptr, for_bytes); vals.copy_from(combined_ptr, for_bytes);
for (blt::ptrdiff_t i = static_cast<blt::ptrdiff_t>(arg_position) - 1; i >= 0; i--) for (blt::ptrdiff_t i = static_cast<blt::ptrdiff_t>(arg_position) - 1; i >= 0; i--)
{ {
auto tree = config.generator.get().generate( auto& tree = get_static_tree_tl(program);
config.generator.get().generate(tree,
{program, replacement_func_info.argument_types[i].id, config.replacement_min_depth, {program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
config.replacement_max_depth}); config.replacement_max_depth});
blt::size_t total_bytes_for = tree.total_value_bytes(); blt::size_t total_bytes_for = tree.total_value_bytes();

View File

@ -299,4 +299,13 @@ namespace blt::gp
{ {
} }
void tree_t::clear(gp_program& program)
{
auto* f = &program.get_eval_func();
if (f != func)
func = f;
operations.clear();
values.reset();
}
} }