From 5bd057a96b90efd878c32ce55d99f58e7142806e Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sun, 22 Oct 2023 11:11:07 +0200 Subject: [PATCH] wip --- examples/mpi.cpp | 3 +- redGrapes/dispatch/thread/worker.cpp | 12 ++--- redGrapes/dispatch/thread/worker.hpp | 6 +-- redGrapes/dispatch/thread/worker_pool.cpp | 26 +++++++--- redGrapes/dispatch/thread/worker_pool.hpp | 11 ++++ redGrapes/redGrapes.cpp | 1 + redGrapes/resource/resource.hpp | 1 + redGrapes/task/property/graph.cpp | 33 ++++++------ redGrapes/util/allocator.cpp | 4 +- redGrapes/util/allocator.hpp | 11 +++- redGrapes/util/bump_alloc_chunk.cpp | 4 +- redGrapes/util/bump_alloc_chunk.hpp | 4 +- redGrapes/util/chunked_bump_alloc.hpp | 10 +++- redGrapes/util/chunked_list.hpp | 2 +- redGrapes/util/chunklist.hpp | 8 ++- redGrapes/util/trace.hpp | 2 +- test/chunked_list.cpp | 62 +++++++++++++++++++++++ test/random_graph.cpp | 29 ++++++----- 18 files changed, 171 insertions(+), 58 deletions(-) diff --git a/examples/mpi.cpp b/examples/mpi.cpp index 27963c4d..d9a97789 100644 --- a/examples/mpi.cpp +++ b/examples/mpi.cpp @@ -53,7 +53,8 @@ int main() auto mpi_request_pool = std::make_shared(); hwloc_obj_t obj = hwloc_get_obj_by_type( redGrapes::hwloc_ctx->topology, HWLOC_OBJ_PU, 1 ); - auto mpi_worker = std::make_shared( redGrapes::hwloc_ctx, obj, 4 ); + rg::memory::ChunkedBumpAlloc< rg::memory::HwlocAlloc > mpi_alloc( rg::memory::HwlocAlloc( redGrapes::hwloc_ctx, obj ) ); + auto mpi_worker = std::make_shared( mpi_alloc, redGrapes::hwloc_ctx, obj, 4 ); // initialize main thread to execute tasks from the mpi-queue and poll rg::idle = diff --git a/redGrapes/dispatch/thread/worker.cpp b/redGrapes/dispatch/thread/worker.cpp index 9f8549c4..ba6b4f75 100644 --- a/redGrapes/dispatch/thread/worker.cpp +++ b/redGrapes/dispatch/thread/worker.cpp @@ -19,9 +19,9 @@ namespace dispatch { namespace thread { -WorkerThread::WorkerThread( std::shared_ptr< HwlocContext > hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ) - : Worker( hwloc_ctx, obj, worker_id ), - thread([this] { this->run(); }) +WorkerThread::WorkerThread( memory::ChunkedBumpAlloc< memory::HwlocAlloc > & alloc, std::shared_ptr< HwlocContext > hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ) + : Worker( alloc, hwloc_ctx, obj, worker_id ) + , thread([this] { this->run(); }) { } @@ -29,9 +29,9 @@ WorkerThread::~WorkerThread() { } -Worker::Worker( std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ) - : hwloc_ctx(hwloc_ctx) - , alloc( memory::HwlocAlloc( hwloc_ctx, obj ) ) +Worker::Worker( memory::ChunkedBumpAlloc & alloc, std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ) + : alloc( alloc ) + , hwloc_ctx( hwloc_ctx ) , id( worker_id ) { } diff --git a/redGrapes/dispatch/thread/worker.hpp b/redGrapes/dispatch/thread/worker.hpp index dfb0331c..7401b7d4 100644 --- a/redGrapes/dispatch/thread/worker.hpp +++ b/redGrapes/dispatch/thread/worker.hpp @@ -70,13 +70,13 @@ struct Worker static constexpr size_t queue_capacity = 128; public: - memory::ChunkedBumpAlloc< memory::HwlocAlloc > alloc; + memory::ChunkedBumpAlloc< memory::HwlocAlloc > & alloc; std::shared_ptr< HwlocContext > hwloc_ctx; task::Queue emplacement_queue{ queue_capacity }; task::Queue ready_queue{ queue_capacity }; - Worker( std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId id ); + Worker( memory::ChunkedBumpAlloc< memory::HwlocAlloc > & alloc, std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId id ); virtual ~Worker(); inline WorkerId get_worker_id() { return id; } @@ -129,7 +129,7 @@ struct WorkerThread { std::thread thread; - WorkerThread( std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ); + WorkerThread( memory::ChunkedBumpAlloc & alloc, std::shared_ptr hwloc_ctx, hwloc_obj_t const & obj, WorkerId worker_id ); ~WorkerThread(); void stop(); diff --git a/redGrapes/dispatch/thread/worker_pool.cpp b/redGrapes/dispatch/thread/worker_pool.cpp index 2b1d128e..de6aed08 100644 --- a/redGrapes/dispatch/thread/worker_pool.cpp +++ b/redGrapes/dispatch/thread/worker_pool.cpp @@ -6,8 +6,10 @@ */ #include #include +#include #include #include +#include namespace redGrapes { @@ -19,23 +21,33 @@ namespace thread WorkerPool::WorkerPool( std::shared_ptr< HwlocContext > hwloc_ctx, size_t n_workers ) : worker_state( n_workers ) { - workers.reserve( n_workers ); + redGrapes::dispatch::thread::current_waker_id = 0; +} +void WorkerPool::emplace_workers( size_t n_workers ) +{ unsigned n_pus = hwloc_get_nbobjs_by_type(hwloc_ctx->topology, HWLOC_OBJ_PU); if( n_workers > n_pus ) spdlog::warn("{} worker-threads requested, but only {} PUs available!", n_workers, n_pus); - SPDLOG_INFO("create WorkerPool with {} workers", n_workers); + allocs.reserve( n_workers ); + workers.reserve( n_workers ); + + SPDLOG_INFO("populate WorkerPool with {} workers", n_workers); for( size_t i = 0; i < n_workers; ++i ) { // allocate worker with id `i` on arena `i`, hwloc_obj_t obj = hwloc_get_obj_by_type(hwloc_ctx->topology, HWLOC_OBJ_PU, i); - memory::HwlocAlloc< dispatch::thread::WorkerThread > hwloc_alloc( hwloc_ctx, obj ); - auto worker = std::allocate_shared< dispatch::thread::WorkerThread >( hwloc_alloc, hwloc_ctx, obj, i ); + allocs.emplace_back( + memory::HwlocAlloc( hwloc_ctx, obj ), + REDGRAPES_ALLOC_CHUNKSIZE + ); + + memory::current_arena = i; + auto worker = memory::alloc_shared_bind( i, get_alloc(i), hwloc_ctx, obj, i ); +// auto worker = std::make_shared< WorkerThread >( get_alloc(i), hwloc_ctx, obj, i ); workers.emplace_back( worker ); } - - redGrapes::dispatch::thread::current_waker_id = 0; } WorkerPool::~WorkerPool() @@ -52,6 +64,8 @@ void WorkerPool::stop() { for( auto & worker : workers ) worker->stop(); + + workers.clear(); } int WorkerPool::find_free_worker() diff --git a/redGrapes/dispatch/thread/worker_pool.hpp b/redGrapes/dispatch/thread/worker_pool.hpp index 0b6ef7ad..2ce575f0 100644 --- a/redGrapes/dispatch/thread/worker_pool.hpp +++ b/redGrapes/dispatch/thread/worker_pool.hpp @@ -8,6 +8,8 @@ #include #include +#include +#include namespace redGrapes { @@ -31,6 +33,8 @@ struct WorkerPool WorkerPool( std::shared_ptr< HwlocContext > hwloc_ctx, size_t n_workers = 1 ); ~WorkerPool(); + void emplace_workers( size_t n_workers ); + /* get the number of workers in this pool */ inline size_t size() @@ -46,6 +50,12 @@ struct WorkerPool */ void stop(); + inline memory::ChunkedBumpAlloc< memory::HwlocAlloc > & get_alloc( WorkerId worker_id ) + { + assert( worker_id < allocs.size() ); + return allocs[ worker_id ]; + } + inline WorkerThread & get_worker( WorkerId worker_id ) { assert( worker_id < size() ); @@ -84,6 +94,7 @@ struct WorkerPool int find_free_worker(); private: + std::vector< memory::ChunkedBumpAlloc< memory::HwlocAlloc > > allocs; std::vector< std::shared_ptr< dispatch::thread::WorkerThread > > workers; AtomicBitfield worker_state; }; diff --git a/redGrapes/redGrapes.cpp b/redGrapes/redGrapes.cpp index 575ceb18..4b741ab1 100644 --- a/redGrapes/redGrapes.cpp +++ b/redGrapes/redGrapes.cpp @@ -142,6 +142,7 @@ void init( size_t n_workers, std::shared_ptr scheduler ) { init_tracing(); worker_pool = std::make_shared( hwloc_ctx, n_workers ); + worker_pool->emplace_workers( n_workers ); top_space = std::make_shared(); top_scheduler = scheduler; diff --git a/redGrapes/resource/resource.hpp b/redGrapes/resource/resource.hpp index 9c04f169..7314bfea 100644 --- a/redGrapes/resource/resource.hpp +++ b/redGrapes/resource/resource.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/redGrapes/task/property/graph.cpp b/redGrapes/task/property/graph.cpp index ea440e10..0417ce39 100644 --- a/redGrapes/task/property/graph.cpp +++ b/redGrapes/task/property/graph.cpp @@ -54,25 +54,24 @@ void GraphProperty::init_graph() TRACE_EVENT("Graph", "CheckPredecessors"); auto it = r->task_entry; - ++it; - for(; it != r->resource->users.rend(); ++it ) - { - TRACE_EVENT("Graph", "Check Pred"); - Task * preceding_task = *it; - - if( preceding_task == this->space->parent ) - break; + ++it; + for(; it != r->resource->users.rend(); ++it ) + { + TRACE_EVENT("Graph", "Check Pred"); + Task * preceding_task = *it; - if( - preceding_task->space == this->space && - this->space->is_serial( *preceding_task, *this->task ) - ) - { - add_dependency( *preceding_task ); + if( preceding_task == this->space->parent ) + break; - if( preceding_task->has_sync_access( r->resource ) ) - break; - } + if( + preceding_task->space == this->space && + this->space->is_serial( *preceding_task, *this->task ) + ) + { + add_dependency( *preceding_task ); + if( preceding_task->has_sync_access( r->resource ) ) + break; + } } } } diff --git a/redGrapes/util/allocator.cpp b/redGrapes/util/allocator.cpp index 1d80c592..7e33f2d4 100644 --- a/redGrapes/util/allocator.cpp +++ b/redGrapes/util/allocator.cpp @@ -14,12 +14,12 @@ UntypedAllocator::UntypedAllocator( dispatch::thread::WorkerId worker_id ) void * UntypedAllocator::allocate( size_t n_bytes ) { - return (void*)worker_pool->get_worker( worker_id ).alloc.allocate< uint8_t >( n_bytes ); + return (void*)worker_pool->get_alloc( worker_id ).allocate< uint8_t >( n_bytes ); } void UntypedAllocator::deallocate( void * ptr ) { - worker_pool->get_worker( worker_id ).alloc.deallocate( ptr ); + worker_pool->get_alloc( worker_id ).deallocate( ptr ); } } // namespace memory diff --git a/redGrapes/util/allocator.hpp b/redGrapes/util/allocator.hpp index 7aed0fda..de81d1a7 100644 --- a/redGrapes/util/allocator.hpp +++ b/redGrapes/util/allocator.hpp @@ -3,13 +3,22 @@ #include #include #include -#include +// #include #include //#include namespace redGrapes { +namespace dispatch + { + namespace thread + { + using WorkerId = unsigned; + struct WorkerPool; + } + } + extern std::shared_ptr< dispatch::thread::WorkerPool > worker_pool; namespace memory diff --git a/redGrapes/util/bump_alloc_chunk.cpp b/redGrapes/util/bump_alloc_chunk.cpp index 4f4f8a1d..dd2d6262 100644 --- a/redGrapes/util/bump_alloc_chunk.cpp +++ b/redGrapes/util/bump_alloc_chunk.cpp @@ -56,9 +56,9 @@ void * BumpAllocChunk::m_alloc( size_t n_bytes ) return nullptr; } -size_t BumpAllocChunk::m_free( void * ) +uint16_t BumpAllocChunk::m_free( void * ) { - return count.fetch_sub(1) - 1; + return count.fetch_sub(1); } bool BumpAllocChunk::contains( void * ptr ) const diff --git a/redGrapes/util/bump_alloc_chunk.hpp b/redGrapes/util/bump_alloc_chunk.hpp index 3cb73b22..2a298cb5 100644 --- a/redGrapes/util/bump_alloc_chunk.hpp +++ b/redGrapes/util/bump_alloc_chunk.hpp @@ -34,14 +34,14 @@ struct BumpAllocChunk void reset(); void * m_alloc( size_t n_bytes ); - size_t m_free( void * ); + uint16_t m_free( void * ); bool contains( void * ) const; std::atomic< uintptr_t > next_addr; uintptr_t const lower_limit; uintptr_t const upper_limit; - std::atomic< size_t > count; + std::atomic< uint16_t > count; }; } // namespace memory diff --git a/redGrapes/util/chunked_bump_alloc.hpp b/redGrapes/util/chunked_bump_alloc.hpp index 5eef2bb4..2d343486 100644 --- a/redGrapes/util/chunked_bump_alloc.hpp +++ b/redGrapes/util/chunked_bump_alloc.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace redGrapes { @@ -143,7 +144,7 @@ struct ChunkedBumpAlloc * and this chunk is not `head`, * remove this chunk */ - if( it->m_free((void*)ptr) == 0 ) + if( it->m_free((void*)ptr) == 1 ) { SPDLOG_TRACE("ChunkedBumpAlloc: erase chunk {}", it->lower_limit); bump_allocators.erase( it ); @@ -155,7 +156,12 @@ struct ChunkedBumpAlloc prev = it; } - spdlog::error("try to deallocate invalid pointer ({})", (void*)ptr); + spdlog::error("try to deallocate invalid pointer ({}). current_arena={}, this={}", (void*)ptr, current_arena, (void*)this); + + backward::StackTrace st; + st.load_here(32); + backward::Printer p; + p.print(st); } }; diff --git a/redGrapes/util/chunked_list.hpp b/redGrapes/util/chunked_list.hpp index 4f068b3e..440a39a8 100644 --- a/redGrapes/util/chunked_list.hpp +++ b/redGrapes/util/chunked_list.hpp @@ -129,7 +129,7 @@ struct ChunkedList ~Item() { - if( iter_offset == 0 ) + if( refcount.fetch_sub(1) == 1 ) storage.value.~T(); } diff --git a/redGrapes/util/chunklist.hpp b/redGrapes/util/chunklist.hpp index 66b244e8..17e258a3 100644 --- a/redGrapes/util/chunklist.hpp +++ b/redGrapes/util/chunklist.hpp @@ -49,13 +49,17 @@ struct ChunkList ChunkData * chunk_data; template < typename... Args > - Chunk( uintptr_t chunk_data, Args&&... args ) : deleted(false), prev(nullptr), chunk_data((ChunkData*)chunk_data) + Chunk( uintptr_t chunk_data, Args&&... args ) + : deleted(false) + , prev(nullptr) + , chunk_data((ChunkData*)chunk_data) { new ( get() ) ChunkData ( std::forward(args)... ); } ~Chunk() { + spdlog::info("destruct chunk {}", (void*)chunk_data); get()->~ChunkData(); } @@ -141,7 +145,7 @@ struct ChunkList /* TODO: use sizeof( ...shared_ptr_inplace_something... ) */ - size_t const shared_ptr_size = 128; + size_t const shared_ptr_size = 512; return sizeof(Chunk) + shared_ptr_size; } diff --git a/redGrapes/util/trace.hpp b/redGrapes/util/trace.hpp index 9cec151d..7947c816 100644 --- a/redGrapes/util/trace.hpp +++ b/redGrapes/util/trace.hpp @@ -1,7 +1,7 @@ #pragma once -#include +//#include #ifndef REDGRAPES_ENABLE_TRACE #define REDGRAPES_ENABLE_TRACE 0 diff --git a/test/chunked_list.cpp b/test/chunked_list.cpp index c58481aa..3efaee53 100644 --- a/test/chunked_list.cpp +++ b/test/chunked_list.cpp @@ -5,6 +5,68 @@ #include #include +struct TestItem +{ + int id; + + TestItem(int id):id(id){} + ~TestItem() + { + spdlog::info("destroy {}", this->id); + } +}; + +TEST_CASE("Chunked List") +{ + /* + redGrapes::init(1 + //, 281 + ); + + redGrapes::ChunkedList< TestItem > l( 2 ); + + { + auto p1 = l.push( TestItem(10) ); + auto p2 = l.push( TestItem(20) ); + + { + auto p3 = l.push( TestItem(30) ); + auto p4 = l.push( TestItem(40) ); + + l.push( TestItem(50) ); + l.push( TestItem(60) ); + + for( auto it = l.rbegin(); it != l.rend(); ++it ) + fmt::print("v = {}\n", it->id); + + fmt::print("--\n"); + + l.remove(p3); + l.remove(p4); + + fmt::print("--\n"); + } + + + for( auto it = l.rbegin(); it != l.rend(); ++it ) + fmt::print("v = {}\n", it->id); + + fmt::print("--\n"); + l.remove(p1); + l.remove(p2); + fmt::print("--\n"); + } + + for( auto it = l.rbegin(); it != l.rend(); ++it ) + fmt::print("v = {}\n", it->id); + + l.remove(l.rbegin()); + l.remove(l.rbegin()); + + redGrapes::finalize(); +*/ +} + /* TODO TEST_CASE("ChunkedList singlethreaded") diff --git a/test/random_graph.cpp b/test/random_graph.cpp index cdbf002a..b1faab61 100644 --- a/test/random_graph.cpp +++ b/test/random_graph.cpp @@ -39,7 +39,7 @@ void hash(unsigned task_id, std::chrono::microseconds task_duration(2); unsigned n_resources = 16; unsigned n_tasks = 128; -unsigned n_threads = 4; +unsigned n_threads = 8; unsigned min_dependencies = 0; unsigned max_dependencies = 5; std::mt19937 gen; @@ -61,7 +61,7 @@ void generate_access_pattern() unsigned n_dependencies = distrib_n_deps(gen); for(int j = 0; j < n_dependencies; ++j) { - unsigned max_path_length = 0; + unsigned max_path_length = 0; while(1) { @@ -72,22 +72,22 @@ void generate_access_pattern() access_pattern[i].push_back(resource_id); hash(i, expected_hash[resource_id]); - if( path_length[resource_id] > max_path_length ) - max_path_length = path_length[resource_id]; + if( path_length[resource_id] > max_path_length ) + max_path_length = path_length[resource_id]; break; } } - for( unsigned rid : access_pattern[i] ) - path_length[rid] = max_path_length + 1; + for( unsigned rid : access_pattern[i] ) + path_length[rid] = max_path_length + 1; } } unsigned max_path_length = 1; for( unsigned pl : path_length ) - if( pl > max_path_length ) - max_path_length = pl; + if( pl > max_path_length ) + max_path_length = pl; std::cout << "max path length = " << max_path_length << std::endl; } @@ -98,9 +98,11 @@ TEST_CASE("RandomGraph") generate_access_pattern(); + redGrapes::worker_pool.reset(); + rg::init(n_threads); + { - rg::init(n_threads); - std::vector>> resources(n_resources); + std::vector>> resources(n_resources); for(int i = 0; i < n_tasks; ++i) switch(access_pattern[i].size()) @@ -180,12 +182,15 @@ TEST_CASE("RandomGraph") break; } + spdlog::info("BARRIER"); rg::barrier(); + spdlog::info("check resource values"); for(int i = 0; i < n_resources; ++i) REQUIRE( *resources[i] == expected_hash[i] ); + } - rg::finalize(); - }; + rg::finalize(); + redGrapes::worker_pool.reset(); }