diff --git a/examples/1_resources.cpp b/examples/1_resources.cpp index 9ba8a173..b3303a29 100644 --- a/examples/1_resources.cpp +++ b/examples/1_resources.cpp @@ -27,10 +27,10 @@ int main(int, char*[]) redGrapes::ResourceUser user3({b.read(), c.write()}); - std::cout << "is_serial(user1,user1) = " << redGrapes::ResourceUser::is_serial(user1, user1) << std::endl; - std::cout << "is_serial(user1,user2) = " << redGrapes::ResourceUser::is_serial(user1, user2) << std::endl; - std::cout << "is_serial(user1,user3) = " << redGrapes::ResourceUser::is_serial(user1, user3) << std::endl; - std::cout << "is_serial(user2,user3) = " << redGrapes::ResourceUser::is_serial(user2, user3) << std::endl; + std::cout << "is_serial(user1,user1) = " << is_serial(user1, user1) << std::endl; + std::cout << "is_serial(user1,user2) = " << is_serial(user1, user2) << std::endl; + std::cout << "is_serial(user1,user3) = " << is_serial(user1, user3) << std::endl; + std::cout << "is_serial(user2,user3) = " << is_serial(user2, user3) << std::endl; return 0; } diff --git a/examples/6_resource_scope.cpp b/examples/6_resource_scope.cpp index e049ec09..283c9737 100644 --- a/examples/6_resource_scope.cpp +++ b/examples/6_resource_scope.cpp @@ -8,6 +8,8 @@ #include #include +#include + namespace rg = redGrapes; int main() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6f2d4cf1..b2ddd839 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -55,7 +55,7 @@ if(CMAKE_CUDA_COMPILER) enable_language(CUDA) add_executable(cuda_mandelbrot cuda_mandelbrot.cu) - target_compile_features(cuda_mandelbrot PUBLIC cuda_std_14) + target_compile_features(cuda_mandelbrot PUBLIC cxx_std_${redGrapes_CXX_STANDARD}) set_target_properties(cuda_mandelbrot PROPERTIES CUDA_EXTENSIONS OFF CUDA_STANDARD_REQUIRED ON diff --git a/examples/cholesky.cpp b/examples/cholesky.cpp index eb87b598..0b20402f 100644 --- a/examples/cholesky.cpp +++ b/examples/cholesky.cpp @@ -5,24 +5,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include - -#include -// work-around, see -// https://github.com/xianyi/OpenBLAS/issues/1992#issuecomment-459474791 -// https://github.com/xianyi/OpenBLAS/pull/1998 -#include -#define lapack_complex_float std::complex -#define lapack_complex_double std::complex -// end work-around +#include +#include +#include #include -#define REDGRAPES_TASK_PROPERTIES redGrapes::LabelProperty - -#include "redGrapes/resource/ioresource.hpp" - -#include +#include template void print_matrix(std::vector> A, int nblks, int blocksize) @@ -139,7 +128,7 @@ int main(int argc, char* argv[]) { // A[j,j] = A[j,j] - A[j,i] * (A[j,i])^t rg.emplace_task( - [blksz, nblks](auto a, auto c) + [blksz](auto a, auto c) { spdlog::debug("dsyrk"); cblas_dsyrk( @@ -161,7 +150,7 @@ int main(int argc, char* argv[]) // Cholesky Factorization of A[j,j] rg.emplace_task( - [j, blksz, nblks](auto a) + [blksz](auto a) { spdlog::debug("dpotrf"); LAPACKE_dpotrf(LAPACK_COL_MAJOR, 'L', blksz, *a, blksz); @@ -172,7 +161,7 @@ int main(int argc, char* argv[]) { // A[i,j] <- A[i,j] = X * (A[j,j])^t rg.emplace_task( - [blksz, nblks](auto a, auto b) + [blksz](auto a, auto b) { spdlog::debug("dtrsm"); cblas_dtrsm( diff --git a/examples/mpi.cpp b/examples/mpi.cpp index 532ecdee..c6acc3fe 100644 --- a/examples/mpi.cpp +++ b/examples/mpi.cpp @@ -4,6 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#define ENABLE_WORKSTEALING 1 #include #include @@ -14,6 +15,8 @@ #include #include +#include + /** * This example shows how to use MPI with redGrapes. * @@ -40,8 +43,6 @@ enum SchedulerTags SCHED_CUDA }; -#define ENABLE_WORKSTEALING 1 - struct MPIConfig { int world_rank; @@ -64,16 +65,15 @@ int main() auto rg = redGrapes::init( redGrapes::SchedulerDescription( - std::make_shared< - redGrapes::scheduler::PoolScheduler>>(17), + std::make_shared>>( + 17), UselessWorkers{}), redGrapes::SchedulerDescription( - std::make_shared< - redGrapes::scheduler::PoolScheduler>>(4), + std::make_shared>>( + 4), redGrapes::DefaultTag{}), redGrapes::SchedulerDescription( - std::make_shared< - redGrapes::scheduler::ThreadScheduler>>(), + std::make_shared>>(), MPITag{})); diff --git a/redGrapes/TaskFreeCtx.hpp b/redGrapes/TaskFreeCtx.hpp index 0b1e08b9..d32bd212 100644 --- a/redGrapes/TaskFreeCtx.hpp +++ b/redGrapes/TaskFreeCtx.hpp @@ -10,6 +10,11 @@ #include "redGrapes/memory/chunked_bump_alloc.hpp" #include "redGrapes/memory/hwloc_alloc.hpp" +#include +#include +#include +#include + namespace redGrapes { diff --git a/redGrapes/dispatch/mpi/mpiWorker.hpp b/redGrapes/dispatch/mpi/mpiWorker.hpp index 5c4040f6..7230161a 100644 --- a/redGrapes/dispatch/mpi/mpiWorker.hpp +++ b/redGrapes/dispatch/mpi/mpiWorker.hpp @@ -23,6 +23,7 @@ namespace redGrapes template struct MPIWorker { + using task_type = TTask; std::shared_ptr> requestPool; WorkerId id; diff --git a/redGrapes/dispatch/thread/DefaultWorker.hpp b/redGrapes/dispatch/thread/DefaultWorker.hpp index cfe4a7be..7610a040 100644 --- a/redGrapes/dispatch/thread/DefaultWorker.hpp +++ b/redGrapes/dispatch/thread/DefaultWorker.hpp @@ -25,7 +25,7 @@ namespace redGrapes namespace thread { - template + template struct WorkerPool; /*! @@ -37,10 +37,11 @@ namespace redGrapes template struct DefaultWorker { + using task_type = TTask; // private: WorkerId id; AtomicBitfield& m_worker_state; - WorkerPool& m_worker_pool; + WorkerPool& m_worker_pool; /*! if true, the thread shall stop * instead of waiting when it is out of jobs @@ -57,10 +58,7 @@ namespace redGrapes task::Queue emplacement_queue{queue_capacity}; task::Queue ready_queue{queue_capacity}; - DefaultWorker( - WorkerId worker_id, - AtomicBitfield& worker_state, - WorkerPool& worker_pool) + DefaultWorker(WorkerId worker_id, AtomicBitfield& worker_state, WorkerPool& worker_pool) : id(worker_id) , m_worker_state(worker_state) , m_worker_pool(worker_pool) @@ -117,3 +115,5 @@ namespace redGrapes } // namespace thread } // namespace dispatch } // namespace redGrapes + +#include "redGrapes/dispatch/thread/DefaultWorker.tpp" diff --git a/redGrapes/dispatch/thread/WorkerThread.hpp b/redGrapes/dispatch/thread/WorkerThread.hpp index eed339f9..132fe31a 100644 --- a/redGrapes/dispatch/thread/WorkerThread.hpp +++ b/redGrapes/dispatch/thread/WorkerThread.hpp @@ -18,7 +18,7 @@ namespace redGrapes::dispatch::thread { - template + template struct WorkerThread { std::thread thread; @@ -48,7 +48,7 @@ namespace redGrapes::dispatch::thread hwloc_obj_t const obj, WorkerId worker_id, AtomicBitfield& worker_state, - WorkerPool& worker_pool) + WorkerPool& worker_pool) : alloc(alloc) , hwloc_ctx(hwloc_ctx) , obj{obj} diff --git a/redGrapes/dispatch/thread/cpuset.hpp b/redGrapes/dispatch/thread/cpuset.hpp deleted file mode 100644 index 27c2bff1..00000000 --- a/redGrapes/dispatch/thread/cpuset.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2023 Michael Sippel - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include - -namespace redGrapes -{ - namespace dispatch - { - namespace thread - { - - inline void pin_cpu(unsigned cpuidx) - { - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(cpuidx % CPU_SETSIZE, &cpuset); - - int rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if(rc != 0) - spdlog::error("cannot set thread affinity ({})", rc); - } - - inline void unpin_cpu() - { - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - for(int j = 0; j < 64; ++j) - CPU_SET(j, &cpuset); - - int rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if(rc != 0) - spdlog::error("cannot set thread affinity ({})", rc); - } - - - } // namespace thread - } // namespace dispatch -} // namespace redGrapes diff --git a/redGrapes/dispatch/thread/worker_pool.hpp b/redGrapes/dispatch/thread/worker_pool.hpp index 8f7a8225..48b238d5 100644 --- a/redGrapes/dispatch/thread/worker_pool.hpp +++ b/redGrapes/dispatch/thread/worker_pool.hpp @@ -7,7 +7,6 @@ #pragma once #include "redGrapes/TaskFreeCtx.hpp" -#include "redGrapes/dispatch/thread/DefaultWorker.hpp" #include "redGrapes/memory/hwloc_alloc.hpp" #include "redGrapes/util/bitfield.hpp" @@ -27,12 +26,15 @@ namespace redGrapes AVAILABLE = 1 }; - template + template struct WorkerThread; - template + template struct WorkerPool { + using task_type = Worker::task_type; + using TTask = task_type; + WorkerPool(HwlocContext& hwloc_ctx, size_t n_workers); ~WorkerPool(); @@ -53,7 +55,7 @@ namespace redGrapes */ void stop(); - inline WorkerThread& get_worker_thread(WorkerId local_worker_id) + inline WorkerThread& get_worker_thread(WorkerId local_worker_id) { assert(local_worker_id < size()); return *workers[local_worker_id]; @@ -96,7 +98,7 @@ namespace redGrapes * task-graph in the emplacement queues of other workers * and removes it from there */ - TTask* steal_new_task(dispatch::thread::DefaultWorker& worker) + TTask* steal_new_task(Worker& worker) { std::optional task = probe_worker_by_state( [&worker, this](unsigned idx) -> std::optional @@ -127,7 +129,7 @@ namespace redGrapes /* tries to find a ready task in any queue of other workers * and removes it from the queue */ - TTask* steal_ready_task(dispatch::thread::DefaultWorker& worker) + TTask* steal_ready_task(Worker& worker) { std::optional task = probe_worker_by_state( [&worker, this](unsigned idx) -> std::optional @@ -157,7 +159,7 @@ namespace redGrapes // give worker a ready task if available // @return task if a new task was found, nullptr otherwise - TTask* steal_task(dispatch::thread::DefaultWorker& worker) + TTask* steal_task(Worker& worker) { unsigned local_worker_id = worker.id - m_base_id; @@ -186,7 +188,7 @@ namespace redGrapes private: - std::vector>> workers; + std::vector>> workers; HwlocContext& hwloc_ctx; AtomicBitfield worker_state; unsigned int num_workers; @@ -197,3 +199,5 @@ namespace redGrapes } // namespace thread } // namespace dispatch } // namespace redGrapes + +#include "redGrapes/dispatch/thread/worker_pool.tpp" diff --git a/redGrapes/dispatch/thread/worker_pool.tpp b/redGrapes/dispatch/thread/worker_pool.tpp index eb3fb0aa..1dfcd49f 100644 --- a/redGrapes/dispatch/thread/worker_pool.tpp +++ b/redGrapes/dispatch/thread/worker_pool.tpp @@ -21,16 +21,16 @@ namespace redGrapes { namespace thread { - template - WorkerPool::WorkerPool(HwlocContext& hwloc_ctx, size_t n_workers) + template + WorkerPool::WorkerPool(HwlocContext& hwloc_ctx, size_t n_workers) : hwloc_ctx(hwloc_ctx) , worker_state(n_workers) , num_workers(n_workers) { } - template - void WorkerPool::emplace_workers(WorkerId base_id) + template + void WorkerPool::emplace_workers(WorkerId base_id) { m_base_id = base_id; if(num_workers > TaskFreeCtx::n_pus) @@ -51,7 +51,7 @@ namespace redGrapes memory::HwlocAlloc(TaskFreeCtx::hwloc_ctx, obj), REDGRAPES_ALLOC_CHUNKSIZE); - auto worker = memory::alloc_shared_bind>( + auto worker = memory::alloc_shared_bind>( worker_id, TaskFreeCtx::worker_alloc_pool->get_alloc(worker_id), TaskFreeCtx::hwloc_ctx, @@ -63,20 +63,20 @@ namespace redGrapes } } - template - WorkerPool::~WorkerPool() + template + WorkerPool::~WorkerPool() { } - template - void WorkerPool::start() + template + void WorkerPool::start() { for(auto& worker : workers) worker->start(); } - template - void WorkerPool::stop() + template + void WorkerPool::stop() { for(auto& worker : workers) worker->stop(); @@ -84,8 +84,8 @@ namespace redGrapes workers.clear(); } - template - int WorkerPool::find_free_worker() + template + int WorkerPool::find_free_worker() { TRACE_EVENT("Scheduler", "find_worker"); diff --git a/redGrapes/redGrapes.hpp b/redGrapes/redGrapes.hpp index 690fab0c..78577bbb 100644 --- a/redGrapes/redGrapes.hpp +++ b/redGrapes/redGrapes.hpp @@ -16,6 +16,7 @@ #include "redGrapes/scheduler/event.hpp" #include "redGrapes/scheduler/pool_scheduler.hpp" #include "redGrapes/task/task.hpp" +#include "redGrapes/task/task_builder.hpp" #include "redGrapes/task/task_space.hpp" #include "redGrapes/util/bind_args.hpp" #include "redGrapes/util/tuple_map.hpp" @@ -26,9 +27,6 @@ #include #include -// `TaskBuilder` needs "RedGrapes`, so can only include here after definiton -#include "redGrapes/task/task_builder.hpp" // TODO change this to needs LocalImpl - namespace redGrapes { @@ -219,22 +217,22 @@ namespace redGrapes }; // TODO make sure init can only be called once - template - [[nodiscard]] inline auto init(Ts... execDescs) + // require atleast one T execDesc + template + [[nodiscard]] inline auto init(T execDesc, Ts... execDescs) { - using DescType = boost::mp11::mp_list; + using DescType = boost::mp11::mp_list; using DescMap = boost::mp11::mp_transform; - return RedGrapes(execDescs...); + return RedGrapes(execDesc, execDescs...); } template [[nodiscard]] inline auto init(size_t n_workers = std::thread::hardware_concurrency()) { auto execDesc = SchedulerDescription( - std::make_shared, - dispatch::thread::DefaultWorker>>>(n_workers), + std::make_shared>>>( + n_workers), DefaultTag{}); using DescType = boost::mp11::mp_list; using DescMap = boost::mp11::mp_transform; @@ -245,12 +243,4 @@ namespace redGrapes } // namespace redGrapes -#include "redGrapes/dispatch/thread/DefaultWorker.tpp" -#include "redGrapes/dispatch/thread/worker_pool.tpp" #include "redGrapes/redGrapes.tpp" -#include "redGrapes/resource/resource_user.tpp" -#include "redGrapes/scheduler/event.tpp" -#include "redGrapes/scheduler/event_ptr.tpp" -#include "redGrapes/scheduler/pool_scheduler.tpp" -#include "redGrapes/task/property/graph.tpp" -#include "redGrapes/util/trace.tpp" diff --git a/redGrapes/resource/access/area.hpp b/redGrapes/resource/access/area.hpp index 521b353c..b1e2062b 100644 --- a/redGrapes/resource/access/area.hpp +++ b/redGrapes/resource/access/area.hpp @@ -72,6 +72,6 @@ struct fmt::formatter template auto format(redGrapes::access::AreaAccess const& acc, FormatContext& ctx) { - return format_to(ctx.out(), "{{ \"area\" : {{ \"begin\" : {}, \"end\" : {} }} }}", acc[0], acc[1]); + return fmt::format_to(ctx.out(), "{{ \"area\" : {{ \"begin\" : {}, \"end\" : {} }} }}", acc[0], acc[1]); } }; diff --git a/redGrapes/resource/access/combine.hpp b/redGrapes/resource/access/combine.hpp index 85617c60..12387cf4 100644 --- a/redGrapes/resource/access/combine.hpp +++ b/redGrapes/resource/access/combine.hpp @@ -14,7 +14,6 @@ #include #include -#include #include namespace redGrapes diff --git a/redGrapes/resource/resource.hpp b/redGrapes/resource/resource.hpp index c2730ac9..0e8a74eb 100644 --- a/redGrapes/resource/resource.hpp +++ b/redGrapes/resource/resource.hpp @@ -215,13 +215,16 @@ namespace redGrapes }; } // namespace trait - struct DefaultAccessPolicy + namespace access { - static bool is_serial(DefaultAccessPolicy, DefaultAccessPolicy) + struct DefaultAccessPolicy { - return true; - } - }; + static bool is_serial(DefaultAccessPolicy, DefaultAccessPolicy) + { + return true; + } + }; + } // namespace access /** * @defgroup AccessPolicy @@ -250,7 +253,7 @@ namespace redGrapes * Represents a concrete resource. * Copied objects represent the same resource. */ - template + template class Resource { protected: diff --git a/redGrapes/resource/resource_user.hpp b/redGrapes/resource/resource_user.hpp index f14759db..46f8e6cf 100644 --- a/redGrapes/resource/resource_user.hpp +++ b/redGrapes/resource/resource_user.hpp @@ -43,9 +43,8 @@ namespace redGrapes }; template - class ResourceUser + struct ResourceUser { - public: ResourceUser(); ResourceUser(ResourceUser const& other); ResourceUser(std::initializer_list> list); @@ -55,14 +54,25 @@ namespace redGrapes void build_unique_resource_list(); bool has_sync_access(std::shared_ptr> const& res); bool is_superset_of(ResourceUser const& a) const; - static bool is_superset(ResourceUser const& a, ResourceUser const& b); - static bool is_serial(ResourceUser const& a, ResourceUser const& b); + + friend bool is_serial(ResourceUser const& a, ResourceUser const& b) + { + TRACE_EVENT("ResourceUser", "is_serial"); + for(auto ra = a.access_list.crbegin(); ra != a.access_list.crend(); ++ra) + for(auto rb = b.access_list.crbegin(); rb != b.access_list.crend(); ++rb) + { + TRACE_EVENT("ResourceUser", "RA::is_serial"); + if(ResourceAccess::is_serial(*ra, *rb)) + return true; + } + return false; + } uint8_t scope_level; ChunkedList, 8> access_list; ChunkedList, 8> unique_resources; - }; // class ResourceUser + }; // struct ResourceUser } // namespace redGrapes @@ -91,3 +101,5 @@ struct fmt::formatter> return out; } }; + +#include "redGrapes/resource/resource_user.tpp" diff --git a/redGrapes/resource/resource_user.tpp b/redGrapes/resource/resource_user.tpp index bd78f2f8..82f45fd5 100644 --- a/redGrapes/resource/resource_user.tpp +++ b/redGrapes/resource/resource_user.tpp @@ -6,6 +6,7 @@ */ #pragma once + #include "redGrapes/TaskCtx.hpp" #include "redGrapes/resource/resource.hpp" #include "redGrapes/resource/resource_user.hpp" @@ -81,20 +82,6 @@ namespace redGrapes return false; } - template - bool ResourceUser::is_serial(ResourceUser const& a, ResourceUser const& b) - { - TRACE_EVENT("ResourceUser", "is_serial"); - for(auto ra = a.access_list.crbegin(); ra != a.access_list.crend(); ++ra) - for(auto rb = b.access_list.crbegin(); rb != b.access_list.crend(); ++rb) - { - TRACE_EVENT("ResourceUser", "RA::is_serial"); - if(ResourceAccess::is_serial(*ra, *rb)) - return true; - } - return false; - } - template bool ResourceUser::is_superset_of(ResourceUser const& a) const { @@ -113,10 +100,4 @@ namespace redGrapes return true; } - template - bool ResourceUser::is_superset(ResourceUser const& a, ResourceUser const& b) - { - return a.is_superset_of(b); - } - } // namespace redGrapes diff --git a/redGrapes/scheduler/event.hpp b/redGrapes/scheduler/event.hpp index 20813228..239acf8c 100644 --- a/redGrapes/scheduler/event.hpp +++ b/redGrapes/scheduler/event.hpp @@ -114,3 +114,6 @@ namespace redGrapes } // namespace scheduler } // namespace redGrapes + +#include "redGrapes/scheduler/event.tpp" +#include "redGrapes/scheduler/event_ptr.tpp" diff --git a/redGrapes/scheduler/pool_scheduler.hpp b/redGrapes/scheduler/pool_scheduler.hpp index 91173d3f..c5d13a95 100644 --- a/redGrapes/scheduler/pool_scheduler.hpp +++ b/redGrapes/scheduler/pool_scheduler.hpp @@ -24,17 +24,18 @@ namespace redGrapes * Uses simple round-robin algorithm to distribute tasks to workers * and implements work-stealing */ - template - struct PoolScheduler : public IScheduler + template + struct PoolScheduler : public IScheduler { + using TTask = Worker::task_type; WorkerId m_base_id; CondVar cv; WorkerId local_next_worker_id = 0; unsigned n_workers; - std::shared_ptr> m_worker_pool; + std::shared_ptr> m_worker_pool; PoolScheduler(unsigned num_workers); - PoolScheduler(std::shared_ptr> workerPool); + PoolScheduler(std::shared_ptr> workerPool); void idle(); @@ -73,3 +74,5 @@ namespace redGrapes } // namespace scheduler } // namespace redGrapes + +#include "redGrapes/scheduler/pool_scheduler.tpp" diff --git a/redGrapes/scheduler/pool_scheduler.tpp b/redGrapes/scheduler/pool_scheduler.tpp index 97e8d5cf..82e8a4d8 100644 --- a/redGrapes/scheduler/pool_scheduler.tpp +++ b/redGrapes/scheduler/pool_scheduler.tpp @@ -18,23 +18,22 @@ namespace redGrapes { namespace scheduler { - template - PoolScheduler::PoolScheduler(unsigned num_workers) + template + PoolScheduler::PoolScheduler(unsigned num_workers) : n_workers(num_workers) , m_worker_pool( - std::make_shared>(TaskFreeCtx::hwloc_ctx, num_workers)) + std::make_shared>(TaskFreeCtx::hwloc_ctx, num_workers)) { } - template - PoolScheduler::PoolScheduler( - std::shared_ptr> workerPool) + template + PoolScheduler::PoolScheduler(std::shared_ptr> workerPool) : m_worker_pool(workerPool) { } - template - void PoolScheduler::idle() + template + void PoolScheduler::idle() { SPDLOG_TRACE("PoolScheduler::idle()"); @@ -49,8 +48,8 @@ namespace redGrapes /* send the new task to a worker */ - template - void PoolScheduler::emplace_task(TTask& task) + template + void PoolScheduler::emplace_task(TTask& task) { // TODO: properly store affinity information in task WorkerId worker_id = task.worker_id - m_base_id; @@ -85,8 +84,8 @@ namespace redGrapes * but only through follower-list so it is not assigned to a worker yet. * since this task is now ready, send find a worker for it */ - template - void PoolScheduler::activate_task(TTask& task) + template + void PoolScheduler::activate_task(TTask& task) { //! worker id to use in case all workers are busy // TODO analyse and optimize @@ -115,8 +114,8 @@ namespace redGrapes * * @return true if thread was indeed asleep */ - template - bool PoolScheduler::wake(WakerId id) + template + bool PoolScheduler::wake(WakerId id) { if(id == 0) return cv.notify(); @@ -129,16 +128,16 @@ namespace redGrapes /* wakeup all wakers (workers + main thread) */ - template - void PoolScheduler::wake_all() + template + void PoolScheduler::wake_all() { wake(0); for(uint16_t i = m_base_id; i < m_base_id + n_workers; ++i) wake(i); } - template - unsigned PoolScheduler::getNextWorkerID() + template + unsigned PoolScheduler::getNextWorkerID() { // TODO make atomic auto id = local_next_worker_id + m_base_id; @@ -146,23 +145,23 @@ namespace redGrapes return id; } - template - void PoolScheduler::init(WorkerId base_id) + template + void PoolScheduler::init(WorkerId base_id) { // TODO check if it was already initalized m_base_id = base_id; m_worker_pool->emplace_workers(m_base_id); } - template - void PoolScheduler::startExecution() + template + void PoolScheduler::startExecution() { // TODO check if it was already started m_worker_pool->start(); } - template - void PoolScheduler::stopExecution() + template + void PoolScheduler::stopExecution() { // TODO check if it was already stopped m_worker_pool->stop(); diff --git a/redGrapes/scheduler/tag_match.hpp b/redGrapes/scheduler/tag_match.hpp deleted file mode 100644 index f18ebf86..00000000 --- a/redGrapes/scheduler/tag_match.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright 2020-2024 Michael Sippel, Tapish Narwal - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - - -#include "redGrapes/scheduler/scheduler.hpp" - -#include - -#include -#include -#include -#include - -namespace redGrapes -{ - namespace scheduler - { - - template - struct TagMatch : IScheduler - { - struct SubScheduler - { - std::bitset supported_tags; - std::shared_ptr> s; - }; - - std::vector sub_schedulers; - - void add_scheduler(std::bitset supported_tags, std::shared_ptr> s) - { - sub_schedulers.push_back(SubScheduler{supported_tags, s}); - } - - void add_scheduler(std::initializer_list tag_list, std::shared_ptr> s) - { - std::bitset supported_tags; - for(auto tag : tag_list) - supported_tags.set(tag); - this->add_scheduler(supported_tags, s); - } - - void emplace_task(TTask& task) - { - if(auto sub_scheduler = get_matching_scheduler(task.required_scheduler_tags)) - return (*sub_scheduler)->emplace_task(task); - else - throw std::runtime_error("no scheduler found for task"); - } - - void activate_task(TTask& task) - { - if(auto sub_scheduler = get_matching_scheduler(task.required_scheduler_tags)) - return (*sub_scheduler)->activate_task(task); - else - throw std::runtime_error("no scheduler found for task"); - } - - std::optional>> get_matching_scheduler( - std::bitset const& required_tags) - { - for(auto const& s : sub_schedulers) - if((s.supported_tags & required_tags) == required_tags) - return s.s; - - return std::nullopt; - } - - bool task_dependency_type(TTask const& a, TTask& b) - { - /// fixme: b or a ? - if(auto sub_scheduler = get_matching_scheduler(b.required_scheduler_tags)) - return (*sub_scheduler)->task_dependency_type(a, b); - else - throw std::runtime_error("no scheduler found for task"); - } - - void wake_all() - { - for(auto const& s : sub_schedulers) - s.s->wake_all(); - } - - bool wake(WakerId waker_id) - { - for(auto const& s : sub_schedulers) - if(s.s->wake(waker_id)) - return true; - - return false; - } - }; - - /*! Factory function to easily create a tag-match-scheduler object - */ - template - struct TagMatchBuilder - { - std::shared_ptr> tag_match; - - operator std::shared_ptr>() const - { - return tag_match; - } - - TagMatchBuilder add(std::initializer_list tags, std::shared_ptr> s) - { - tag_match->add_scheduler(tags, s); - return *this; - } - }; - - template - auto make_tag_match_scheduler() - { - return TagMatchBuilder{std::make_shared>()}; - } - - - } // namespace scheduler - -} // namespace redGrapes diff --git a/redGrapes/scheduler/tag_match_property.hpp b/redGrapes/scheduler/tag_match_property.hpp deleted file mode 100644 index bff1ae11..00000000 --- a/redGrapes/scheduler/tag_match_property.hpp +++ /dev/null @@ -1,92 +0,0 @@ - -#pragma once - -#include - -#include -#include -#include - -namespace redGrapes -{ - namespace scheduler - { - template - struct SchedulingTagProperties - { - std::bitset required_scheduler_tags; - - template - struct Builder - { - PropertiesBuilder& builder; - - Builder(PropertiesBuilder& b) : builder(b) - { - } - - PropertiesBuilder& scheduling_tags(std::initializer_list tags) - { - std::bitset tags_bitset; - for(auto tag : tags) - tags_bitset.set(tag); - return scheduling_tags(tags_bitset); - } - - PropertiesBuilder& scheduling_tags(std::bitset tags) - { - builder.task->required_scheduler_tags |= tags; - return builder; - } - }; - - struct Patch - { - template - struct Builder - { - Builder(PatchBuilder&) - { - } - }; - }; - - void apply_patch(Patch const&) - { - } - }; - } // namespace scheduler -} // namespace redGrapes - -template -struct fmt::formatter> -{ - constexpr auto parse(format_parse_context& ctx) - { - return ctx.begin(); - } - - template - auto format(redGrapes::scheduler::SchedulingTagProperties const& prop, FormatContext& ctx) - { - auto out = ctx.out(); - - out = fmt::format_to(out, "\"schedulingTags\" : ["); - - bool first = true; - for(size_t i = 0; i < T_tag_count; ++i) - { - if(prop.required_scheduler_tags.test(i)) - { - if(!first) - out = format_to(out, ", "); - - first = false; - out = format_to(out, "{}", (Tag) i); - } - } - - out = fmt::format_to(out, "]"); - return out; - } -}; diff --git a/redGrapes/scheduler/thread_scheduler.hpp b/redGrapes/scheduler/thread_scheduler.hpp index 234b4f97..0aaa9e75 100644 --- a/redGrapes/scheduler/thread_scheduler.hpp +++ b/redGrapes/scheduler/thread_scheduler.hpp @@ -11,6 +11,7 @@ #include "redGrapes/dispatch/mpi/request_pool.hpp" #include "redGrapes/dispatch/thread/WorkerThread.hpp" #include "redGrapes/scheduler/scheduler.hpp" +#include "redGrapes/sync/cv.hpp" #include @@ -25,19 +26,21 @@ namespace redGrapes * Uses simple round-robin algorithm to distribute tasks to workers * and implements work-stealing */ - template - struct ThreadScheduler : public IScheduler + template + struct ThreadScheduler : public IScheduler { + using TTask = Worker::task_type; + WorkerId m_base_id; CondVar cv; - std::shared_ptr> m_worker_thread; + std::shared_ptr> m_worker_thread; static constexpr unsigned n_workers = 1; ThreadScheduler() { } - ThreadScheduler(std::shared_ptr> workerThread) + ThreadScheduler(std::shared_ptr> workerThread) : m_worker_thread(workerThread) { } @@ -120,7 +123,7 @@ namespace redGrapes memory::HwlocAlloc(TaskFreeCtx::hwloc_ctx, obj), REDGRAPES_ALLOC_CHUNKSIZE); - m_worker_thread = memory::alloc_shared_bind>( + m_worker_thread = memory::alloc_shared_bind>( m_base_id, TaskFreeCtx::worker_alloc_pool->get_alloc(m_base_id), TaskFreeCtx::hwloc_ctx, diff --git a/redGrapes/task/property/graph.hpp b/redGrapes/task/property/graph.hpp index 37f1ef0e..684d0606 100644 --- a/redGrapes/task/property/graph.hpp +++ b/redGrapes/task/property/graph.hpp @@ -197,3 +197,5 @@ struct fmt::formatter> return ctx.out(); } }; + +#include "redGrapes/task/property/graph.tpp" diff --git a/redGrapes/task/property/graph.tpp b/redGrapes/task/property/graph.tpp index 56534c93..07fae06c 100644 --- a/redGrapes/task/property/graph.tpp +++ b/redGrapes/task/property/graph.tpp @@ -61,7 +61,7 @@ namespace redGrapes if(preceding_task == space->parent) break; - if(preceding_task->space == space && space->is_serial(*preceding_task, *task)) + if(preceding_task->space == space && is_serial(*preceding_task, *task)) { add_dependency(*preceding_task); if(preceding_task->has_sync_access(r->resource)) @@ -120,7 +120,7 @@ namespace redGrapes scheduler::EventPtr follower = *it; if(follower.task) { - if(!space->is_serial(*task, *follower.task)) + if(!is_serial(*task, *follower.task)) { // remove dependency // follower.task->in_edges.erase(std::find(std::begin(follower.task->in_edges), diff --git a/redGrapes/task/property/id.hpp b/redGrapes/task/property/id.hpp index f24f5c19..d18c9ebe 100644 --- a/redGrapes/task/property/id.hpp +++ b/redGrapes/task/property/id.hpp @@ -91,6 +91,6 @@ struct fmt::formatter template auto format(redGrapes::IDProperty const& id_prop, FormatContext& ctx) { - return format_to(ctx.out(), "\"id\" : {}", id_prop.task_id); + return fmt::format_to(ctx.out(), "\"id\" : {}", id_prop.task_id); } }; diff --git a/redGrapes/task/property/label.hpp b/redGrapes/task/property/label.hpp index 366321bb..18465716 100644 --- a/redGrapes/task/property/label.hpp +++ b/redGrapes/task/property/label.hpp @@ -71,6 +71,6 @@ struct fmt::formatter template auto format(redGrapes::LabelProperty const& label_prop, FormatContext& ctx) { - return format_to(ctx.out(), "\"label\" : \"{}\"", label_prop.label); + return fmt::format_to(ctx.out(), "\"label\" : \"{}\"", label_prop.label); } }; diff --git a/redGrapes/task/property/resource.hpp b/redGrapes/task/property/resource.hpp index 46f96d78..f70c22c4 100644 --- a/redGrapes/task/property/resource.hpp +++ b/redGrapes/task/property/resource.hpp @@ -134,25 +134,6 @@ namespace redGrapes } }; - template - struct ResourcePrecedencePolicy - { - static bool is_serial(ResourceProperty const& a, ResourceProperty const& b) - { - return redGrapes::ResourceUser::is_serial(a, b); - } - - static void assert_superset(ResourceProperty const& super, ResourceProperty const& sub) - { - if(!redGrapes::ResourceUser::is_superset(super, sub)) - { - auto msg = fmt::format("Not allowed: {} is no superset of {}\n", super, sub); - spdlog::error(msg); - throw std::runtime_error(msg); - } - } - }; - } // namespace redGrapes template @@ -166,6 +147,6 @@ struct fmt::formatter> template auto format(redGrapes::ResourceProperty const& label_prop, FormatContext& ctx) { - return format_to(ctx.out(), "\"resources\" : {}", (redGrapes::ResourceUser const&) label_prop); + return fmt::format_to(ctx.out(), "\"resources\" : {}", (redGrapes::ResourceUser const&) label_prop); } }; diff --git a/redGrapes/task/task.hpp b/redGrapes/task/task.hpp index 57fe49c7..8a517598 100644 --- a/redGrapes/task/task.hpp +++ b/redGrapes/task/task.hpp @@ -18,7 +18,7 @@ namespace redGrapes { template - concept C_TaskProperty = requires(T taskProp, T::Patch patch) + concept C_TaskProperty = requires(T taskProp, typename T::Patch patch) { { taskProp.apply_patch(patch) diff --git a/redGrapes/task/task_space.hpp b/redGrapes/task/task_space.hpp index 054ff574..1a1c6fe5 100644 --- a/redGrapes/task/task_space.hpp +++ b/redGrapes/task/task_space.hpp @@ -9,7 +9,6 @@ #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/memory/block.hpp" -#include "redGrapes/resource/resource_user.hpp" #include "redGrapes/scheduler/scheduler.hpp" #include "redGrapes/util/trace.hpp" @@ -34,10 +33,6 @@ namespace redGrapes std::shared_mutex active_child_spaces_mutex; std::vector>> active_child_spaces; - virtual ~TaskSpace() - { - } - // top space TaskSpace() : depth(0), parent(nullptr) { @@ -51,16 +46,6 @@ namespace redGrapes task_count = 0; } - virtual bool is_serial(TTask& a, TTask& b) - { - return ResourceUser::is_serial(a, b); - } - - virtual bool is_superset(TTask& a, TTask& b) - { - return ResourceUser::is_superset(a, b); - } - // add a new task to the task-space void submit(TTask* task) { @@ -71,7 +56,7 @@ namespace redGrapes ++task_count; if(parent) - assert(this->is_superset(*parent, *task)); + assert(parent->is_superset_of(*task)); for(auto r = task->unique_resources.rbegin(); r != task->unique_resources.rend(); ++r) { diff --git a/redGrapes/util/atomic_list.hpp b/redGrapes/util/atomic_list.hpp index f3f1e2e3..92f22687 100644 --- a/redGrapes/util/atomic_list.hpp +++ b/redGrapes/util/atomic_list.hpp @@ -18,7 +18,6 @@ #include #include #include -#include namespace redGrapes { @@ -298,8 +297,7 @@ namespace redGrapes { old_head = std::atomic_load(&head); std::atomic_store(&new_head->prev, old_head); - append_successful - = std::atomic_compare_exchange_strong(&head, &old_head, new_head); + append_successful = std::atomic_compare_exchange_strong(&head, &old_head, new_head); } return MutBackwardIterator{old_head}; @@ -312,7 +310,7 @@ namespace redGrapes std::shared_ptr expected(nullptr); std::shared_ptr const& desired = new_head; - return std::atomic_compare_exchange_strong(&head, &expected, desired); + return std::atomic_compare_exchange_strong(&head, &expected, desired); } }; diff --git a/redGrapes/util/trace.hpp b/redGrapes/util/trace.hpp index e55b1b1a..b78133bd 100644 --- a/redGrapes/util/trace.hpp +++ b/redGrapes/util/trace.hpp @@ -44,3 +44,5 @@ void StopTracing(std::shared_ptr tracing_session); # define TRACE_EVENT_END #endif + +#include diff --git a/redGrapes/version.hpp b/redGrapes/version.hpp index bfc4a3a0..0e72c2c5 100644 --- a/redGrapes/version.hpp +++ b/redGrapes/version.hpp @@ -8,6 +8,6 @@ #pragma once #define REDGRAPES_VERSION_MAJOR 0 -#define REDGRAPES_VERSION_MINOR 1 +#define REDGRAPES_VERSION_MINOR 2 #define REDGRAPES_VERSION_PATCH 0 #define REDGRAPES_VERSION_LABEL "" diff --git a/test/random_graph.cpp b/test/random_graph.cpp index 27d3fd2e..d4fa6b10 100644 --- a/test/random_graph.cpp +++ b/test/random_graph.cpp @@ -111,7 +111,7 @@ TEST_CASE("RandomGraph") switch(access_pattern[i].size()) { case 0: - rg.emplace_task([i]() { sleep(task_duration); }); + rg.emplace_task([]() { sleep(task_duration); }); break; case 1: diff --git a/test/resource_user.cpp b/test/resource_user.cpp index 1454f2e6..1dea168a 100644 --- a/test/resource_user.cpp +++ b/test/resource_user.cpp @@ -18,35 +18,35 @@ TEST_CASE("Resource User") redGrapes::ResourceUser f4({b.read(), b.write()}); redGrapes::ResourceUser f5({a.read(), a.write(), b.read(), b.write()}); - REQUIRE(redGrapes::ResourceUser::is_serial(f1, f1) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f1, f2) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f1, f3) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f1, f4) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f1, f5) == true); - - REQUIRE(redGrapes::ResourceUser::is_serial(f2, f1) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f2, f2) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f2, f3) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f2, f4) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f2, f5) == true); - - REQUIRE(redGrapes::ResourceUser::is_serial(f3, f1) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f3, f2) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f3, f3) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f3, f4) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f3, f5) == true); - - REQUIRE(redGrapes::ResourceUser::is_serial(f4, f1) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f4, f2) == false); - REQUIRE(redGrapes::ResourceUser::is_serial(f4, f3) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f4, f4) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f4, f5) == true); - - REQUIRE(redGrapes::ResourceUser::is_serial(f5, f1) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f5, f2) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f5, f3) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f5, f4) == true); - REQUIRE(redGrapes::ResourceUser::is_serial(f5, f5) == true); + REQUIRE(redGrapes::is_serial(f1, f1) == false); + REQUIRE(redGrapes::is_serial(f1, f2) == true); + REQUIRE(redGrapes::is_serial(f1, f3) == false); + REQUIRE(redGrapes::is_serial(f1, f4) == false); + REQUIRE(redGrapes::is_serial(f1, f5) == true); + + REQUIRE(redGrapes::is_serial(f2, f1) == true); + REQUIRE(redGrapes::is_serial(f2, f2) == true); + REQUIRE(redGrapes::is_serial(f2, f3) == false); + REQUIRE(redGrapes::is_serial(f2, f4) == false); + REQUIRE(redGrapes::is_serial(f2, f5) == true); + + REQUIRE(redGrapes::is_serial(f3, f1) == false); + REQUIRE(redGrapes::is_serial(f3, f2) == false); + REQUIRE(redGrapes::is_serial(f3, f3) == false); + REQUIRE(redGrapes::is_serial(f3, f4) == true); + REQUIRE(redGrapes::is_serial(f3, f5) == true); + + REQUIRE(redGrapes::is_serial(f4, f1) == false); + REQUIRE(redGrapes::is_serial(f4, f2) == false); + REQUIRE(redGrapes::is_serial(f4, f3) == true); + REQUIRE(redGrapes::is_serial(f4, f4) == true); + REQUIRE(redGrapes::is_serial(f4, f5) == true); + + REQUIRE(redGrapes::is_serial(f5, f1) == true); + REQUIRE(redGrapes::is_serial(f5, f2) == true); + REQUIRE(redGrapes::is_serial(f5, f3) == true); + REQUIRE(redGrapes::is_serial(f5, f4) == true); + REQUIRE(redGrapes::is_serial(f5, f5) == true); REQUIRE(f1.is_superset_of(f1) == true);