silly
parent
034071dae3
commit
b232aaccf8
|
@ -6,3 +6,5 @@ out/
|
||||||
./out/
|
./out/
|
||||||
massif.*
|
massif.*
|
||||||
callgrind.*
|
callgrind.*
|
||||||
|
*.out.*
|
||||||
|
heaptrack.*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.69)
|
project(blt-gp VERSION 0.0.74)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ option(DEBUG_LEVEL "Enable debug features which prints extra information to the
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
add_subdirectory(lib/blt)
|
add_subdirectory(lib/blt)
|
||||||
|
|
||||||
include_directories(include/)
|
include_directories(include/)
|
||||||
|
@ -21,7 +24,7 @@ add_library(blt-gp ${PROJECT_BUILD_FILES})
|
||||||
target_compile_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment)
|
target_compile_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment)
|
||||||
target_link_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment)
|
target_link_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment)
|
||||||
|
|
||||||
target_link_libraries(blt-gp PRIVATE BLT)
|
target_link_libraries(blt-gp PRIVATE BLT Threads::Threads)
|
||||||
target_compile_definitions(blt-gp PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL})
|
target_compile_definitions(blt-gp PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL})
|
||||||
|
|
||||||
if (${ENABLE_ADDRSAN} MATCHES ON)
|
if (${ENABLE_ADDRSAN} MATCHES ON)
|
||||||
|
@ -46,7 +49,7 @@ if (${BUILD_EXAMPLES})
|
||||||
|
|
||||||
add_executable(${name}-example ${source})
|
add_executable(${name}-example ${source})
|
||||||
|
|
||||||
target_link_libraries(${name}-example PRIVATE BLT blt-gp)
|
target_link_libraries(${name}-example PRIVATE BLT blt-gp Threads::Threads)
|
||||||
|
|
||||||
target_compile_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
target_compile_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
||||||
target_link_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
target_link_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
||||||
|
|
|
@ -36,8 +36,8 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t()
|
||||||
.set_initial_max_tree_size(6)
|
.set_initial_max_tree_size(6)
|
||||||
.set_elite_count(0)
|
.set_elite_count(0)
|
||||||
.set_max_generations(50)
|
.set_max_generations(50)
|
||||||
.set_pop_size(500)
|
.set_pop_size(5000)
|
||||||
.set_thread_count(1);
|
.set_thread_count(0);
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_provider type_system;
|
||||||
blt::gp::gp_program program{type_system, SEED, config};
|
blt::gp::gp_program program{type_system, SEED, config};
|
||||||
|
@ -83,7 +83,9 @@ float example_function(float x)
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
BLT_INFO("Starting BLT-GP Symbolic Regression Example");
|
||||||
BLT_START_INTERVAL("Symbolic Regression", "Main");
|
BLT_START_INTERVAL("Symbolic Regression", "Main");
|
||||||
|
BLT_DEBUG("Setup Fitness cases");
|
||||||
for (auto& fitness_case : fitness_cases)
|
for (auto& fitness_case : fitness_cases)
|
||||||
{
|
{
|
||||||
constexpr float range = 10;
|
constexpr float range = 10;
|
||||||
|
@ -93,6 +95,7 @@ int main()
|
||||||
fitness_case = {x, y};
|
fitness_case = {x, y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLT_DEBUG("Setup Types and Operators");
|
||||||
type_system.register_type<float>();
|
type_system.register_type<float>();
|
||||||
|
|
||||||
blt::gp::operator_builder<context> builder{type_system};
|
blt::gp::operator_builder<context> builder{type_system};
|
||||||
|
@ -110,17 +113,24 @@ int main()
|
||||||
|
|
||||||
program.set_operations(builder.build());
|
program.set_operations(builder.build());
|
||||||
|
|
||||||
|
BLT_DEBUG("Generate Initial Population");
|
||||||
program.generate_population(type_system.get_type<float>().id(), fitness_function);
|
program.generate_population(type_system.get_type<float>().id(), fitness_function);
|
||||||
|
|
||||||
|
BLT_DEBUG("Begin Generation Loop");
|
||||||
while (!program.should_terminate())
|
while (!program.should_terminate())
|
||||||
{
|
{
|
||||||
|
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
|
||||||
BLT_START_INTERVAL("Symbolic Regression", "Gen");
|
BLT_START_INTERVAL("Symbolic Regression", "Gen");
|
||||||
program.create_next_generation(blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{});
|
program.create_next_generation(blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{});
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Gen");
|
BLT_END_INTERVAL("Symbolic Regression", "Gen");
|
||||||
|
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");
|
||||||
program.evaluate_fitness();
|
program.evaluate_fitness();
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Fitness");
|
BLT_END_INTERVAL("Symbolic Regression", "Fitness");
|
||||||
|
BLT_TRACE("----------------------------------------------");
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Main");
|
BLT_END_INTERVAL("Symbolic Regression", "Main");
|
||||||
|
|
|
@ -131,6 +131,8 @@ namespace blt::gp
|
||||||
|
|
||||||
prog_config_t& set_thread_count(blt::size_t t)
|
prog_config_t& set_thread_count(blt::size_t t)
|
||||||
{
|
{
|
||||||
|
if (t == 0)
|
||||||
|
t = std::thread::hardware_concurrency();
|
||||||
threads = t;
|
threads = t;
|
||||||
//evaluation_size = (population_size / threads) / 2;
|
//evaluation_size = (population_size / threads) / 2;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <blt/std/ranges.h>
|
#include <blt/std/ranges.h>
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
|
@ -52,6 +54,79 @@
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Author: Kirk Saunders (ks825016@ohio.edu)
|
||||||
|
// Description: Simple implementation of a thread barrier
|
||||||
|
// using C++ condition variables.
|
||||||
|
// Date: 2/17/2020
|
||||||
|
|
||||||
|
// https://github.com/kirksaunders/barrier/blob/master/barrier.hpp
|
||||||
|
class barrier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Construct barrier for use with num threads.
|
||||||
|
explicit barrier(std::atomic_bool& exit_cond, std::size_t num)
|
||||||
|
: num_threads(num),
|
||||||
|
wait_count(0),
|
||||||
|
instance(0),
|
||||||
|
mut(),
|
||||||
|
cv(),
|
||||||
|
exit_cond(exit_cond)
|
||||||
|
{
|
||||||
|
if (num == 0)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Barrier thread count cannot be 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable copying of barrier
|
||||||
|
barrier(const barrier&) = delete;
|
||||||
|
|
||||||
|
barrier& operator=(const barrier&) = delete;
|
||||||
|
|
||||||
|
// This function blocks the calling thread until
|
||||||
|
// all threads (specified by num_threads) have
|
||||||
|
// called it. Blocking is achieved using a
|
||||||
|
// call to condition_variable.wait().
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mut); // acquire lock
|
||||||
|
std::size_t inst = instance; // store current instance for comparison
|
||||||
|
// in predicate
|
||||||
|
|
||||||
|
if (++wait_count == num_threads)
|
||||||
|
{ // all threads reached barrier
|
||||||
|
wait_count = 0; // reset wait_count
|
||||||
|
instance++; // increment instance for next use of barrier and to
|
||||||
|
// pass condition variable predicate
|
||||||
|
cv.notify_all();
|
||||||
|
} else
|
||||||
|
{ // not all threads have reached barrier
|
||||||
|
cv.wait(lock, [this, &inst]() { return (instance != inst || exit_cond); });
|
||||||
|
// NOTE: The predicate lambda here protects against spurious
|
||||||
|
// wakeups of the thread. As long as this->instance is
|
||||||
|
// equal to inst, the thread will not wake.
|
||||||
|
// this->instance will only increment when all threads
|
||||||
|
// have reached the barrier and are ready to be unblocked.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify_all()
|
||||||
|
{
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t num_threads; // number of threads using barrier
|
||||||
|
std::size_t wait_count; // counter to keep track of waiting threads
|
||||||
|
std::size_t instance; // counter to keep track of barrier use count
|
||||||
|
std::mutex mut; // mutex used to protect resources
|
||||||
|
std::condition_variable cv; // condition variable used to block threads
|
||||||
|
std::atomic_bool& exit_cond; // used to signal we should exit
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct argc_t
|
struct argc_t
|
||||||
{
|
{
|
||||||
blt::u32 argc = 0;
|
blt::u32 argc = 0;
|
||||||
|
@ -74,7 +149,7 @@ namespace blt::gp
|
||||||
// function to call this operator
|
// function to call this operator
|
||||||
detail::callable_t function;
|
detail::callable_t function;
|
||||||
// function used to transfer values between stacks
|
// function used to transfer values between stacks
|
||||||
detail::transfer_t transfer;
|
//detail::transfer_t transfer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct operator_storage
|
struct operator_storage
|
||||||
|
@ -125,24 +200,24 @@ namespace blt::gp
|
||||||
BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!");
|
BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!");
|
||||||
|
|
||||||
info.function = op.template make_callable<Context>();
|
info.function = op.template make_callable<Context>();
|
||||||
info.transfer = [](std::optional<std::reference_wrapper<stack_allocator>> to, stack_allocator& from) {
|
// info.transfer = [](std::optional<std::reference_wrapper<stack_allocator>> to, stack_allocator& from) {
|
||||||
#if BLT_DEBUG_LEVEL >= 3
|
//#if BLT_DEBUG_LEVEL >= 3
|
||||||
auto value = from.pop<Return>();
|
// auto value = from.pop<Return>();
|
||||||
//BLT_TRACE_STREAM << value << "\n";
|
// //BLT_TRACE_STREAM << value << "\n";
|
||||||
if (to){
|
// if (to){
|
||||||
to->get().push(value);
|
// to->get().push(value);
|
||||||
}
|
// }
|
||||||
#else
|
//#else
|
||||||
if (to)
|
// if (to)
|
||||||
{
|
// {
|
||||||
to->get().push(from.pop<Return>());
|
// to->get().push(from.pop<Return>());
|
||||||
} else
|
// } else
|
||||||
{
|
// {
|
||||||
from.pop<Return>();
|
// from.pop<Return>();
|
||||||
}
|
// }
|
||||||
#endif
|
//#endif
|
||||||
|
//
|
||||||
};
|
// };
|
||||||
storage.operators.push_back(info);
|
storage.operators.push_back(info);
|
||||||
storage.print_funcs.push_back([](std::ostream& out, stack_allocator& stack) {
|
storage.print_funcs.push_back([](std::ostream& out, stack_allocator& stack) {
|
||||||
out << stack.pop<Return>();
|
out << stack.pop<Return>();
|
||||||
|
@ -285,7 +360,8 @@ namespace blt::gp
|
||||||
{*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});
|
||||||
if (config.threads == 1)
|
if (config.threads == 1)
|
||||||
{
|
{
|
||||||
thread_execution_service = new std::function([this, &fitness_function]() {
|
BLT_INFO("Starting with single thread variant!");
|
||||||
|
thread_execution_service = new std::function([this, &fitness_function](blt::size_t) {
|
||||||
for (const auto& ind : blt::enumerate(current_pop.get_individuals()))
|
for (const auto& ind : blt::enumerate(current_pop.get_individuals()))
|
||||||
{
|
{
|
||||||
fitness_function(ind.second.tree, ind.second.fitness, ind.first);
|
fitness_function(ind.second.tree, ind.second.fitness, ind.first);
|
||||||
|
@ -300,23 +376,24 @@ namespace blt::gp
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
thread_execution_service = new std::function([this, &fitness_function]() {
|
BLT_INFO("Starting thread execution service!");
|
||||||
|
std::scoped_lock lock(thread_helper.thread_function_control);
|
||||||
|
thread_execution_service = new std::function([this, &fitness_function](blt::size_t) {
|
||||||
|
thread_helper.barrier.wait();
|
||||||
if (thread_helper.evaluation_left > 0)
|
if (thread_helper.evaluation_left > 0)
|
||||||
{
|
{
|
||||||
thread_helper.threads_left.fetch_add(1, std::memory_order::memory_order_relaxed);
|
|
||||||
while (thread_helper.evaluation_left > 0)
|
while (thread_helper.evaluation_left > 0)
|
||||||
{
|
{
|
||||||
blt::size_t size = 0;
|
blt::size_t size = 0;
|
||||||
blt::size_t begin = 0;
|
blt::size_t begin = 0;
|
||||||
blt::size_t end = thread_helper.evaluation_left.load(std::memory_order_acquire);
|
blt::size_t end = thread_helper.evaluation_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;
|
begin = end - size;
|
||||||
} while (!thread_helper.evaluation_left.compare_exchange_weak(end, end - size,
|
} while (!thread_helper.evaluation_left.compare_exchange_weak(end, end - size,
|
||||||
std::memory_order::memory_order_release,
|
std::memory_order::memory_order_relaxed,
|
||||||
std::memory_order::memory_order_acquire));
|
std::memory_order::memory_order_relaxed));
|
||||||
|
|
||||||
for (blt::size_t i = begin; i < end; i++)
|
for (blt::size_t i = begin; i < end; i++)
|
||||||
{
|
{
|
||||||
auto& ind = current_pop.get_individuals()[i];
|
auto& ind = current_pop.get_individuals()[i];
|
||||||
|
@ -326,22 +403,22 @@ namespace blt::gp
|
||||||
auto old_best = current_stats.best_fitness.load(std::memory_order_relaxed);
|
auto old_best = current_stats.best_fitness.load(std::memory_order_relaxed);
|
||||||
while (ind.fitness.adjusted_fitness > old_best &&
|
while (ind.fitness.adjusted_fitness > old_best &&
|
||||||
!current_stats.best_fitness.compare_exchange_weak(old_best, ind.fitness.adjusted_fitness,
|
!current_stats.best_fitness.compare_exchange_weak(old_best, ind.fitness.adjusted_fitness,
|
||||||
std::memory_order_release, std::memory_order_relaxed));
|
std::memory_order_relaxed, std::memory_order_relaxed));
|
||||||
|
|
||||||
auto old_worst = current_stats.worst_fitness.load(std::memory_order_relaxed);
|
auto old_worst = current_stats.worst_fitness.load(std::memory_order_relaxed);
|
||||||
while (ind.fitness.adjusted_fitness < old_worst &&
|
while (ind.fitness.adjusted_fitness < old_worst &&
|
||||||
!current_stats.worst_fitness.compare_exchange_weak(old_worst, ind.fitness.adjusted_fitness,
|
!current_stats.worst_fitness.compare_exchange_weak(old_worst, ind.fitness.adjusted_fitness,
|
||||||
std::memory_order_release, std::memory_order_relaxed));
|
std::memory_order_relaxed, std::memory_order_relaxed));
|
||||||
|
|
||||||
auto old_overall = current_stats.overall_fitness.load(std::memory_order_relaxed);
|
auto old_overall = current_stats.overall_fitness.load(std::memory_order_relaxed);
|
||||||
while (!current_stats.overall_fitness.compare_exchange_weak(old_overall,
|
while (!current_stats.overall_fitness.compare_exchange_weak(old_overall,
|
||||||
ind.fitness.adjusted_fitness + old_overall,
|
ind.fitness.adjusted_fitness + old_overall,
|
||||||
std::memory_order_release,
|
std::memory_order_relaxed,
|
||||||
std::memory_order_relaxed));
|
std::memory_order_relaxed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thread_helper.threads_left.fetch_sub(1, std::memory_order::memory_order_relaxed);
|
|
||||||
}
|
}
|
||||||
|
thread_helper.barrier.wait();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
evaluate_fitness_internal();
|
evaluate_fitness_internal();
|
||||||
|
@ -482,6 +559,7 @@ namespace blt::gp
|
||||||
~gp_program()
|
~gp_program()
|
||||||
{
|
{
|
||||||
thread_helper.lifetime_over = true;
|
thread_helper.lifetime_over = true;
|
||||||
|
thread_helper.barrier.notify_all();
|
||||||
for (auto& thread : thread_helper.threads)
|
for (auto& thread : thread_helper.threads)
|
||||||
{
|
{
|
||||||
if (thread->joinable())
|
if (thread->joinable())
|
||||||
|
@ -507,15 +585,18 @@ namespace blt::gp
|
||||||
struct concurrency_storage
|
struct concurrency_storage
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<std::thread>> threads;
|
std::vector<std::unique_ptr<std::thread>> threads;
|
||||||
//std::mutex evaluation_control;
|
std::mutex thread_function_control;
|
||||||
std::atomic_uint64_t evaluation_left = 0;
|
std::atomic_uint64_t evaluation_left = 0;
|
||||||
std::atomic_int64_t threads_left = 0;
|
|
||||||
|
|
||||||
std::atomic_bool lifetime_over = false;
|
std::atomic_bool lifetime_over = false;
|
||||||
} thread_helper;
|
detail::barrier barrier;
|
||||||
|
|
||||||
|
explicit concurrency_storage(blt::size_t threads): barrier(lifetime_over, threads)
|
||||||
|
{}
|
||||||
|
} thread_helper{config.threads};
|
||||||
|
|
||||||
// for convenience, shouldn't decrease performance too much
|
// for convenience, shouldn't decrease performance too much
|
||||||
std::atomic<std::function<void()>*> thread_execution_service = nullptr;
|
std::atomic<std::function<void(blt::size_t)>*> thread_execution_service = nullptr;
|
||||||
|
|
||||||
inline selector_args get_selector_args()
|
inline selector_args get_selector_args()
|
||||||
{
|
{
|
||||||
|
@ -534,52 +615,11 @@ namespace blt::gp
|
||||||
void evaluate_fitness_internal()
|
void evaluate_fitness_internal()
|
||||||
{
|
{
|
||||||
current_stats.clear();
|
current_stats.clear();
|
||||||
if (config.threads == 1)
|
if (config.threads != 1)
|
||||||
{
|
thread_helper.evaluation_left.store(current_pop.get_individuals().size(), std::memory_order_release);
|
||||||
(*thread_execution_service)();
|
(*thread_execution_service)(0);
|
||||||
} else
|
|
||||||
{
|
|
||||||
{
|
|
||||||
//std::scoped_lock lock(thread_helper.evaluation_control);
|
|
||||||
thread_helper.evaluation_left.store(current_pop.get_individuals().size(), std::memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << "Func" << std::endl;
|
|
||||||
while (thread_execution_service == nullptr)
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
//std::cout << "Wait" << std::endl;
|
|
||||||
(*thread_execution_service)();
|
|
||||||
//std::cout << "FINSIHED WAITING!!!!!!!! " << thread_helper.threads_left << std::endl;
|
|
||||||
while (thread_helper.threads_left > 0)
|
|
||||||
{
|
|
||||||
//std::cout << thread_helper.threads_left << std::endl;
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
//std::cout << "Finished" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_stats.average_fitness = current_stats.overall_fitness / static_cast<double>(config.population_size);
|
current_stats.average_fitness = current_stats.overall_fitness / static_cast<double>(config.population_size);
|
||||||
|
|
||||||
|
|
||||||
/*current_stats = {};
|
|
||||||
for (const auto& ind : blt::enumerate(current_pop.get_individuals()))
|
|
||||||
{
|
|
||||||
fitness_function(ind.second.tree, ind.second.fitness, ind.first);
|
|
||||||
if (ind.second.fitness.adjusted_fitness > current_stats.best_fitness)
|
|
||||||
{
|
|
||||||
current_stats.best_fitness = ind.second.fitness.adjusted_fitness;
|
|
||||||
current_stats.best_individual = &ind.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ind.second.fitness.adjusted_fitness < current_stats.worst_fitness)
|
|
||||||
{
|
|
||||||
current_stats.worst_fitness = ind.second.fitness.adjusted_fitness;
|
|
||||||
current_stats.worst_individual = &ind.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_stats.overall_fitness += ind.second.fitness.adjusted_fitness;
|
|
||||||
}
|
|
||||||
current_stats.average_fitness = current_stats.overall_fitness / static_cast<double>(config.population_size);*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,15 +73,14 @@ namespace blt::gp
|
||||||
if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(aligned_size<T>()))
|
if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(aligned_size<T>()))
|
||||||
throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string(
|
throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string(
|
||||||
head->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(T))).c_str());
|
head->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(T))).c_str());
|
||||||
|
if (head->used_bytes_in_block() == 0)
|
||||||
|
move_back();
|
||||||
// make copy
|
// make copy
|
||||||
T t = *reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE);
|
T t = *reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE);
|
||||||
// call destructor
|
// call destructor
|
||||||
reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE)->~T();
|
reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE)->~T();
|
||||||
|
// move offset back
|
||||||
head->metadata.offset -= TYPE_SIZE;
|
head->metadata.offset -= TYPE_SIZE;
|
||||||
if (head->used_bytes_in_block() == 0)
|
|
||||||
{
|
|
||||||
move_back();
|
|
||||||
}
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +139,9 @@ namespace blt::gp
|
||||||
if (diff <= 0)
|
if (diff <= 0)
|
||||||
{
|
{
|
||||||
bytes -= head->used_bytes_in_block();
|
bytes -= head->used_bytes_in_block();
|
||||||
move_back();
|
|
||||||
if (diff == 0)
|
if (diff == 0)
|
||||||
break;
|
break;
|
||||||
|
move_back();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// otherwise update the offset pointer
|
// otherwise update the offset pointer
|
||||||
|
@ -164,13 +163,15 @@ namespace blt::gp
|
||||||
throw std::runtime_error("This stack is empty!");
|
throw std::runtime_error("This stack is empty!");
|
||||||
if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(bytes))
|
if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(bytes))
|
||||||
BLT_ABORT("This stack doesn't contain enough data for this type! This is an invalid runtime state!");
|
BLT_ABORT("This stack doesn't contain enough data for this type! This is an invalid runtime state!");
|
||||||
|
|
||||||
|
if (head->used_bytes_in_block() == 0)
|
||||||
|
move_back();
|
||||||
|
|
||||||
auto type_size = aligned_size(bytes);
|
auto type_size = aligned_size(bytes);
|
||||||
auto ptr = to.allocate_bytes(bytes);
|
auto ptr = to.allocate_bytes(bytes);
|
||||||
to.head->metadata.offset = static_cast<blt::u8*>(ptr) + type_size;
|
to.head->metadata.offset = static_cast<blt::u8*>(ptr) + type_size;
|
||||||
std::memcpy(ptr, head->metadata.offset - type_size, type_size);
|
std::memcpy(ptr, head->metadata.offset - type_size, type_size);
|
||||||
head->metadata.offset -= type_size;
|
head->metadata.offset -= type_size;
|
||||||
if (head->used_bytes_in_block() == 0)
|
|
||||||
move_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -218,10 +219,7 @@ namespace blt::gp
|
||||||
|
|
||||||
stack_allocator() = default;
|
stack_allocator() = default;
|
||||||
|
|
||||||
// it should be possible to remove the complex copy contrusctor along with trasnfer functions
|
// TODO: cleanup this allocator!
|
||||||
// simply keep track of the start of the stack, aloing with the current pointer and never dealloacted
|
|
||||||
// it adds another 8 bytes to each block but should prevent the need for copying when you can just reset the stack.
|
|
||||||
// (read copy)
|
|
||||||
// if you keep track of type size information you can memcpy between stack allocators as you already only allow trivially copyable types
|
// if you keep track of type size information you can memcpy between stack allocators as you already only allow trivially copyable types
|
||||||
stack_allocator(const stack_allocator& copy)
|
stack_allocator(const stack_allocator& copy)
|
||||||
{
|
{
|
||||||
|
@ -401,7 +399,10 @@ namespace blt::gp
|
||||||
auto old = head;
|
auto old = head;
|
||||||
head = head->metadata.prev;
|
head = head->metadata.prev;
|
||||||
if (head == nullptr)
|
if (head == nullptr)
|
||||||
|
{
|
||||||
head = old;
|
head = old;
|
||||||
|
head->reset();
|
||||||
|
}
|
||||||
//free_chain(old);
|
//free_chain(old);
|
||||||
// required to prevent silly memory :3
|
// required to prevent silly memory :3
|
||||||
// if (head != nullptr)
|
// if (head != nullptr)
|
||||||
|
|
|
@ -34,12 +34,16 @@ namespace blt::gp
|
||||||
|
|
||||||
struct op_container_t
|
struct op_container_t
|
||||||
{
|
{
|
||||||
op_container_t(detail::callable_t& func, detail::transfer_t& transfer, operator_id id, bool is_value):
|
// op_container_t(detail::callable_t& func, detail::transfer_t& transfer, operator_id id, bool is_value):
|
||||||
func(func), transfer(transfer), id(id), is_value(is_value)
|
// func(func), transfer(transfer), id(id), is_value(is_value)
|
||||||
|
// {}
|
||||||
|
op_container_t(detail::callable_t& func, blt::size_t type_size, operator_id id, bool is_value):
|
||||||
|
func(func), type_size(type_size), id(id), is_value(is_value)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::reference_wrapper<detail::callable_t> func;
|
std::reference_wrapper<detail::callable_t> func;
|
||||||
std::reference_wrapper<detail::transfer_t> transfer;
|
blt::size_t type_size;
|
||||||
|
//std::reference_wrapper<detail::transfer_t> transfer;
|
||||||
operator_id id;
|
operator_id id;
|
||||||
bool is_value;
|
bool is_value;
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace blt::gp
|
||||||
|
|
||||||
tree.get_operations().emplace_back(
|
tree.get_operations().emplace_back(
|
||||||
info.function,
|
info.function,
|
||||||
info.transfer,
|
args.program.get_typesystem().get_type(info.return_type).size(),
|
||||||
top.id,
|
top.id,
|
||||||
args.program.is_static(top.id));
|
args.program.is_static(top.id));
|
||||||
max_depth = std::max(max_depth, top.depth);
|
max_depth = std::max(max_depth, top.depth);
|
||||||
|
|
|
@ -57,11 +57,19 @@ namespace blt::gp
|
||||||
// main thread is thread0
|
// main thread is thread0
|
||||||
for (blt::size_t i = 1; i < config.threads; i++)
|
for (blt::size_t i = 1; i < config.threads; i++)
|
||||||
{
|
{
|
||||||
thread_helper.threads.emplace_back(new std::thread([this]() {
|
thread_helper.threads.emplace_back(new std::thread([i, this]() {
|
||||||
|
std::function<void(blt::size_t)>* execution_function = nullptr;
|
||||||
while (!should_thread_terminate())
|
while (!should_thread_terminate())
|
||||||
{
|
{
|
||||||
if (thread_execution_service != nullptr)
|
if (execution_function == nullptr)
|
||||||
(*thread_execution_service)();
|
{
|
||||||
|
std::scoped_lock lock(thread_helper.thread_function_control);
|
||||||
|
if (thread_execution_service != nullptr)
|
||||||
|
execution_function = thread_execution_service.load(std::memory_order_acquire);
|
||||||
|
std::cout.flush();
|
||||||
|
}
|
||||||
|
if (execution_function != nullptr)
|
||||||
|
(*execution_function)(i);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -169,7 +169,7 @@ namespace blt::gp
|
||||||
for (auto it = c1_ops.end() - 1; it != crossover_point_end_itr - 1; it--)
|
for (auto it = c1_ops.end() - 1; it != crossover_point_end_itr - 1; it--)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c1_stack_after_copy, c1_stack_init);
|
c1_stack_init.transfer_bytes(c1_stack_after_copy, it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -179,7 +179,7 @@ namespace blt::gp
|
||||||
for (auto it = crossover_point_end_itr - 1; it != crossover_point_begin_itr - 1; it--)
|
for (auto it = crossover_point_end_itr - 1; it != crossover_point_begin_itr - 1; it--)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c1_stack_for_copy, c1_stack_init);
|
c1_stack_init.transfer_bytes(c1_stack_for_copy, it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -189,7 +189,7 @@ namespace blt::gp
|
||||||
for (auto it = c2_ops.end() - 1; it != found_point_end_itr - 1; it--)
|
for (auto it = c2_ops.end() - 1; it != found_point_end_itr - 1; it--)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c2_stack_after_copy, c2_stack_init);
|
c2_stack_init.transfer_bytes(c2_stack_after_copy, it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -198,7 +198,7 @@ namespace blt::gp
|
||||||
for (auto it = found_point_end_itr - 1; it != found_point_begin_itr - 1; it--)
|
for (auto it = found_point_end_itr - 1; it != found_point_begin_itr - 1; it--)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c2_stack_for_copy, c2_stack_init);
|
c2_stack_init.transfer_bytes(c2_stack_for_copy, it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -208,7 +208,7 @@ namespace blt::gp
|
||||||
for (auto it = found_point_begin_itr; it != found_point_end_itr; it++)
|
for (auto it = found_point_begin_itr; it != found_point_end_itr; it++)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c1.get_values(), c2_stack_for_copy);
|
c2_stack_for_copy.transfer_bytes(c1.get_values(), it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -217,7 +217,7 @@ namespace blt::gp
|
||||||
for (auto it = crossover_point_begin_itr; it != crossover_point_end_itr; it++)
|
for (auto it = crossover_point_begin_itr; it != crossover_point_end_itr; it++)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c2.get_values(), c1_stack_for_copy);
|
c1_stack_for_copy.transfer_bytes(c2.get_values(), it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -227,7 +227,7 @@ namespace blt::gp
|
||||||
for (auto it = crossover_point_end_itr; it != c1_ops.end(); it++)
|
for (auto it = crossover_point_end_itr; it != c1_ops.end(); it++)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c1.get_values(), c1_stack_after_copy);
|
c1_stack_after_copy.transfer_bytes(c1.get_values(), it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL > 1
|
#if BLT_DEBUG_LEVEL > 1
|
||||||
|
@ -236,7 +236,7 @@ namespace blt::gp
|
||||||
for (auto it = found_point_end_itr; it != c2_ops.end(); it++)
|
for (auto it = found_point_end_itr; it != c2_ops.end(); it++)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(c2.get_values(), c2_stack_after_copy);
|
c2_stack_after_copy.transfer_bytes(c2.get_values(), it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now swap the operators
|
// now swap the operators
|
||||||
|
@ -288,7 +288,7 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
{
|
{
|
||||||
it->transfer(after_stack, vals);
|
vals.transfer_bytes(after_stack, it->type_size);
|
||||||
//after_ops.push_back(*it);
|
//after_ops.push_back(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ namespace blt::gp
|
||||||
for (auto it = end_p - 1; it != begin_p - 1; it--)
|
for (auto it = end_p - 1; it != begin_p - 1; it--)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(std::optional<std::reference_wrapper<stack_allocator>>{}, vals);
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(it->type_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto before = begin_p - 1;
|
auto before = begin_p - 1;
|
||||||
|
@ -313,7 +313,7 @@ namespace blt::gp
|
||||||
for (const auto& op : new_ops)
|
for (const auto& op : new_ops)
|
||||||
{
|
{
|
||||||
if (op.is_value)
|
if (op.is_value)
|
||||||
op.transfer(vals, new_vals);
|
new_vals.transfer_bytes(vals, op.type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_end_point = point + new_ops.size();
|
auto new_end_point = point + new_ops.size();
|
||||||
|
@ -322,7 +322,7 @@ namespace blt::gp
|
||||||
for (auto it = new_end_p; it != ops.end(); it++)
|
for (auto it = new_end_p; it != ops.end(); it++)
|
||||||
{
|
{
|
||||||
if (it->is_value)
|
if (it->is_value)
|
||||||
it->transfer(vals, after_stack);
|
after_stack.transfer_bytes(vals, it->type_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
|
@ -42,11 +42,11 @@ namespace blt::gp
|
||||||
operations_stack.pop_back();
|
operations_stack.pop_back();
|
||||||
if (operation.is_value)
|
if (operation.is_value)
|
||||||
{
|
{
|
||||||
operation.transfer(values_process, value_stack);
|
value_stack.transfer_bytes(values_process, operation.type_size);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
operation.func(context, values_process, value_stack);
|
operation.func(context, values_process, value_stack);
|
||||||
operations_stack.emplace_back(empty_callable, operation.transfer, operation.id, true);
|
operations_stack.emplace_back(empty_callable, operation.type_size, operation.id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
@ -88,7 +88,7 @@ namespace blt::gp
|
||||||
for (const auto& v : operations)
|
for (const auto& v : operations)
|
||||||
{
|
{
|
||||||
if (v.is_value)
|
if (v.is_value)
|
||||||
v.transfer(reversed, copy);
|
copy.transfer_bytes(reversed, v.type_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& v : operations)
|
for (const auto& v : operations)
|
||||||
|
@ -187,7 +187,7 @@ namespace blt::gp
|
||||||
values_process.pop_back();
|
values_process.pop_back();
|
||||||
}
|
}
|
||||||
value_stack.push_back(local_depth + 1);
|
value_stack.push_back(local_depth + 1);
|
||||||
operations_stack.emplace_back(empty_callable, operation.transfer, operation.id, true);
|
operations_stack.emplace_back(empty_callable, operation.type_size, operation.id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
|
|
Loading…
Reference in New Issue