diff --git a/redGrapes/TaskFreeCtx.hpp b/redGrapes/TaskFreeCtx.hpp index 4ad37f5d..251a16ec 100644 --- a/redGrapes/TaskFreeCtx.hpp +++ b/redGrapes/TaskFreeCtx.hpp @@ -11,15 +11,15 @@ #include "redGrapes/memory/hwloc_alloc.hpp" #include "redGrapes/sync/cv.hpp" +#include #include -#include #include #include namespace redGrapes { - using WorkerId = unsigned; + using WorkerId = uint8_t; /** WorkerID of parser to wake it up * ID 0,1,2... are used for worker threads @@ -43,10 +43,11 @@ namespace redGrapes struct TaskFreeCtx { - static inline unsigned n_workers; - static inline unsigned n_pus; static inline HwlocContext hwloc_ctx; - static inline std::shared_ptr worker_alloc_pool; + static inline WorkerId n_pus{ + static_cast(hwloc_get_nbobjs_by_type(hwloc_ctx.topology, HWLOC_OBJ_PU))}; + static inline WorkerId n_workers; + static inline WorkerAllocPool worker_alloc_pool; static inline CondVar cv{0}; static inline std::function idle = [] diff --git a/redGrapes/dispatch/thread/worker_pool.hpp b/redGrapes/dispatch/thread/worker_pool.hpp index 1f0193e7..543b40e1 100644 --- a/redGrapes/dispatch/thread/worker_pool.hpp +++ b/redGrapes/dispatch/thread/worker_pool.hpp @@ -76,7 +76,7 @@ namespace redGrapes inline std::optional probe_worker_by_state( F&& f, bool expected_worker_state, - unsigned start_worker_idx, + WorkerId start_worker_idx, bool exclude_start = true) { return worker_state.template probe_by_value( @@ -100,7 +100,7 @@ namespace redGrapes TTask* steal_new_task(Worker& worker) { std::optional task = probe_worker_by_state( - [&worker, this](unsigned idx) -> std::optional + [&worker, this](WorkerId idx) -> std::optional { // we have a candidate of a busy worker, // now check its queue @@ -131,7 +131,7 @@ namespace redGrapes TTask* steal_ready_task(Worker& worker) { std::optional task = probe_worker_by_state( - [&worker, this](unsigned idx) -> std::optional + [&worker, this](WorkerId idx) -> std::optional { // we have a candidate of a busy worker, // now check its queue @@ -160,7 +160,7 @@ namespace redGrapes // @return task if a new task was found, nullptr otherwise TTask* steal_task(Worker& worker) { - unsigned local_worker_id = worker.id - m_base_id; + WorkerId local_worker_id = worker.id - m_base_id; SPDLOG_DEBUG("steal task for worker {}", local_worker_id); @@ -188,9 +188,8 @@ namespace redGrapes private: std::vector>> workers; - HwlocContext* hwloc_ctx_p; AtomicBitfield worker_state; - unsigned int num_workers; + WorkerId num_workers; WorkerId m_base_id; }; diff --git a/redGrapes/dispatch/thread/worker_pool.tpp b/redGrapes/dispatch/thread/worker_pool.tpp index d3117adc..28b7d86a 100644 --- a/redGrapes/dispatch/thread/worker_pool.tpp +++ b/redGrapes/dispatch/thread/worker_pool.tpp @@ -42,10 +42,10 @@ namespace redGrapes SPDLOG_DEBUG("populate WorkerPool with {} workers", num_workers); for(size_t worker_id = base_id; worker_id < base_id + num_workers; ++worker_id) { - unsigned pu_id = worker_id % TaskFreeCtx::n_pus; + WorkerId pu_id = worker_id % TaskFreeCtx::n_pus; // allocate worker with id `i` on arena `i`, hwloc_obj_t obj = hwloc_get_obj_by_type(TaskFreeCtx::hwloc_ctx.topology, HWLOC_OBJ_PU, pu_id); - TaskFreeCtx::worker_alloc_pool->allocs.emplace_back( + TaskFreeCtx::worker_alloc_pool.allocs.emplace_back( memory::HwlocAlloc(TaskFreeCtx::hwloc_ctx, obj), REDGRAPES_ALLOC_CHUNKSIZE); @@ -82,12 +82,12 @@ namespace redGrapes SPDLOG_TRACE("find worker..."); - unsigned start_idx = 0; + WorkerId start_idx = 0; if(TaskFreeCtx::current_worker_id) start_idx = *TaskFreeCtx::current_worker_id - m_base_id; - std::optional idx = this->probe_worker_by_state( - [this](unsigned idx) -> std::optional + std::optional idx = this->probe_worker_by_state( + [this](WorkerId idx) -> std::optional { if(set_worker_state(idx, WorkerState::BUSY)) return idx; diff --git a/redGrapes/memory/allocator.hpp b/redGrapes/memory/allocator.hpp index ffd83e27..64225811 100644 --- a/redGrapes/memory/allocator.hpp +++ b/redGrapes/memory/allocator.hpp @@ -34,12 +34,12 @@ namespace redGrapes Block allocate(size_t n_bytes) { - return TaskFreeCtx::worker_alloc_pool->get_alloc(worker_id).allocate(n_bytes); + return TaskFreeCtx::worker_alloc_pool.get_alloc(worker_id).allocate(n_bytes); } void deallocate(Block blk) { - TaskFreeCtx::worker_alloc_pool->get_alloc(worker_id).deallocate(blk); + TaskFreeCtx::worker_alloc_pool.get_alloc(worker_id).deallocate(blk); } }; diff --git a/redGrapes/redGrapes.hpp b/redGrapes/redGrapes.hpp index 658e4db0..c29bd51b 100644 --- a/redGrapes/redGrapes.hpp +++ b/redGrapes/redGrapes.hpp @@ -48,15 +48,13 @@ namespace redGrapes TaskFreeCtx::n_workers = std::apply([](auto... args) { return (args.scheduler->n_workers + ...); }, execDescTuple); - TaskFreeCtx::n_pus = hwloc_get_nbobjs_by_type(TaskFreeCtx::hwloc_ctx.topology, HWLOC_OBJ_PU); if(TaskFreeCtx::n_workers > TaskFreeCtx::n_pus) SPDLOG_WARN( "{} worker-threads requested, but only {} PUs available!", TaskFreeCtx::n_workers, TaskFreeCtx::n_pus); - TaskFreeCtx::worker_alloc_pool = std::make_shared(); - TaskFreeCtx::worker_alloc_pool->allocs.reserve(TaskFreeCtx::n_workers); + TaskFreeCtx::worker_alloc_pool.allocs.reserve(TaskFreeCtx::n_workers); TaskCtx::root_space = std::make_shared>(); @@ -65,7 +63,7 @@ namespace redGrapes scheduler->init(base_worker_id); base_worker_id = base_worker_id + scheduler->n_workers; }; - unsigned base_worker_id = 0; + WorkerId base_worker_id = 0; std::apply( [&base_worker_id, initAdd](auto... args) { ((initAdd(args.scheduler, base_worker_id)), ...); }, execDescTuple); diff --git a/redGrapes/resource/resource.hpp b/redGrapes/resource/resource.hpp index 0e8a74eb..3ed1c26b 100644 --- a/redGrapes/resource/resource.hpp +++ b/redGrapes/resource/resource.hpp @@ -34,6 +34,8 @@ namespace redGrapes { + using ResourceID = uint16_t; + template class Resource; @@ -41,30 +43,29 @@ namespace redGrapes class ResourceBase { protected: - static unsigned int generateID() + static ResourceID generateID() { - static std::atomic id_counter; + static std::atomic id_counter; return id_counter.fetch_add(1); } public: - unsigned int id; - unsigned int scope_level; - - SpinLock users_mutex; ChunkedList users; + SpinLock users_mutex; + ResourceID id; + uint8_t scope_level; /** * Create a new resource with an unused ID. */ ResourceBase() - : id(generateID()) + : users(memory::Allocator(get_arena_id())) + , id(generateID()) , scope_level(TaskCtx::scope_depth()) - , users(memory::Allocator(get_arena_id())) { } - unsigned get_arena_id() const + WorkerId get_arena_id() const { return id % TaskFreeCtx::n_workers; } @@ -158,7 +159,7 @@ namespace redGrapes return this->obj->resource->scope_level; } - unsigned int resource_id() const + ResourceID resource_id() const { return this->obj->resource->id; } @@ -267,7 +268,7 @@ namespace redGrapes Access(Access&& other) : ResourceAccess::AccessBase( - std::move(std::forward::AccessBase>(other))) // TODO check this + std::move(std::forward::AccessBase>(other))) // TODO check this , policy(std::move(other.policy)) { } @@ -322,10 +323,10 @@ namespace redGrapes public: Resource() { - static unsigned i = 0; + static ResourceID i = 0; - WorkerId worker_id = i++ % TaskFreeCtx::n_workers; - base = redGrapes::memory::alloc_shared_bind>(worker_id); + i = i++ % TaskFreeCtx::n_workers; + base = redGrapes::memory::alloc_shared_bind>(i); } /** diff --git a/redGrapes/resource/resource_user.hpp b/redGrapes/resource/resource_user.hpp index bddd923f..5ac9d295 100644 --- a/redGrapes/resource/resource_user.hpp +++ b/redGrapes/resource/resource_user.hpp @@ -65,10 +65,9 @@ namespace redGrapes return false; } - uint8_t scope_level; - ChunkedList, 8> access_list; ChunkedList, 8> unique_resources; + uint8_t scope_level; }; // struct ResourceUser } // namespace redGrapes diff --git a/redGrapes/scheduler/cuda_thread_scheduler.hpp b/redGrapes/scheduler/cuda_thread_scheduler.hpp index d507e250..c8f98fbb 100644 --- a/redGrapes/scheduler/cuda_thread_scheduler.hpp +++ b/redGrapes/scheduler/cuda_thread_scheduler.hpp @@ -36,10 +36,10 @@ namespace redGrapes // TODO check if it was already initalized if(!this->m_worker_thread) { - unsigned pu_id = base_id % TaskFreeCtx::n_pus; + WorkerId pu_id = base_id % TaskFreeCtx::n_pus; // allocate worker with id `i` on arena `i`, hwloc_obj_t obj = hwloc_get_obj_by_type(TaskFreeCtx::hwloc_ctx.topology, HWLOC_OBJ_PU, pu_id); - TaskFreeCtx::worker_alloc_pool->allocs.emplace_back( + TaskFreeCtx::worker_alloc_pool.allocs.emplace_back( memory::HwlocAlloc(TaskFreeCtx::hwloc_ctx, obj), REDGRAPES_ALLOC_CHUNKSIZE); diff --git a/redGrapes/scheduler/event.hpp b/redGrapes/scheduler/event.hpp index 239acf8c..ee883375 100644 --- a/redGrapes/scheduler/event.hpp +++ b/redGrapes/scheduler/event.hpp @@ -40,9 +40,9 @@ namespace redGrapes template struct EventPtr { - enum EventPtrTag tag; - TTask* task; std::shared_ptr> external_event; + TTask* task; + enum EventPtrTag tag = T_UNINITIALIZED; inline bool operator==(EventPtr const& other) const { @@ -84,16 +84,16 @@ namespace redGrapes template struct Event { + //! the set of subsequent events + ChunkedList, REDGRAPES_EVENT_FOLLOWER_LIST_CHUNKSIZE> followers; + /*! number of incoming edges * state == 0: event is reached and can be removed */ - std::atomic_uint16_t state; - + std::atomic state; //! waker that is waiting for this event WakerId waker_id; - //! the set of subsequent events - ChunkedList, REDGRAPES_EVENT_FOLLOWER_LIST_CHUNKSIZE> followers; Event(); Event(Event&); diff --git a/redGrapes/scheduler/pool_scheduler.hpp b/redGrapes/scheduler/pool_scheduler.hpp index 0b9b968a..b9809ede 100644 --- a/redGrapes/scheduler/pool_scheduler.hpp +++ b/redGrapes/scheduler/pool_scheduler.hpp @@ -25,11 +25,11 @@ namespace redGrapes { using TTask = Worker::task_type; WorkerId m_base_id; - unsigned n_workers; - std::shared_ptr> m_worker_pool; + WorkerId n_workers; + dispatch::thread::WorkerPool m_worker_pool; - PoolScheduler(unsigned num_workers); - PoolScheduler(std::shared_ptr> workerPool); + PoolScheduler(WorkerId num_workers); + PoolScheduler(dispatch::thread::WorkerPool workerPool); /* send the new task to a worker */ @@ -53,7 +53,7 @@ namespace redGrapes */ void wake_all(); - unsigned getNextWorkerID(); + WorkerId getNextWorkerID(); void init(WorkerId base_id); diff --git a/redGrapes/scheduler/pool_scheduler.tpp b/redGrapes/scheduler/pool_scheduler.tpp index 98e97ed9..0dce91a7 100644 --- a/redGrapes/scheduler/pool_scheduler.tpp +++ b/redGrapes/scheduler/pool_scheduler.tpp @@ -19,14 +19,13 @@ namespace redGrapes namespace scheduler { template - PoolScheduler::PoolScheduler(unsigned num_workers) - : n_workers(num_workers) - , m_worker_pool(std::make_shared>(num_workers)) + PoolScheduler::PoolScheduler(WorkerId num_workers) : n_workers(num_workers) + , m_worker_pool(num_workers) { } template - PoolScheduler::PoolScheduler(std::shared_ptr> workerPool) + PoolScheduler::PoolScheduler(dispatch::thread::WorkerPool workerPool) : m_worker_pool(workerPool) { } @@ -39,7 +38,7 @@ namespace redGrapes // TODO: properly store affinity information in task WorkerId local_worker_id = task.worker_id - m_base_id; - m_worker_pool->get_worker_thread(local_worker_id).worker.dispatch_task(task); + m_worker_pool.get_worker_thread(local_worker_id).worker.dispatch_task(task); /* hack as of 2023/11/17 * @@ -53,10 +52,10 @@ namespace redGrapes #endif #if REDGRAPES_EMPLACE_NOTIFY_NEXT - auto id = m_worker_pool->probe_worker_by_state( - [&m_worker_pool](unsigned idx) + auto id = m_worker_pool.probe_worker_by_state( + [&m_worker_pool](WorkerId idx) { - m_worker_pool->get_worker_thread(idx).worker.wake(); + m_worker_pool.get_worker_thread(idx).worker.wake(); return idx; }, dispatch::thread::WorkerState::AVAILABLE, @@ -74,12 +73,12 @@ namespace redGrapes { //! worker id to use in case all workers are busy // TODO analyse and optimize - static thread_local std::atomic next_worker( + static thread_local std::atomic next_worker( TaskFreeCtx::current_worker_id ? *TaskFreeCtx::current_worker_id + 1 - m_base_id : 0); TRACE_EVENT("Scheduler", "activate_task"); SPDLOG_TRACE("PoolScheduler::activate_task({})", task.task_id); - int worker_id = m_worker_pool->find_free_worker(); + int worker_id = m_worker_pool.find_free_worker(); if(worker_id < 0) { worker_id = next_worker.fetch_add(1) % n_workers; @@ -87,9 +86,9 @@ namespace redGrapes worker_id = next_worker.fetch_add(1) % n_workers; } - m_worker_pool->get_worker_thread(worker_id).worker.ready_queue.push(&task); - m_worker_pool->set_worker_state(worker_id, dispatch::thread::WorkerState::BUSY); - m_worker_pool->get_worker_thread(worker_id).worker.wake(); + m_worker_pool.get_worker_thread(worker_id).worker.ready_queue.push(&task); + m_worker_pool.set_worker_state(worker_id, dispatch::thread::WorkerState::BUSY); + m_worker_pool.get_worker_thread(worker_id).worker.wake(); } /* Wakeup some worker or the main thread @@ -104,7 +103,7 @@ namespace redGrapes auto local_waker_id = id - m_base_id; // TODO analyse and optimize if(local_waker_id > 0 && local_waker_id <= n_workers) - return m_worker_pool->get_worker_thread(local_waker_id).worker.wake(); + return m_worker_pool.get_worker_thread(local_waker_id).worker.wake(); else return false; } @@ -114,12 +113,12 @@ namespace redGrapes template void PoolScheduler::wake_all() { - for(uint16_t i = m_base_id; i < m_base_id + n_workers; ++i) + for(WorkerId i = m_base_id; i < m_base_id + n_workers; ++i) wake(i); } template - unsigned PoolScheduler::getNextWorkerID() + WorkerId PoolScheduler::getNextWorkerID() { static std::atomic local_next_worker_counter = 0; return (local_next_worker_counter++ % n_workers) + m_base_id; @@ -130,21 +129,21 @@ namespace redGrapes { // TODO check if it was already initalized m_base_id = base_id; - m_worker_pool->emplace_workers(m_base_id); + m_worker_pool.emplace_workers(m_base_id); } template void PoolScheduler::startExecution() { // TODO check if it was already started - m_worker_pool->start(); + m_worker_pool.start(); } template void PoolScheduler::stopExecution() { // TODO check if it was already stopped - m_worker_pool->stop(); + m_worker_pool.stop(); } diff --git a/redGrapes/scheduler/scheduler.hpp b/redGrapes/scheduler/scheduler.hpp index 56c6a100..5c314a1b 100644 --- a/redGrapes/scheduler/scheduler.hpp +++ b/redGrapes/scheduler/scheduler.hpp @@ -7,6 +7,8 @@ #pragma once +#include "redGrapes/TaskFreeCtx.hpp" + #include namespace redGrapes @@ -53,7 +55,7 @@ namespace redGrapes return false; } - virtual unsigned getNextWorkerID() + virtual WorkerId getNextWorkerID() { return 0; } diff --git a/redGrapes/scheduler/thread_scheduler.hpp b/redGrapes/scheduler/thread_scheduler.hpp index d76b3a17..bd34b649 100644 --- a/redGrapes/scheduler/thread_scheduler.hpp +++ b/redGrapes/scheduler/thread_scheduler.hpp @@ -26,7 +26,7 @@ namespace redGrapes WorkerId m_base_id; std::shared_ptr> m_worker_thread; - static constexpr unsigned n_workers = 1; + static constexpr WorkerId n_workers = 1; ThreadScheduler() { @@ -81,7 +81,7 @@ namespace redGrapes m_worker_thread->worker.wake(); } - unsigned getNextWorkerID() + WorkerId getNextWorkerID() { return m_base_id; } @@ -92,10 +92,10 @@ namespace redGrapes // TODO check if it was already initalized if(!m_worker_thread) { - unsigned pu_id = base_id % TaskFreeCtx::n_pus; + WorkerId pu_id = base_id % TaskFreeCtx::n_pus; // allocate worker with id `i` on arena `i`, hwloc_obj_t obj = hwloc_get_obj_by_type(TaskFreeCtx::hwloc_ctx.topology, HWLOC_OBJ_PU, pu_id); - TaskFreeCtx::worker_alloc_pool->allocs.emplace_back( + TaskFreeCtx::worker_alloc_pool.allocs.emplace_back( memory::HwlocAlloc(TaskFreeCtx::hwloc_ctx, obj), REDGRAPES_ALLOC_CHUNKSIZE); diff --git a/redGrapes/task/property/graph.hpp b/redGrapes/task/property/graph.hpp index 684d0606..a32a1f41 100644 --- a/redGrapes/task/property/graph.hpp +++ b/redGrapes/task/property/graph.hpp @@ -54,9 +54,6 @@ namespace redGrapes TTask* task; - //! number of parents - uint8_t scope_depth; - //! task space that contains this task, must not be null std::shared_ptr> space; @@ -77,22 +74,22 @@ namespace redGrapes inline scheduler::EventPtr get_pre_event() { - return scheduler::EventPtr{scheduler::T_EVT_PRE, this->task}; + return scheduler::EventPtr{nullptr, this->task, scheduler::T_EVT_PRE}; } inline scheduler::EventPtr get_post_event() { - return scheduler::EventPtr{scheduler::T_EVT_POST, this->task}; + return scheduler::EventPtr{nullptr, this->task, scheduler::T_EVT_POST}; } inline scheduler::EventPtr get_result_set_event() { - return scheduler::EventPtr{scheduler::T_EVT_RES_SET, this->task}; + return scheduler::EventPtr{nullptr, this->task, scheduler::T_EVT_RES_SET}; } inline scheduler::EventPtr get_result_get_event() { - return scheduler::EventPtr{scheduler::T_EVT_RES_GET, this->task}; + return scheduler::EventPtr{nullptr, this->task, scheduler::T_EVT_RES_GET}; } inline bool is_ready() @@ -178,7 +175,7 @@ namespace redGrapes }; }; - void apply_patch(Patch const&){}; + void apply_patch(Patch const&) {}; }; } // namespace redGrapes diff --git a/redGrapes/task/property/graph.tpp b/redGrapes/task/property/graph.tpp index 752d48fc..a348beca 100644 --- a/redGrapes/task/property/graph.tpp +++ b/redGrapes/task/property/graph.tpp @@ -22,7 +22,7 @@ namespace redGrapes { auto event = memory::alloc_shared>(); event->add_follower(get_post_event()); - return scheduler::EventPtr{scheduler::T_EVT_EXT, task, event}; + return scheduler::EventPtr{event, task, scheduler::T_EVT_EXT}; } /*! diff --git a/redGrapes/task/property/id.hpp b/redGrapes/task/property/id.hpp index d18c9ebe..09d23581 100644 --- a/redGrapes/task/property/id.hpp +++ b/redGrapes/task/property/id.hpp @@ -23,9 +23,9 @@ namespace redGrapes struct IDProperty { private: - static std::atomic_int& id_counter() + static std::atomic& id_counter() { - static std::atomic_int x; + static std::atomic x; return x; } diff --git a/redGrapes/task/task.hpp b/redGrapes/task/task.hpp index 135dd206..bc9635cf 100644 --- a/redGrapes/task/task.hpp +++ b/redGrapes/task/task.hpp @@ -12,6 +12,7 @@ #include "redGrapes/task/property/resource.hpp" #include "redGrapes/task/task_base.hpp" +#include #include namespace redGrapes @@ -29,15 +30,15 @@ namespace redGrapes struct Task : TaskBase> , TaskProperties1< - IDProperty, - ResourceProperty>, GraphProperty>, + ResourceProperty>, + IDProperty, UserTaskProperties...> { using TaskProperties = TaskProperties1< - IDProperty, - ResourceProperty>, GraphProperty>, + ResourceProperty>, + IDProperty, UserTaskProperties...>; virtual ~Task() @@ -45,8 +46,8 @@ namespace redGrapes } // worker id where task is first emplaced and task memory is located (may be stolen later) - unsigned worker_id; - std::atomic_int removal_countdown; + WorkerId worker_id; + std::atomic removal_countdown; scheduler::IScheduler>* scheduler_p; Task(scheduler::IScheduler>& scheduler) diff --git a/redGrapes/task/task_space.hpp b/redGrapes/task/task_space.hpp index 6ad728fc..e7439a7e 100644 --- a/redGrapes/task/task_space.hpp +++ b/redGrapes/task/task_space.hpp @@ -9,6 +9,7 @@ #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/memory/block.hpp" +#include "redGrapes/task/property/id.hpp" #include "redGrapes/util/trace.hpp" #include @@ -22,7 +23,7 @@ namespace redGrapes template struct TaskSpace : std::enable_shared_from_this> { - std::atomic task_count; + std::atomic task_count; unsigned depth; TTask* parent; @@ -64,13 +65,13 @@ namespace redGrapes void free_task(TTask* task) { TRACE_EVENT("TaskSpace", "free_task()"); - unsigned count = task_count.fetch_sub(1) - 1; + TaskID count = task_count.fetch_sub(1) - 1; - unsigned worker_id = task->worker_id; + WorkerId worker_id = task->worker_id; task->~TTask(); // FIXME: len of the Block is not correct since FunTask object is bigger than sizeof(Task) - TaskFreeCtx::worker_alloc_pool->get_alloc(worker_id).deallocate( + TaskFreeCtx::worker_alloc_pool.get_alloc(worker_id).deallocate( memory::Block{(uintptr_t) task, sizeof(TTask)}); // TODO: implement this using post-event of root-task? @@ -90,7 +91,7 @@ namespace redGrapes bool empty() const { - unsigned tc = task_count.load(); + TaskID tc = task_count.load(); return tc == 0; } };