replace lock with CXE loop

thread
Brett 2024-07-12 18:33:39 -04:00
parent c4cff07210
commit b6d249b23e
5 changed files with 63 additions and 101 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.64) project(blt-gp VERSION 0.0.65)
include(CTest) include(CTest)
@ -79,6 +79,6 @@ if (${BUILD_EXAMPLES})
blt_add_example(blt-gp5 examples/gp_test_5.cpp) blt_add_example(blt-gp5 examples/gp_test_5.cpp)
blt_add_example(blt-gp6 examples/gp_test_6.cpp) blt_add_example(blt-gp6 examples/gp_test_6.cpp)
blt_add_example(blt-gp7 examples/gp_test_7.cpp) blt_add_example(blt-gp7 examples/gp_test_7.cpp)
blt_add_example(blt-symbolic-regression examples/gp_symbolic_regression_example.cpp) blt_add_example(blt-SR-playground examples/pg_symbolic_regression.cpp)
endif () endif ()

View File

@ -36,7 +36,7 @@ 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(0); .set_thread_count(0);
blt::gp::type_provider type_system; blt::gp::type_provider type_system;

View File

@ -283,54 +283,60 @@ 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});
if (config.threads == 1)
{
thread_execution_service = new std::function([this, &fitness_function]() { thread_execution_service = new std::function([this, &fitness_function]() {
if (thread_helper.evaluation_left > 0) if (thread_helper.evaluation_left > 0)
{ {
std::cout << "Thread Incrementing " << thread_helper.threads_left << std::endl;
auto old_value_start = thread_helper.threads_left.load(std::memory_order::memory_order_acquire); }
while (!thread_helper.threads_left.compare_exchange_weak(old_value_start, old_value_start + 1, std::memory_order_release, });
std::memory_order_relaxed)); } else
std::cout << "Thread beginning " << thread_helper.threads_left << std::endl; {
thread_execution_service = new std::function([this, &fitness_function]() {
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 begin = 0; blt::size_t begin = 0;
blt::size_t end = 0; blt::size_t end = thread_helper.evaluation_left.load(std::memory_order_acquire);
blt::size_t size = 0;
do
{ {
std::scoped_lock lock(thread_helper.evaluation_control); size = std::min(end, config.evaluation_size);
end = thread_helper.evaluation_left; begin = end - size;
auto size = std::min(thread_helper.evaluation_left.load(), config.evaluation_size); } while (!thread_helper.evaluation_left.compare_exchange_weak(end, end - size,
begin = thread_helper.evaluation_left - size; std::memory_order::memory_order_release,
thread_helper.evaluation_left -= size; std::memory_order::memory_order_acquire));
}
//std::cout << "Processing " << begin << " to " << end << " with " << thread_helper.evaluation_left << " left" << std::endl;
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];
fitness_function(ind.tree, ind.fitness, i); fitness_function(ind.tree, ind.fitness, i);
auto old_best = current_stats.best_fitness.load(); 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_release, std::memory_order_relaxed));
auto old_worst = current_stats.worst_fitness.load(); 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_release, std::memory_order_relaxed));
auto old_overall = current_stats.overall_fitness.load(); auto old_overall = current_stats.overall_fitness.load(std::memory_order_relaxed);
while (!current_stats.overall_fitness.compare_exchange_weak(old_overall, ind.fitness.adjusted_fitness + old_overall, while (!current_stats.overall_fitness.compare_exchange_weak(old_overall,
std::memory_order_release, std::memory_order_relaxed)); ind.fitness.adjusted_fitness + old_overall,
} std::memory_order_release,
}
std::cout << "Thread Decrementing " << thread_helper.threads_left << std::endl;
auto old_value = thread_helper.threads_left.load(std::memory_order::memory_order_acquire);
while (!thread_helper.threads_left.compare_exchange_weak(old_value, old_value - 1, std::memory_order_release,
std::memory_order_relaxed)); std::memory_order_relaxed));
std::cout << "Thread Ending " << thread_helper.threads_left << std::endl; }
}
thread_helper.threads_left.fetch_sub(1, std::memory_order::memory_order_relaxed);
} }
}); });
}
evaluate_fitness_internal(); evaluate_fitness_internal();
} }
@ -494,7 +500,7 @@ 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 evaluation_control;
std::atomic_uint64_t evaluation_left = 0; std::atomic_uint64_t evaluation_left = 0;
std::atomic_int64_t threads_left = 0; std::atomic_int64_t threads_left = 0;
@ -518,8 +524,6 @@ namespace blt::gp
void create_threads(); void create_threads();
void execute_thread();
void evaluate_fitness_internal() void evaluate_fitness_internal()
{ {
current_stats.clear(); current_stats.clear();
@ -529,22 +533,22 @@ namespace blt::gp
} else } else
{ {
{ {
std::scoped_lock lock(thread_helper.evaluation_control); //std::scoped_lock lock(thread_helper.evaluation_control);
thread_helper.evaluation_left = current_pop.get_individuals().size(); thread_helper.evaluation_left.store(current_pop.get_individuals().size(), std::memory_order_release);
} }
std::cout << "Func" << std::endl; //std::cout << "Func" << std::endl;
while (thread_execution_service == nullptr) while (thread_execution_service == nullptr)
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::cout << "Wait" << std::endl; //std::cout << "Wait" << std::endl;
(*thread_execution_service)(); (*thread_execution_service)();
std::cout << "FINSIHED WAITING!!!!!!!! " << thread_helper.threads_left << std::endl; //std::cout << "FINSIHED WAITING!!!!!!!! " << thread_helper.threads_left << std::endl;
while (thread_helper.threads_left > 0) while (thread_helper.threads_left > 0)
{ {
//std::cout << thread_helper.threads_left << std::endl; //std::cout << thread_helper.threads_left << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
std::cout << "Finished" << std::endl; //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);

View File

@ -67,47 +67,4 @@ namespace blt::gp
})); }));
} }
} }
void gp_program::execute_thread()
{
if (thread_helper.evaluation_left > 0)
{
std::cout << "Thread beginning" << std::endl;
while (thread_helper.evaluation_left > 0)
{
blt::size_t begin = 0;
blt::size_t end = 0;
{
std::scoped_lock lock(thread_helper.evaluation_control);
end = thread_helper.evaluation_left;
auto size = std::min(thread_helper.evaluation_left.load(), config.evaluation_size);
begin = thread_helper.evaluation_left - size;
thread_helper.evaluation_left -= size;
}
std::cout << "Processing " << begin << " to " << end << " with " << thread_helper.evaluation_left << " left" << std::endl;
for (blt::size_t i = begin; i < end; i++)
{
auto& ind = current_pop.get_individuals()[i];
//evaluate_fitness_func(ind.tree, ind.fitness, i);
auto old_best = current_stats.best_fitness.load();
while (ind.fitness.adjusted_fitness > old_best &&
!current_stats.best_fitness.compare_exchange_weak(old_best, ind.fitness.adjusted_fitness,
std::memory_order_release, std::memory_order_relaxed));
auto old_worst = current_stats.worst_fitness.load();
while (ind.fitness.adjusted_fitness < old_worst &&
!current_stats.worst_fitness.compare_exchange_weak(old_worst, ind.fitness.adjusted_fitness,
std::memory_order_release, std::memory_order_relaxed));
auto old_overall = current_stats.overall_fitness.load();
while (!current_stats.overall_fitness.compare_exchange_weak(old_overall, ind.fitness.adjusted_fitness + old_overall,
std::memory_order_release, std::memory_order_relaxed));
}
}
thread_helper.threads_left--;
std::cout << "thread finished!" << std::endl;
}
}
} }

1
test_perf.sh Executable file
View File

@ -0,0 +1 @@
perf stat -d -d -d -r 30 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch ./cmake-build-release/blt-SR-playground-example