thread_local stats
parent
ddcad0cbdb
commit
55f5b5bc05
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.1.40)
|
project(blt-gp VERSION 0.1.41)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -148,9 +148,9 @@ int main()
|
||||||
auto mutation_allocations_v = blt::gp::mutation_allocations.get_calls();
|
auto mutation_allocations_v = blt::gp::mutation_allocations.get_calls();
|
||||||
auto reproduction_calls_v = blt::gp::reproduction_calls.get_calls();
|
auto reproduction_calls_v = blt::gp::reproduction_calls.get_calls();
|
||||||
auto reproduction_allocations_v = blt::gp::reproduction_allocations.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 Crossover Calls: %ld", crossover_calls_v);
|
||||||
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 Mutation Calls: %ld", mutation_calls_v);
|
||||||
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 Reproduction Calls: %ld", reproduction_calls_v);
|
||||||
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 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 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("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());
|
||||||
|
|
|
@ -367,8 +367,7 @@ namespace blt::gp
|
||||||
(*thread_execution_service)(0);
|
(*thread_execution_service)(0);
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
blt::gp::tracker.stop_measurement(gen_alloc);
|
blt::gp::tracker.stop_measurement(gen_alloc);
|
||||||
BLT_TRACE("Generation Allocated %ld times with a total of %s", gen_alloc.getAllocationDifference(),
|
gen_alloc.pretty_print("Generation");
|
||||||
blt::byte_convert_t(gen_alloc.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +385,7 @@ namespace blt::gp
|
||||||
evaluate_fitness_internal();
|
evaluate_fitness_internal();
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
blt::gp::tracker.stop_measurement(fitness_alloc);
|
blt::gp::tracker.stop_measurement(fitness_alloc);
|
||||||
BLT_TRACE("Fitness Allocated %ld times with a total of %s", fitness_alloc.getAllocationDifference(),
|
fitness_alloc.pretty_print("Fitness");
|
||||||
blt::byte_convert_t(fitness_alloc.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace blt::gp
|
||||||
if (random.choice(config.crossover_chance))
|
if (random.choice(config.crossover_chance))
|
||||||
{
|
{
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
auto state = tracker.start_measurement();
|
auto state = tracker.start_measurement_thread_local();
|
||||||
#endif
|
#endif
|
||||||
// crossover
|
// crossover
|
||||||
const tree_t* p1;
|
const tree_t* p1;
|
||||||
|
@ -100,10 +100,12 @@ namespace blt::gp
|
||||||
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));
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
tracker.stop_measurement(state);
|
tracker.stop_measurement_thread_local(state);
|
||||||
crossover_calls.call(state.getAllocatedByteDifference());
|
crossover_calls.call();
|
||||||
if (state.getAllocationDifference() != 0)
|
if (state.getAllocatedByteDifference() != 0)
|
||||||
|
{
|
||||||
crossover_allocations.call(state.getAllocatedByteDifference());
|
crossover_allocations.call(state.getAllocatedByteDifference());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +114,7 @@ namespace blt::gp
|
||||||
if (random.choice(config.mutation_chance))
|
if (random.choice(config.mutation_chance))
|
||||||
{
|
{
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
auto state = tracker.start_measurement();
|
auto state = tracker.start_measurement_thread_local();
|
||||||
#endif
|
#endif
|
||||||
// mutation
|
// mutation
|
||||||
const tree_t* p;
|
const tree_t* p;
|
||||||
|
@ -121,8 +123,8 @@ namespace blt::gp
|
||||||
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));
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
tracker.stop_measurement(state);
|
tracker.stop_measurement_thread_local(state);
|
||||||
mutation_calls.call(state.getAllocatedByteDifference());
|
mutation_calls.call();
|
||||||
if (state.getAllocationDifference() != 0)
|
if (state.getAllocationDifference() != 0)
|
||||||
{
|
{
|
||||||
mutation_allocations.call(state.getAllocatedByteDifference());
|
mutation_allocations.call(state.getAllocatedByteDifference());
|
||||||
|
@ -135,13 +137,13 @@ namespace blt::gp
|
||||||
if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance))
|
if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance))
|
||||||
{
|
{
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
auto state = tracker.start_measurement();
|
auto state = tracker.start_measurement_thread_local();
|
||||||
#endif
|
#endif
|
||||||
// reproduction
|
// reproduction
|
||||||
c1 = reproduction_selection.select(program, current_pop);
|
c1 = reproduction_selection.select(program, current_pop);
|
||||||
#ifdef BLT_TRACK_ALLOCATIONS
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
tracker.stop_measurement(state);
|
tracker.stop_measurement_thread_local(state);
|
||||||
reproduction_calls.call(state.getAllocatedByteDifference());
|
reproduction_calls.call();
|
||||||
if (state.getAllocationDifference() != 0)
|
if (state.getAllocationDifference() != 0)
|
||||||
{
|
{
|
||||||
reproduction_allocations.call(state.getAllocatedByteDifference());
|
reproduction_allocations.call(state.getAllocatedByteDifference());
|
||||||
|
|
|
@ -20,15 +20,60 @@
|
||||||
#define BLT_GP_STATS_H
|
#define BLT_GP_STATS_H
|
||||||
|
|
||||||
#include <blt/std/types.h>
|
#include <blt/std/types.h>
|
||||||
#include <atomic>
|
#include <blt/std/hashmap.h>
|
||||||
|
#include <blt/std/assert.h>
|
||||||
|
#include <thread>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
class allocation_tracker_t
|
class allocation_tracker_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class tl_t
|
||||||
|
{
|
||||||
|
friend allocation_tracker_t;
|
||||||
|
public:
|
||||||
|
[[nodiscard]] blt::u64 getAllocations() const
|
||||||
|
{
|
||||||
|
return get_map(allocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::u64 getDeallocations() const
|
||||||
|
{
|
||||||
|
return get_map(deallocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::u64 getAllocatedBytes() const
|
||||||
|
{
|
||||||
|
return get_map(allocated_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::u64 getDeallocatedBytes() const
|
||||||
|
{
|
||||||
|
return get_map(deallocated_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::u64 getAllocationDifference() const
|
||||||
|
{
|
||||||
|
return std::abs(static_cast<blt::i64>(getAllocations()) - static_cast<blt::i64>(getDeallocations()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::u64 getCurrentlyAllocatedBytes() const
|
||||||
|
{
|
||||||
|
return getAllocatedBytes() - getDeallocatedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>> allocations;
|
||||||
|
blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>> deallocations;
|
||||||
|
blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>> allocated_bytes;
|
||||||
|
blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>> deallocated_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
struct allocation_data_t
|
struct allocation_data_t
|
||||||
{
|
{
|
||||||
blt::u64 start_allocations = 0;
|
blt::u64 start_allocations = 0;
|
||||||
|
@ -60,18 +105,33 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
return end_deallocated_bytes - start_deallocated_bytes;
|
return end_deallocated_bytes - start_deallocated_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pretty_print(const std::string& name) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void reserve()
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(mutex);
|
||||||
|
tl.allocations[std::this_thread::get_id()] = std::make_unique<blt::u64>();
|
||||||
|
tl.deallocations[std::this_thread::get_id()] = std::make_unique<blt::u64>();
|
||||||
|
tl.allocated_bytes[std::this_thread::get_id()] = std::make_unique<blt::u64>();
|
||||||
|
tl.deallocated_bytes[std::this_thread::get_id()] = std::make_unique<blt::u64>();
|
||||||
|
}
|
||||||
|
|
||||||
void allocate(blt::size_t bytes)
|
void allocate(blt::size_t bytes)
|
||||||
{
|
{
|
||||||
allocations++;
|
allocations++;
|
||||||
allocated_bytes += bytes;
|
allocated_bytes += bytes;
|
||||||
|
add_map(tl.allocations, 1);
|
||||||
|
add_map(tl.allocated_bytes, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(blt::size_t bytes)
|
void deallocate(blt::size_t bytes)
|
||||||
{
|
{
|
||||||
deallocations++;
|
deallocations++;
|
||||||
deallocated_bytes += bytes;
|
deallocated_bytes += bytes;
|
||||||
|
add_map(tl.deallocations, 1);
|
||||||
|
add_map(tl.deallocated_bytes, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] blt::u64 getAllocations() const
|
[[nodiscard]] blt::u64 getAllocations() const
|
||||||
|
@ -104,29 +164,73 @@ namespace blt::gp
|
||||||
return getAllocatedBytes() - getDeallocatedBytes();
|
return getAllocatedBytes() - getDeallocatedBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocation_tracker_t::tl_t& get_thread_local()
|
||||||
|
{
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] allocation_data_t start_measurement() const
|
[[nodiscard]] allocation_data_t start_measurement() const
|
||||||
{
|
{
|
||||||
allocation_data_t data{};
|
allocation_data_t data{};
|
||||||
data.start_allocations = allocations;
|
data.start_allocations = getAllocations();
|
||||||
data.start_deallocations = deallocations;
|
data.start_deallocations = getDeallocations();
|
||||||
data.start_allocated_bytes = allocated_bytes;
|
data.start_allocated_bytes = getAllocatedBytes();
|
||||||
data.start_deallocated_bytes = deallocated_bytes;
|
data.start_deallocated_bytes = getDeallocatedBytes();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] allocation_data_t start_measurement_thread_local() const
|
||||||
|
{
|
||||||
|
allocation_data_t data{};
|
||||||
|
data.start_allocations = tl.getAllocations();
|
||||||
|
data.start_deallocations = tl.getDeallocations();
|
||||||
|
data.start_allocated_bytes = tl.getAllocatedBytes();
|
||||||
|
data.start_deallocated_bytes = tl.getDeallocatedBytes();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_measurement(allocation_data_t& data) const
|
void stop_measurement(allocation_data_t& data) const
|
||||||
{
|
{
|
||||||
data.end_allocations = allocations;
|
data.end_allocations = getAllocations();
|
||||||
data.end_deallocations = deallocations;
|
data.end_deallocations = getDeallocations();
|
||||||
data.end_allocated_bytes = allocated_bytes;
|
data.end_allocated_bytes = getAllocatedBytes();
|
||||||
data.end_deallocated_bytes = deallocated_bytes;
|
data.end_deallocated_bytes = getDeallocatedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_measurement_thread_local(allocation_data_t& data) const
|
||||||
|
{
|
||||||
|
data.end_allocations = tl.getAllocations();
|
||||||
|
data.end_deallocations = tl.getDeallocations();
|
||||||
|
data.end_allocated_bytes = tl.getAllocatedBytes();
|
||||||
|
data.end_deallocated_bytes = tl.getDeallocatedBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void add_map(blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>>& map, blt::u64 value)
|
||||||
|
{
|
||||||
|
auto l = map.find(std::this_thread::get_id());
|
||||||
|
if (l == map.end())
|
||||||
|
BLT_ABORT("Thread doesn't exist inside this map!");
|
||||||
|
auto& v = *l->second;
|
||||||
|
v += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static blt::u64 get_map(const blt::hashmap_t<std::thread::id, std::unique_ptr<blt::u64>>& map)
|
||||||
|
{
|
||||||
|
auto l = map.find(std::this_thread::get_id());
|
||||||
|
if (l == map.end())
|
||||||
|
BLT_ABORT("Thread doesn't exist inside this map!");
|
||||||
|
return *l->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_t tl;
|
||||||
|
|
||||||
std::atomic_uint64_t allocations = 0;
|
std::atomic_uint64_t allocations = 0;
|
||||||
std::atomic_uint64_t deallocations = 0;
|
std::atomic_uint64_t deallocations = 0;
|
||||||
std::atomic_uint64_t allocated_bytes = 0;
|
std::atomic_uint64_t allocated_bytes = 0;
|
||||||
std::atomic_uint64_t deallocated_bytes = 0;
|
std::atomic_uint64_t deallocated_bytes = 0;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class call_tracker_t
|
class call_tracker_t
|
||||||
|
@ -190,7 +294,6 @@ namespace blt::gp
|
||||||
std::atomic_uint64_t primary_calls = 0;
|
std::atomic_uint64_t primary_calls = 0;
|
||||||
std::atomic_uint64_t secondary_value = 0;
|
std::atomic_uint64_t secondary_value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLT_GP_STATS_H
|
#endif //BLT_GP_STATS_H
|
||||||
|
|
|
@ -58,12 +58,18 @@ namespace blt::gp
|
||||||
|
|
||||||
void gp_program::create_threads()
|
void gp_program::create_threads()
|
||||||
{
|
{
|
||||||
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
|
tracker.reserve();
|
||||||
|
#endif
|
||||||
if (config.threads == 0)
|
if (config.threads == 0)
|
||||||
config.set_thread_count(std::thread::hardware_concurrency());
|
config.set_thread_count(std::thread::hardware_concurrency());
|
||||||
// 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([i, this]() {
|
thread_helper.threads.emplace_back(new std::thread([i, this]() {
|
||||||
|
#ifdef BLT_TRACK_ALLOCATIONS
|
||||||
|
tracker.reserve();
|
||||||
|
#endif
|
||||||
std::function<void(blt::size_t)>* execution_function = nullptr;
|
std::function<void(blt::size_t)>* execution_function = nullptr;
|
||||||
while (!should_thread_terminate())
|
while (!should_thread_terminate())
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,8 +17,14 @@
|
||||||
*/
|
*/
|
||||||
#include <blt/gp/stats.h>
|
#include <blt/gp/stats.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
|
#include "blt/std/format.h"
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void allocation_tracker_t::allocation_data_t::pretty_print(const std::string& name) const
|
||||||
|
{
|
||||||
|
BLT_TRACE("%s Allocations: %ld times with a total of %s", name.c_str(), getAllocationDifference(),
|
||||||
|
blt::byte_convert_t(getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -105,6 +105,9 @@ namespace blt::gp
|
||||||
auto copy_ptr_c1 = get_thread_pointer_for_size<struct c1_t>(c1_total);
|
auto copy_ptr_c1 = get_thread_pointer_for_size<struct c1_t>(c1_total);
|
||||||
auto copy_ptr_c2 = get_thread_pointer_for_size<struct c2_t>(c2_total);
|
auto copy_ptr_c2 = get_thread_pointer_for_size<struct c2_t>(c2_total);
|
||||||
|
|
||||||
|
c1_stack.reserve(c1_stack.bytes_in_head() - c1_stack_for_bytes + c2_stack_for_bytes);
|
||||||
|
c2_stack.reserve(c2_stack.bytes_in_head() - c2_stack_for_bytes + c1_stack_for_bytes);
|
||||||
|
|
||||||
c1_stack.copy_to(copy_ptr_c1, c1_total);
|
c1_stack.copy_to(copy_ptr_c1, c1_total);
|
||||||
c1_stack.pop_bytes(c1_total);
|
c1_stack.pop_bytes(c1_total);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue