diff --git a/examples/1_resources.cpp b/examples/1_resources.cpp index b7527f54..a7a79f89 100644 --- a/examples/1_resources.cpp +++ b/examples/1_resources.cpp @@ -12,21 +12,21 @@ int main(int, char*[]) { auto rg = redGrapes::init(1); - using TTask = decltype(rg)::RGTask; auto a = rg.createFieldResource>(); auto b = rg.createIOResource(); auto c = rg.createIOResource(); - redGrapes::ResourceUser user1( + redGrapes::ResourceUser user1( {a.read(), // complete resource a.write().area({0}, {10}), // write only indices 0 to 10 b.write()}, + 0, 0); - redGrapes::ResourceUser user2({b.read()}, 0); + redGrapes::ResourceUser user2({b.read()}, 0, 0); - redGrapes::ResourceUser user3({b.read(), c.write()}, 0); + redGrapes::ResourceUser user3({b.read(), c.write()}, 0, 0); std::cout << "is_serial(user1,user1) = " << is_serial(user1, user1) << std::endl; std::cout << "is_serial(user1,user2) = " << is_serial(user1, user2) << std::endl; diff --git a/examples/cholesky.cpp b/examples/cholesky.cpp index 0b20402f..216237a5 100644 --- a/examples/cholesky.cpp +++ b/examples/cholesky.cpp @@ -13,8 +13,7 @@ #include -template -void print_matrix(std::vector> A, int nblks, int blocksize) +void print_matrix(std::vector> A, int nblks, int blocksize) { for(int ia = 0; ia < nblks; ++ia) { @@ -71,7 +70,7 @@ int main(int argc, char* argv[]) Alin[i * N + i] += N; // initialize tiled matrix in column-major layout - std::vector> A(nblks * nblks); + std::vector> A(nblks * nblks); // allocate each tile (also in column-major layout) for(size_t j = 0; j < nblks; ++j) diff --git a/examples/cuda_mandelbrot.cu b/examples/cuda_mandelbrot.cu index fbd7bd6a..38b94668 100644 --- a/examples/cuda_mandelbrot.cu +++ b/examples/cuda_mandelbrot.cu @@ -93,8 +93,8 @@ int main() size_t height = 4096; size_t area = width * height; - redGrapes::IOResource host_buffer; - redGrapes::IOResource device_buffer; + redGrapes::IOResource host_buffer; + redGrapes::IOResource device_buffer; rg.emplace_task( [area](auto host_buffer) diff --git a/examples/game_of_life.cpp b/examples/game_of_life.cpp index afb85ee2..1c5d29ba 100644 --- a/examples/game_of_life.cpp +++ b/examples/game_of_life.cpp @@ -53,8 +53,7 @@ int main(int, char*[]) using Buffer = std::array, size.y + 2>; - using TaskType = decltype(rg)::RGTask; - std::vector> buffers; + std::vector> buffers; for(size_t i = 0; i < 4; ++i) buffers.emplace_back(); diff --git a/examples/mpi.cpp b/examples/mpi.cpp index eb075bc9..d3afcd05 100644 --- a/examples/mpi.cpp +++ b/examples/mpi.cpp @@ -93,7 +93,7 @@ int main() }); // initialize MPI config - redGrapes::IOResource mpi_config; + redGrapes::IOResource mpi_config; rg.emplace_task( [](auto config) { @@ -103,9 +103,9 @@ int main() mpi_config.write()); // main loop - std::array, RGTask>, 2> field = { - redGrapes::FieldResource, RGTask>(), - redGrapes::FieldResource, RGTask>(), + std::array>, 2> field = { + redGrapes::FieldResource>(), + redGrapes::FieldResource>(), }; int current = 0; diff --git a/redGrapes/TaskCtx.hpp b/redGrapes/TaskCtx.hpp deleted file mode 100644 index 7b6bafd4..00000000 --- a/redGrapes/TaskCtx.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright 2024 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/TaskFreeCtx.hpp" -#include "redGrapes/scheduler/event.hpp" -#include "redGrapes/task/task_space.hpp" - -#include - -#include - -namespace redGrapes -{ - template - struct TaskCtx - { - //! pause the currently running task at least until event is reached - // else is supposed to be called when .get()/.submit() is called on emplace task, which calls the future - // .get(), - // if there is no current task at that time (not in a child task space) in the root space,wake up the parser - // thread - // we can assert(event.task != 0); - static void yield(scheduler::EventPtr event) - { - if(current_task) - { - while(!event->is_reached()) - current_task->yield(event); - } - else - { - event->waker_id = parserID; - while(!event->is_reached()) - TaskFreeCtx::idle(); - } - } - - /*! Create an event on which the termination of the current task depends. - * A task must currently be running. - * - * @return Handle to flag the event with `reach_event` later. - * nullopt if there is no task running currently - */ - static std::optional> create_event() - { - if(current_task) - return current_task->make_event(); - else - return std::nullopt; - } - - static std::shared_ptr> current_task_space() - { - if(current_task) - { - if(!current_task->children) - { - auto task_space = std::make_shared>(current_task); - SPDLOG_TRACE("create child space = {}", (void*) task_space.get()); - current_task->children = task_space; - } - - return current_task->children; - } - else - return root_space; - } - - static unsigned scope_depth() - { - if(auto ts = current_task_space()) - return ts->depth; - else - return 0; - } - - static inline thread_local TTask* current_task; - static inline std::shared_ptr> root_space; - }; - -} // namespace redGrapes diff --git a/redGrapes/dispatch/cuda/cuda_worker.hpp b/redGrapes/dispatch/cuda/cuda_worker.hpp index 5677a5a7..2cbb8fad 100644 --- a/redGrapes/dispatch/cuda/cuda_worker.hpp +++ b/redGrapes/dispatch/cuda/cuda_worker.hpp @@ -7,9 +7,9 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/dispatch/cuda/cuda_task_properties.hpp" #include "redGrapes/dispatch/cuda/event_pool.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/scheduler/event.hpp" #include "redGrapes/sync/cv.hpp" #include "redGrapes/task/queue.hpp" @@ -108,7 +108,7 @@ namespace redGrapes::dispatch::cuda assert(task.is_ready()); std::lock_guard lock(mutex); - TaskCtx::current_task = &task; + current_task = &task; // run the code that calls the CUDA API and submits work to *task->m_cuda_stream_idx auto event = task(); @@ -116,7 +116,7 @@ namespace redGrapes::dispatch::cuda cudaEvent_t cuda_event = event_pool.alloc(); // works even if the m_cuda_stream index optional is nullopt, because it gets casted to 0 cudaEventRecord(cuda_event, streams[*(task->m_cuda_stream_idx)].cuda_stream); - auto my_event = TaskCtx::create_event(); + auto my_event = create_event_impl(); events.push(std::make_pair(cuda_event, *my_event)); SPDLOG_TRACE( "CudaStreamDispatcher {}: recorded event {}", @@ -137,7 +137,7 @@ namespace redGrapes::dispatch::cuda else task.get_post_event().notify(); - TaskCtx::current_task = nullptr; + current_task = nullptr; } /* repeatedly try to find and execute tasks diff --git a/redGrapes/dispatch/mpi/mpiWorker.hpp b/redGrapes/dispatch/mpi/mpiWorker.hpp index c10f24b7..a6bc4ffe 100644 --- a/redGrapes/dispatch/mpi/mpiWorker.hpp +++ b/redGrapes/dispatch/mpi/mpiWorker.hpp @@ -8,6 +8,7 @@ #pragma once #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/dispatch/mpi/request_pool.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/sync/cv.hpp" #include "redGrapes/task/queue.hpp" @@ -75,7 +76,7 @@ namespace redGrapes assert(task.is_ready()); task.get_pre_event().notify(); - TaskCtx::current_task = &task; + current_task = &task; auto event = task(); @@ -90,7 +91,7 @@ namespace redGrapes else task.get_post_event().notify(); - TaskCtx::current_task = nullptr; + current_task = nullptr; } /* find a task that shall be executed next diff --git a/redGrapes/dispatch/mpi/request_pool.hpp b/redGrapes/dispatch/mpi/request_pool.hpp index 552a69e2..6533aa65 100644 --- a/redGrapes/dispatch/mpi/request_pool.hpp +++ b/redGrapes/dispatch/mpi/request_pool.hpp @@ -7,7 +7,7 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/scheduler/event.hpp" #include @@ -83,8 +83,8 @@ namespace redGrapes */ MPI_Status get_status(MPI_Request request) { - auto status = memory::alloc_shared_bind((*TaskCtx::current_task)->worker_id); - auto event = *TaskCtx::create_event(); + auto status = memory::alloc_shared_bind(static_cast(current_task)->worker_id); + auto event = *create_event_impl(); // SPDLOG_TRACE("MPI RequestPool: status event = {}", (void*)event.get()); @@ -95,7 +95,7 @@ namespace redGrapes statuses.push_back(status); } - TaskCtx::yield(event); + yield_impl(event); return *status; } diff --git a/redGrapes/dispatch/thread/DefaultWorker.tpp b/redGrapes/dispatch/thread/DefaultWorker.tpp index 48dbc57a..f3593666 100644 --- a/redGrapes/dispatch/thread/DefaultWorker.tpp +++ b/redGrapes/dispatch/thread/DefaultWorker.tpp @@ -6,9 +6,9 @@ */ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/dispatch/thread/DefaultWorker.hpp" #include "redGrapes/dispatch/thread/worker_pool.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/util/bitfield.hpp" #include "redGrapes/util/trace.hpp" @@ -58,7 +58,7 @@ namespace redGrapes assert(task.is_ready()); task.get_pre_event().notify(); - TaskCtx::current_task = &task; + current_task = &task; auto event = task(); @@ -73,7 +73,7 @@ namespace redGrapes else task.get_post_event().notify(); - TaskCtx::current_task = nullptr; + current_task = nullptr; } template diff --git a/redGrapes/dispatch/thread/WorkerThread.hpp b/redGrapes/dispatch/thread/WorkerThread.hpp index 5747cc02..41ce1df2 100644 --- a/redGrapes/dispatch/thread/WorkerThread.hpp +++ b/redGrapes/dispatch/thread/WorkerThread.hpp @@ -10,7 +10,6 @@ #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/memory/hwloc_alloc.hpp" -#include #include #include @@ -26,7 +25,8 @@ namespace redGrapes::dispatch::thread Worker worker; template - WorkerThread(hwloc_obj_t const obj, Args&&... args) : obj{obj}, worker{std::forward(args)...} + WorkerThread(hwloc_obj_t const obj, Args&&... args) : obj{obj} + , worker{std::forward(args)...} { } diff --git a/redGrapes/globalSpace.hpp b/redGrapes/globalSpace.hpp new file mode 100644 index 00000000..76fd2804 --- /dev/null +++ b/redGrapes/globalSpace.hpp @@ -0,0 +1,87 @@ +/* Copyright 2024 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/TaskFreeCtx.hpp" +#include "redGrapes/resource/resource_user.hpp" +#include "redGrapes/scheduler/event.hpp" +#include "redGrapes/task/task_space.hpp" + +#include + +#include + +namespace redGrapes +{ + + // not a Task because Task type is a template, so we static cast current_task to Task type everywhere + inline thread_local ResourceUser* current_task; + + inline std::shared_ptr root_space; + + inline std::shared_ptr current_task_space() + { + if(current_task) + { + if(!current_task->children) + { + auto task_space = std::make_shared(current_task); + SPDLOG_TRACE("create child space = {}", (void*) task_space.get()); + current_task->children = task_space; + } + + return current_task->children; + } + else + return root_space; + } + + inline unsigned scope_depth_impl() + { + if(auto ts = current_task_space()) + return ts->depth; + else + return 0; + } + + //! pause the currently running task at least until event is reached + // else is supposed to be called when .get()/.submit() is called on emplace task, which calls the future + // .get(), + // if there is no current task at that time (not in a child task space) in the root space,wake up the parser + // thread + // we can assert(event.task != 0); + template + void yield_impl(scheduler::EventPtr event) + { + if(current_task) + { + while(!event->is_reached()) + static_cast(current_task)->yield(event); + } + else + { + event->waker_id = parserID; + while(!event->is_reached()) + TaskFreeCtx::idle(); + } + } + + /*! Create an event on which the termination of the current task depends. + * A task must currently be running. + * + * @return Handle to flag the event with `reach_event` later. + * nullopt if there is no task running currently + */ + template + std::optional> create_event_impl() + { + if(current_task) + return static_cast(current_task)->make_event(); + else + return std::nullopt; + } + +} // namespace redGrapes diff --git a/redGrapes/redGrapes.hpp b/redGrapes/redGrapes.hpp index 5db0c40b..ae287a29 100644 --- a/redGrapes/redGrapes.hpp +++ b/redGrapes/redGrapes.hpp @@ -8,9 +8,8 @@ #pragma once #include "redGrapes/SchedulerDescription.hpp" -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/TaskFreeCtx.hpp" -#include "redGrapes/memory/hwloc_alloc.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/resource/fieldresource.hpp" #include "redGrapes/resource/ioresource.hpp" #include "redGrapes/scheduler/event.hpp" @@ -56,7 +55,7 @@ namespace redGrapes TaskFreeCtx::worker_alloc_pool.allocs.reserve(TaskFreeCtx::n_workers); - TaskCtx::root_space = std::make_shared>(); + root_space = std::make_shared(); auto initAdd = [](auto scheduler, auto& base_worker_id) { @@ -80,7 +79,7 @@ namespace redGrapes [&](auto pair) { scheduler_map[boost::mp11::mp_first{}]->stopExecution(); }); boost::mp11::mp_for_each([&](auto pair) { scheduler_map[boost::mp11::mp_first{}].reset(); }); - TaskCtx::root_space.reset(); + root_space.reset(); finalize_tracing(); } @@ -95,7 +94,7 @@ namespace redGrapes // TODO make this generic template void yield(scheduler::EventPtr event) { - TaskCtx::yield(event); + yield_impl(event); } //! apply a patch to the properties of the currently running task @@ -113,17 +112,12 @@ namespace redGrapes */ std::optional> create_event() { - return TaskCtx::create_event(); + return create_event_impl(); } unsigned scope_depth() const { - return TaskCtx::scope_depth(); - } - - std::shared_ptr> current_task_space() const - { - return TaskCtx::current_task_space(); + return scope_depth_impl(); } /*! create a new task, as child of the currently running task (if there is one) @@ -157,9 +151,13 @@ namespace redGrapes throw std::bad_alloc(); // construct task in-place - new(task) FunTask(worker_id, *scheduler_map[TSchedTag{}]); + new(task) FunTask(worker_id, scope_depth_impl(), *scheduler_map[TSchedTag{}]); - return TaskBuilder(task, std::forward(f), std::forward(args)...); + return TaskBuilder( + task, + current_task_space(), + std::forward(f), + std::forward(args)...); } template @@ -180,37 +178,38 @@ namespace redGrapes } template - auto createFieldResource(Container* c) -> FieldResource + auto createFieldResource(Container* c) -> FieldResource { - return FieldResource(c); + return FieldResource(c); } template - auto createFieldResource(Args&&... args) -> FieldResource + auto createFieldResource(Args&&... args) -> FieldResource { - return FieldResource(std::forward(args)...); + return FieldResource(std::forward(args)...); } template - auto createIOResource(std::shared_ptr o) -> IOResource + auto createIOResource(std::shared_ptr o) -> IOResource { - return IOResource(o); + return IOResource(o); } template - auto createIOResource(Args&&... args) -> IOResource + auto createIOResource(Args&&... args) -> IOResource { - return IOResource(std::forward(args)...); + return IOResource(std::forward(args)...); } template - auto createResource() -> Resource + auto createResource() -> Resource { - return Resource(TaskFreeCtx::create_resource_uid()); + return Resource(TaskFreeCtx::create_resource_uid()); } private: MapTuple scheduler_map; + #if REDGRAPES_ENABLE_TRACE std::shared_ptr tracing_session; #endif diff --git a/redGrapes/redGrapes.tpp b/redGrapes/redGrapes.tpp index 039ead88..ced4361e 100644 --- a/redGrapes/redGrapes.tpp +++ b/redGrapes/redGrapes.tpp @@ -7,8 +7,8 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/TaskFreeCtx.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/redGrapes.hpp" #include "redGrapes/util/trace.hpp" @@ -29,7 +29,8 @@ namespace redGrapes backtrace() const { std::vector> bt; - for(RGTask* task = TaskCtx::current_task; task != nullptr; task = task->space->parent) + for(auto task = static_cast(current_task); task != nullptr; + task = static_cast(task->space->parent)) bt.push_back(*task); return bt; @@ -63,7 +64,7 @@ namespace redGrapes { SPDLOG_TRACE("barrier"); - while(!TaskCtx::root_space->empty()) + while(!root_space->empty()) TaskFreeCtx::idle(); } @@ -72,10 +73,10 @@ namespace redGrapes void RedGrapes::update_properties( typename Task::TaskProperties::Patch const& patch) { - if(TaskCtx::current_task) + if(current_task) { - TaskCtx::current_task->apply_patch(patch); - TaskCtx::current_task->update_graph(); + static_cast(current_task)->apply_patch(patch); + static_cast(current_task)->update_graph(); } else throw std::runtime_error("update_properties: currently no task running"); diff --git a/redGrapes/resource/fieldresource.hpp b/redGrapes/resource/fieldresource.hpp index 2356f4fb..692c7ef1 100644 --- a/redGrapes/resource/fieldresource.hpp +++ b/redGrapes/resource/fieldresource.hpp @@ -73,8 +73,8 @@ namespace redGrapes namespace fieldresource { - template - struct AreaGuard : SharedResourceObject::dim>> + template + struct AreaGuard : SharedResourceObject::dim>> { static constexpr size_t dim = trait::Field::dim; using Item = typename trait::Field::Item; @@ -92,31 +92,31 @@ namespace redGrapes protected: AreaGuard(ResourceId id, std::shared_ptr const& obj) - : SharedResourceObject>(id, obj) + : SharedResourceObject>(id, obj) { } template AreaGuard(ResourceId id, Args&&... args) - : SharedResourceObject>(id, std::forward(args)...) + : SharedResourceObject>(id, std::forward(args)...) { } AreaGuard( - Resource::dim>> const& res, + Resource::dim>> const& res, std::shared_ptr const& obj) - : SharedResourceObject>(res, obj) + : SharedResourceObject>(res, obj) { } template - AreaGuard(Resource::dim>> const& res, Args&&... args) - : SharedResourceObject>(res, std::forward(args)...) + AreaGuard(Resource::dim>> const& res, Args&&... args) + : SharedResourceObject>(res, std::forward(args)...) { } AreaGuard(AreaGuard const& other, Index begin, Index end) - : SharedResourceObject>(other) + : SharedResourceObject>(other) , m_area(other.make_area(begin, end)) { } @@ -144,12 +144,12 @@ namespace redGrapes access::ArrayAccess m_area; }; - template - struct ReadGuard : AreaGuard + template + struct ReadGuard : AreaGuard { static constexpr size_t dim = trait::Field::dim; - using typename AreaGuard::Index; - using typename AreaGuard::Item; + using typename AreaGuard::Index; + using typename AreaGuard::Item; ReadGuard read() const noexcept { @@ -179,45 +179,45 @@ namespace redGrapes return this->obj.get(); } - operator ResourceAccess() const noexcept + operator ResourceAccess() const noexcept { return this->make_access(access::FieldAccess(access::IOAccess::read, this->m_area)); } protected: - ReadGuard(ReadGuard const& other, Index begin, Index end) : AreaGuard(other, begin, end) + ReadGuard(ReadGuard const& other, Index begin, Index end) : AreaGuard(other, begin, end) { } - ReadGuard(ResourceId id, std::shared_ptr const& obj) : AreaGuard(id, obj) + ReadGuard(ResourceId id, std::shared_ptr const& obj) : AreaGuard(id, obj) { } template - ReadGuard(ResourceId id, Args&&... args) : AreaGuard(id, std::forward(args)...) + ReadGuard(ResourceId id, Args&&... args) : AreaGuard(id, std::forward(args)...) { } ReadGuard( - Resource::dim>> const& res, + Resource::dim>> const& res, std::shared_ptr const& obj) - : AreaGuard(res, obj) + : AreaGuard(res, obj) { } template - ReadGuard(Resource::dim>> const& res, Args&&... args) - : AreaGuard(res, std::forward(args)...) + ReadGuard(Resource::dim>> const& res, Args&&... args) + : AreaGuard(res, std::forward(args)...) { } }; - template - struct WriteGuard : ReadGuard + template + struct WriteGuard : ReadGuard { static constexpr size_t dim = trait::Field::dim; - using typename ReadGuard::Index; - using typename ReadGuard::Item; + using typename ReadGuard::Index; + using typename ReadGuard::Item; WriteGuard write() const noexcept { @@ -247,51 +247,48 @@ namespace redGrapes return this->obj.get(); } - operator ResourceAccess() const noexcept + operator ResourceAccess() const noexcept { return this->make_access(access::FieldAccess(access::IOAccess::write, this->m_area)); } protected: - WriteGuard(WriteGuard const& other, Index begin, Index end) - : ReadGuard(other, begin, end) + WriteGuard(WriteGuard const& other, Index begin, Index end) : ReadGuard(other, begin, end) { } - WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) + WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) { } template - WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) + WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) { } WriteGuard( - Resource::dim>> const& res, + Resource::dim>> const& res, std::shared_ptr const& obj) - : ReadGuard(res, obj) + : ReadGuard(res, obj) { } template - WriteGuard(Resource::dim>> const& res, Args&&... args) - : ReadGuard(res, std::forward(args)...) + WriteGuard(Resource::dim>> const& res, Args&&... args) + : ReadGuard(res, std::forward(args)...) { } }; } // namespace fieldresource - template - struct FieldResource : fieldresource::WriteGuard + template + struct FieldResource : fieldresource::WriteGuard { static constexpr size_t dim = trait::Field::dim; FieldResource(Container* c) - : fieldresource::WriteGuard( - TaskFreeCtx::create_resource_uid(), - std::shared_ptr(c)) + : fieldresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::shared_ptr(c)) { } @@ -301,21 +298,19 @@ namespace redGrapes || std::is_same_v>, Container*>) ) FieldResource(Args&&... args) - : fieldresource::WriteGuard( - TaskFreeCtx::create_resource_uid(), - std::forward(args)...) + : fieldresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::forward(args)...) { } template - FieldResource(FieldResource const& res, Container* c) - : fieldresource::WriteGuard(res, std::shared_ptr(c)) + FieldResource(FieldResource const& res, Container* c) + : fieldresource::WriteGuard(res, std::shared_ptr(c)) { } template - FieldResource(FieldResource const& res, Args&&... args) - : fieldresource::WriteGuard(res, std::forward(args)...) + FieldResource(FieldResource const& res, Args&&... args) + : fieldresource::WriteGuard(res, std::forward(args)...) { } }; diff --git a/redGrapes/resource/ioresource.hpp b/redGrapes/resource/ioresource.hpp index b40f888e..4b883b18 100644 --- a/redGrapes/resource/ioresource.hpp +++ b/redGrapes/resource/ioresource.hpp @@ -25,10 +25,10 @@ namespace redGrapes namespace ioresource { - template - struct ReadGuard : public SharedResourceObject + template + struct ReadGuard : public SharedResourceObject { - operator ResourceAccess() const noexcept + operator ResourceAccess() const noexcept { return this->make_access(access::IOAccess::read); } @@ -55,32 +55,32 @@ namespace redGrapes protected: ReadGuard(ResourceId id, std::shared_ptr const& obj) - : SharedResourceObject(id, obj) + : SharedResourceObject(id, obj) { } template ReadGuard(ResourceId id, Args&&... args) - : SharedResourceObject(id, std::forward(args)...) + : SharedResourceObject(id, std::forward(args)...) { } - ReadGuard(Resource const& res, std::shared_ptr const& obj) - : SharedResourceObject(res, obj) + ReadGuard(Resource< access::IOAccess> const& res, std::shared_ptr const& obj) + : SharedResourceObject(res, obj) { } template - ReadGuard(Resource const& res, Args&&... args) - : SharedResourceObject(res, std::forward(args)...) + ReadGuard(Resource< access::IOAccess> const& res, Args&&... args) + : SharedResourceObject(res, std::forward(args)...) { } }; - template - struct WriteGuard : public ReadGuard + template + struct WriteGuard : public ReadGuard { - operator ResourceAccess() const noexcept + operator ResourceAccess() const noexcept { return this->make_access(access::IOAccess::write); } @@ -106,34 +106,34 @@ namespace redGrapes } protected: - WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) + WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) { } template - WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) + WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) { } - WriteGuard(Resource const& res, std::shared_ptr const& obj) - : ReadGuard(res, obj) + WriteGuard(Resource< access::IOAccess> const& res, std::shared_ptr const& obj) + : ReadGuard(res, obj) { } template - WriteGuard(Resource const& res, Args&&... args) - : ReadGuard(res, std::forward(args)...) + WriteGuard(Resource< access::IOAccess> const& res, Args&&... args) + : ReadGuard(res, std::forward(args)...) { } }; } // namespace ioresource - template - struct IOResource : public ioresource::WriteGuard + template + struct IOResource : public ioresource::WriteGuard { IOResource(std::shared_ptr const& o) - : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), o) + : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), o) { } @@ -142,19 +142,19 @@ namespace redGrapes !(traits::is_specialization_of>, IOResource>::value || std::is_same_v>, std::shared_ptr>) ) IOResource(Args&&... args) - : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::forward(args)...) + : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::forward(args)...) { } template - IOResource(IOResource const& res, std::shared_ptr const& obj) - : ioresource::WriteGuard(res, obj) + IOResource(IOResource const& res, std::shared_ptr const& obj) + : ioresource::WriteGuard(res, obj) { } template - IOResource(IOResource const& res, Args&&... args) - : ioresource::WriteGuard(res, std::forward(args)...) + IOResource(IOResource const& res, Args&&... args) + : ioresource::WriteGuard(res, std::forward(args)...) { } diff --git a/redGrapes/resource/resource.hpp b/redGrapes/resource/resource.hpp index f4a4934f..30f3d5c3 100644 --- a/redGrapes/resource/resource.hpp +++ b/redGrapes/resource/resource.hpp @@ -11,7 +11,6 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/memory/allocator.hpp" #include "redGrapes/sync/spinlock.hpp" @@ -34,6 +33,9 @@ namespace redGrapes { + struct ResourceUser; + unsigned scope_depth_impl(); + namespace mapping { template @@ -59,14 +61,13 @@ namespace redGrapes } // namespace mapping - template + template class Resource; - template class ResourceBase { public: - ChunkedList users; + ChunkedList users; SpinLock users_mutex; ResourceId id; uint8_t scope_level; @@ -77,22 +78,21 @@ namespace redGrapes ResourceBase(ResourceId id) : users(memory::Allocator(mapping::map_resource_to_worker(id))) , id(id) - , scope_level(TaskCtx::scope_depth()) + , scope_level(scope_depth_impl()) { } }; - template class ResourceAccess { // https://stackoverflow.com/questions/16567212/why-does-the-standard-prohibit-friend-declarations-of-partial-specializations - template + template friend class Resource; private: struct AccessBase { - AccessBase(boost::typeindex::type_index access_type, std::shared_ptr> resource) + AccessBase(boost::typeindex::type_index access_type, std::shared_ptr resource) : access_type(access_type) , resource(resource) { @@ -105,7 +105,7 @@ namespace redGrapes virtual ~AccessBase(){}; virtual bool operator==(AccessBase const& r) const = 0; - bool is_same_resource(ResourceAccess::AccessBase const& a) const + bool is_same_resource(ResourceAccess::AccessBase const& a) const { return this->resource == a.resource; } @@ -116,7 +116,7 @@ namespace redGrapes virtual std::string mode_format() const = 0; boost::typeindex::type_index access_type; - std::shared_ptr> resource; + std::shared_ptr resource; }; // AccessBase // todo use allocator!! @@ -127,22 +127,22 @@ namespace redGrapes { } - ResourceAccess(ResourceAccess const& other) : obj(other.obj) + ResourceAccess(ResourceAccess const& other) : obj(other.obj) { } - ResourceAccess(ResourceAccess&& other) : obj(std::move(other.obj)) + ResourceAccess(ResourceAccess&& other) : obj(std::move(other.obj)) { other.obj.reset(); } - ResourceAccess& operator=(ResourceAccess const& other) + ResourceAccess& operator=(ResourceAccess const& other) { this->obj = other.obj; return *this; } - static bool is_serial(ResourceAccess const& a, ResourceAccess const& b) + static bool is_serial(ResourceAccess const& a, ResourceAccess const& b) { if(a.obj->access_type == b.obj->access_type) return a.obj->is_serial(*b.obj); @@ -150,7 +150,7 @@ namespace redGrapes return false; } - bool is_superset_of(ResourceAccess const& a) const + bool is_superset_of(ResourceAccess const& a) const { // if ( this->obj->resource.scope_level < a.obj->resource.scope_level ) // return true; @@ -180,7 +180,7 @@ namespace redGrapes return this->obj->mode_format(); } - std::shared_ptr> get_resource() + std::shared_ptr get_resource() { return obj->resource; } @@ -191,14 +191,14 @@ namespace redGrapes * @param a another ResourceAccess * @return true if `a` is associated with the same resource as `this` */ - bool is_same_resource(ResourceAccess const& a) const + bool is_same_resource(ResourceAccess const& a) const { if(this->obj->access_type == a.obj->access_type) return this->obj->is_same_resource(*a.obj); return false; } - bool operator==(ResourceAccess const& a) const + bool operator==(ResourceAccess const& a) const { if(this->obj->access_type == a.obj->access_type) return *(this->obj) == *(a.obj); @@ -214,10 +214,7 @@ namespace redGrapes * can be casted to a ResourceAccess */ template - struct BuildProperties< - T, - TTask, - typename std::enable_if>::value>::type> + struct BuildProperties::value>::type> { template static inline void build(Builder& builder, T const& obj) @@ -265,21 +262,21 @@ namespace redGrapes * Represents a concrete resource. * Copied objects represent the same resource. */ - template + template class Resource { protected: - struct Access : public ResourceAccess::AccessBase + struct Access : public ResourceAccess::AccessBase { - Access(std::shared_ptr> resource, AccessPolicy policy) - : ResourceAccess::AccessBase(boost::typeindex::type_id(), resource) + Access(std::shared_ptr resource, AccessPolicy policy) + : ResourceAccess::AccessBase(boost::typeindex::type_id(), resource) , policy(policy) { } Access(Access&& other) - : ResourceAccess::AccessBase( - std::move(std::forward::AccessBase>(other))) // TODO check this + : ResourceAccess::AccessBase( + std::move(std::forward(other))) // TODO check this , policy(std::move(other.policy)) { } @@ -288,26 +285,26 @@ namespace redGrapes { } - bool is_synchronizing() const + bool is_synchronizing() const override { return policy.is_synchronizing(); } - bool is_serial(typename ResourceAccess::AccessBase const& a_) const + bool is_serial(typename ResourceAccess::AccessBase const& a_) const override { Access const& a = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess return this->is_same_resource(a) && AccessPolicy::is_serial(this->policy, a.policy); } - bool is_superset_of(typename ResourceAccess::AccessBase const& a_) const + bool is_superset_of(typename ResourceAccess::AccessBase const& a_) const override { Access const& a = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess return this->is_same_resource(a) && this->policy.is_superset_of(a.policy); } - bool operator==(typename ResourceAccess::AccessBase const& a_) const + bool operator==(typename ResourceAccess::AccessBase const& a_) const override { Access const& a = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess @@ -323,11 +320,11 @@ namespace redGrapes AccessPolicy policy; }; // struct ThisResourceAccess - std::shared_ptr> base; + std::shared_ptr base; public: Resource(ResourceId id) - : base{redGrapes::memory::alloc_shared_bind>(mapping::map_resource_to_worker(id), id)} + : base{redGrapes::memory::alloc_shared_bind(mapping::map_resource_to_worker(id), id)} { } @@ -339,11 +336,11 @@ namespace redGrapes * @param pol AccessPolicy object, containing all access information * @return ResourceAccess on this resource */ - ResourceAccess make_access(AccessPolicy pol) const + ResourceAccess make_access(AccessPolicy pol) const { auto a = redGrapes::memory::alloc_shared_bind(mapping::map_resource_to_worker(base->id), base, pol); - return ResourceAccess(a); + return ResourceAccess(a); } ResourceId resource_id() const @@ -354,34 +351,32 @@ namespace redGrapes }; // class Resource - template - struct SharedResourceObject : Resource + template + struct SharedResourceObject : Resource { // protected: std::shared_ptr obj; - SharedResourceObject(ResourceId id, std::shared_ptr const& obj) - : Resource(id) - , obj(obj) + SharedResourceObject(ResourceId id, std::shared_ptr const& obj) : Resource(id), obj(obj) { } template SharedResourceObject(ResourceId id, Args&&... args) - : Resource(id) + : Resource(id) , obj{memory::alloc_shared_bind(mapping::map_resource_to_worker(id), std::forward(args)...)} { } - SharedResourceObject(Resource const& res, std::shared_ptr const& obj) - : Resource{res} + SharedResourceObject(Resource const& res, std::shared_ptr const& obj) + : Resource{res} , obj{obj} { } template - SharedResourceObject(Resource const& res, Args&&... args) - : Resource{res} + SharedResourceObject(Resource const& res, Args&&... args) + : Resource{res} , obj{memory::alloc_shared_bind( mapping::map_resource_to_worker(res.resource_id()), std::forward(args)...)} @@ -392,8 +387,8 @@ namespace redGrapes } // namespace redGrapes -template -struct fmt::formatter> +template<> +struct fmt::formatter { constexpr auto parse(format_parse_context& ctx) { @@ -401,7 +396,7 @@ struct fmt::formatter> } template - auto format(redGrapes::ResourceAccess const& acc, FormatContext& ctx) + auto format(redGrapes::ResourceAccess const& acc, FormatContext& ctx) { return fmt::format_to( ctx.out(), diff --git a/redGrapes/resource/resource_user.hpp b/redGrapes/resource/resource_user.hpp index 05a6fee9..93f5135f 100644 --- a/redGrapes/resource/resource_user.hpp +++ b/redGrapes/resource/resource_user.hpp @@ -11,6 +11,7 @@ #pragma once +#include "redGrapes/resource/resource.hpp" #include "redGrapes/util/chunked_list.hpp" #include @@ -24,41 +25,94 @@ namespace redGrapes # define REDGRAPES_RUL_CHUNKSIZE 128 #endif - template - struct ResourceBase; + struct TaskSpace; - template - struct ResourceAccess; - - template struct ResourceUsageEntry { - std::shared_ptr> resource; - typename ChunkedList::MutBackwardIterator task_entry; + std::shared_ptr resource; + typename ChunkedList::MutBackwardIterator user_entry; - bool operator==(ResourceUsageEntry const& other) const; + friend bool operator==(ResourceUsageEntry const& a, ResourceUsageEntry const& b) + { + return a.resource == b.resource; + } }; - template struct ResourceUser { - ResourceUser(WorkerId worker_id); + ResourceUser(WorkerId worker_id, unsigned scope_depth) + : access_list(memory::Allocator(worker_id)) + , unique_resources(memory::Allocator(worker_id)) + , scope_level(scope_depth) + { + } + ResourceUser(ResourceUser const& other) = delete; - ResourceUser(ResourceUser const& other, WorkerId worker_id) + ResourceUser(ResourceUser const& other, WorkerId worker_id) : access_list(memory::Allocator(worker_id), other.access_list) , unique_resources(memory::Allocator(worker_id), other.unique_resources) , scope_level(other.scope_level) { } - ResourceUser(std::initializer_list> list, WorkerId worker_id); + ResourceUser(std::initializer_list list, WorkerId worker_id, unsigned scope_depth) + : access_list(memory::Allocator(worker_id)) + , unique_resources(memory::Allocator(worker_id)) + , scope_level(scope_depth) + { + for(auto& ra : list) + add_resource_access(ra); + } + + void add_resource_access(ResourceAccess ra) + { + this->access_list.push(ra); + std::shared_ptr r = ra.get_resource(); + unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); + } + + void rm_resource_access(ResourceAccess ra) + { + this->access_list.erase(ra); + } + + void build_unique_resource_list() + { + for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) + { + std::shared_ptr r = ra->get_resource(); + unique_resources.erase(ResourceUsageEntry{r, r->users.rend()}); + unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); + } + } - void add_resource_access(ResourceAccess ra); - void rm_resource_access(ResourceAccess ra); - void build_unique_resource_list(); - bool has_sync_access(std::shared_ptr> const& res); - bool is_superset_of(ResourceUser const& a) const; + bool has_sync_access(std::shared_ptr const& res) + { + for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) + { + if(ra->get_resource() == res && ra->is_synchronizing()) + return true; + } + return false; + } + + bool is_superset_of(ResourceUser const& a) const + { + TRACE_EVENT("ResourceUser", "is_superset"); + for(auto ra = a.access_list.rbegin(); ra != a.access_list.rend(); ++ra) + { + bool found = false; + for(auto r = access_list.rbegin(); r != access_list.rend(); ++r) + if(r->is_superset_of(*ra)) + found = true; + + if(!found && ra->scope_level() <= scope_level) + // a introduced a new resource + return false; + } + return true; + } friend bool is_serial(ResourceUser const& a, ResourceUser const& b) { @@ -67,21 +121,27 @@ namespace redGrapes 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)) + if(ResourceAccess::is_serial(*ra, *rb)) return true; } return false; } - ChunkedList, 8> access_list; - ChunkedList, 8> unique_resources; + ChunkedList access_list; + ChunkedList unique_resources; uint8_t scope_level; + //! task space that contains this task, must not be null + std::shared_ptr space; + + //! task space for children, may be null + std::shared_ptr children; + }; // struct ResourceUser } // namespace redGrapes -template -struct fmt::formatter> +template<> +struct fmt::formatter { constexpr auto parse(format_parse_context& ctx) { @@ -89,7 +149,7 @@ struct fmt::formatter> } template - auto format(redGrapes::ResourceUser const& r, FormatContext& ctx) + auto format(redGrapes::ResourceUser const& r, FormatContext& ctx) { auto out = ctx.out(); out = fmt::format_to(out, "["); @@ -105,5 +165,3 @@ 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 deleted file mode 100644 index 515f8683..00000000 --- a/redGrapes/resource/resource_user.tpp +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright 2019-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/TaskCtx.hpp" -#include "redGrapes/resource/resource.hpp" -#include "redGrapes/resource/resource_user.hpp" -#include "redGrapes/util/trace.hpp" - -namespace redGrapes -{ - template - bool ResourceUsageEntry::operator==(ResourceUsageEntry const& other) const - { - return resource == other.resource; - } - - template - ResourceUser::ResourceUser(WorkerId worker_id) - : access_list(memory::Allocator(worker_id)) - , unique_resources(memory::Allocator(worker_id)) - , scope_level(TaskCtx::scope_depth()) - { - } - - template - ResourceUser::ResourceUser(std::initializer_list> list, WorkerId worker_id) - : access_list(memory::Allocator(worker_id)) - , unique_resources(memory::Allocator(worker_id)) - , scope_level(TaskCtx::scope_depth()) - { - for(auto& ra : list) - add_resource_access(ra); - } - - template - void ResourceUser::add_resource_access(ResourceAccess ra) - { - this->access_list.push(ra); - std::shared_ptr> r = ra.get_resource(); - unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); - } - - template - void ResourceUser::rm_resource_access(ResourceAccess ra) - { - this->access_list.erase(ra); - } - - template - void ResourceUser::build_unique_resource_list() - { - for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) - { - std::shared_ptr> r = ra->get_resource(); - unique_resources.erase(ResourceUsageEntry{r, r->users.rend()}); - unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); - } - } - - template - bool ResourceUser::has_sync_access(std::shared_ptr> const& res) - { - for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) - { - if(ra->get_resource() == res && ra->is_synchronizing()) - return true; - } - return false; - } - - template - bool ResourceUser::is_superset_of(ResourceUser const& a) const - { - TRACE_EVENT("ResourceUser", "is_superset"); - for(auto ra = a.access_list.rbegin(); ra != a.access_list.rend(); ++ra) - { - bool found = false; - for(auto r = access_list.rbegin(); r != access_list.rend(); ++r) - if(r->is_superset_of(*ra)) - found = true; - - if(!found && ra->scope_level() <= scope_level) - // a introduced a new resource - return false; - } - return true; - } - -} // namespace redGrapes diff --git a/redGrapes/scheduler/cuda_thread_scheduler.hpp b/redGrapes/scheduler/cuda_thread_scheduler.hpp index c8f98fbb..047cdfd3 100644 --- a/redGrapes/scheduler/cuda_thread_scheduler.hpp +++ b/redGrapes/scheduler/cuda_thread_scheduler.hpp @@ -7,9 +7,9 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/dispatch/cuda/cuda_worker.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/scheduler/thread_scheduler.hpp" #include @@ -84,7 +84,7 @@ namespace redGrapes { static std::atomic_uint stream_idx = 0; auto task_stream_idx = stream_idx.fetch_add(1) % num_streams; - TaskCtx::current_task->m_cuda_stream_idx = task_stream_idx; + static_cast(current_task)->m_cuda_stream_idx = task_stream_idx; return this->m_worker_thread->worker.streams[task_stream_idx].cuda_stream; } }; diff --git a/redGrapes/task/future.hpp b/redGrapes/task/future.hpp index 38ccf8c3..68d42ab7 100644 --- a/redGrapes/task/future.hpp +++ b/redGrapes/task/future.hpp @@ -10,7 +10,7 @@ */ #pragma once -#include "redGrapes/TaskCtx.hpp" +#include "redGrapes/globalSpace.hpp" namespace redGrapes { @@ -51,7 +51,7 @@ namespace redGrapes T get(void) { // wait until result is set - TaskCtx::yield(task.get_result_set_event()); + yield_impl(task.get_result_set_event()); // take result T result = std::move(*reinterpret_cast(task.get_result_data())); @@ -104,7 +104,7 @@ namespace redGrapes void get(void) { // wait until result is set - TaskCtx::yield(task.get_result_set_event()); + yield_impl(task.get_result_set_event()); // take result taken = true; diff --git a/redGrapes/task/property/graph.hpp b/redGrapes/task/property/graph.hpp index 03b748ec..cb57b095 100644 --- a/redGrapes/task/property/graph.hpp +++ b/redGrapes/task/property/graph.hpp @@ -12,15 +12,8 @@ #include -#include - namespace redGrapes { - - // struct Task; - template - struct TaskSpace; - /*! * Each task associates with two events: * A Pre-Event and a Post-Event. @@ -43,7 +36,8 @@ namespace redGrapes template struct GraphProperty { - GraphProperty(WorkerId worker_id) + // Params workerId and scope_depth + GraphProperty(WorkerId worker_id, unsigned) : pre_event{worker_id} , post_event{worker_id} , result_set_event{worker_id} @@ -63,12 +57,6 @@ namespace redGrapes TTask* task; - //! task space that contains this task, must not be null - std::shared_ptr> space; - - //! task space for children, may be null - std::shared_ptr> children; - /* // in edges dont need a mutex because they are initialized // once by `init_dependencies()` and only read afterwards. diff --git a/redGrapes/task/property/graph.tpp b/redGrapes/task/property/graph.tpp index b1caa0ca..04d0e2b3 100644 --- a/redGrapes/task/property/graph.tpp +++ b/redGrapes/task/property/graph.tpp @@ -10,8 +10,6 @@ #include "redGrapes/task/property/graph.hpp" #include "redGrapes/util/trace.hpp" -#include - namespace redGrapes { @@ -38,7 +36,7 @@ namespace redGrapes TRACE_EVENT("Graph", "init_graph"); for(auto r = task->unique_resources.rbegin(); r != task->unique_resources.rend(); ++r) { - if(r->task_entry != r->resource->users.rend()) + if(r->user_entry != r->resource->users.rend()) { // TODO: can this lock be avoided? // @@ -51,18 +49,18 @@ namespace redGrapes std::unique_lock lock(r->resource->users_mutex); TRACE_EVENT("Graph", "CheckPredecessors"); - auto it = r->task_entry; + auto it = r->user_entry; ++it; for(; it != r->resource->users.rend(); ++it) { TRACE_EVENT("Graph", "Check Pred"); - TTask* preceding_task = *it; + auto preceding_task = static_cast(*it); - if(preceding_task == space->parent) + if(preceding_task == task->space->parent) break; - if(preceding_task->space == space && is_serial(*preceding_task, *task)) + if(preceding_task->space == task->space && is_serial(*preceding_task, *task)) { add_dependency(*preceding_task); if(preceding_task->has_sync_access(r->resource)) @@ -83,8 +81,8 @@ namespace redGrapes // corresponding lock to init_graph() std::unique_lock lock(r->resource->users_mutex); - if(r->task_entry != r->resource->users.rend()) - r->resource->users.remove(r->task_entry); + if(r->user_entry != r->resource->users.rend()) + r->resource->users.remove(r->user_entry); } } diff --git a/redGrapes/task/property/id.hpp b/redGrapes/task/property/id.hpp index e38e5890..2ea5a613 100644 --- a/redGrapes/task/property/id.hpp +++ b/redGrapes/task/property/id.hpp @@ -34,19 +34,20 @@ namespace redGrapes public: TaskID task_id; - IDProperty(WorkerId) : task_id(-1) // id_counter().fetch_add( 1, std::memory_order_seq_cst ) ) + // Params workerId and scope_depth + IDProperty(WorkerId, unsigned) : task_id(-1) // id_counter().fetch_add( 1, std::memory_order_seq_cst ) ) { } - IDProperty(WorkerId, IDProperty&& other) : task_id(other.task_id) + IDProperty(IDProperty&& other) : task_id(other.task_id) { } - IDProperty(WorkerId, IDProperty const& other) : task_id(other.task_id) + IDProperty(IDProperty const& other) : task_id(other.task_id) { } - IDProperty& operator=(IDProperty const& other) + IDProperty& operator=(IDProperty const&) { return *this; } diff --git a/redGrapes/task/property/inherit.hpp b/redGrapes/task/property/inherit.hpp index a7ff1dc6..29722a61 100644 --- a/redGrapes/task/property/inherit.hpp +++ b/redGrapes/task/property/inherit.hpp @@ -25,7 +25,9 @@ namespace redGrapes : T_Head , TaskPropertiesInherit { - TaskPropertiesInherit(WorkerId worker_id) :T_Head(worker_id), TaskPropertiesInherit(worker_id) + TaskPropertiesInherit(WorkerId worker_id, unsigned scope_depth) + : T_Head(worker_id, scope_depth) + , TaskPropertiesInherit(worker_id, scope_depth) { } @@ -70,7 +72,8 @@ namespace redGrapes template<> struct TaskPropertiesInherit { - TaskPropertiesInherit(WorkerId) + // Params workerId and scope_depth + TaskPropertiesInherit(WorkerId, unsigned) { } @@ -101,7 +104,8 @@ namespace redGrapes template struct TaskProperties1 : public TaskPropertiesInherit { - TaskProperties1(WorkerId worker_id) : TaskPropertiesInherit(worker_id) + TaskProperties1(WorkerId worker_id, unsigned scope_depth) + : TaskPropertiesInherit(worker_id, scope_depth) { } diff --git a/redGrapes/task/property/label.hpp b/redGrapes/task/property/label.hpp index 7c88ea76..8da22248 100644 --- a/redGrapes/task/property/label.hpp +++ b/redGrapes/task/property/label.hpp @@ -25,7 +25,8 @@ namespace redGrapes // TODO Optimization, use the workerId to allocate the label string seperate from the task // using string = std::basic_string, memory::StdAllocator>; - LabelProperty(WorkerId) + // Params workerId and scope_depth + LabelProperty(WorkerId, unsigned) { } diff --git a/redGrapes/task/property/resource.hpp b/redGrapes/task/property/resource.hpp index e772cb23..cd847d08 100644 --- a/redGrapes/task/property/resource.hpp +++ b/redGrapes/task/property/resource.hpp @@ -11,8 +11,8 @@ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/TaskFreeCtx.hpp" +#include "redGrapes/globalSpace.hpp" #include "redGrapes/resource/resource_user.hpp" #include @@ -25,9 +25,9 @@ namespace redGrapes { template - struct ResourceProperty : ResourceUser + struct ResourceProperty : ResourceUser { - ResourceProperty(WorkerId worker_id) : ResourceUser(worker_id) + ResourceProperty(WorkerId worker_id, unsigned scope_depth) : ResourceUser(worker_id, scope_depth) { } @@ -40,16 +40,16 @@ namespace redGrapes { } - PropertiesBuilder& resources(std::initializer_list> list) + PropertiesBuilder& resources(std::initializer_list list) { - for(ResourceAccess const& ra : list) + for(ResourceAccess const& ra : list) builder.task->access_list.push(ra); builder.task->build_unique_resource_list(); return builder; } - inline PropertiesBuilder& add_resource(ResourceAccess access) + inline PropertiesBuilder& add_resource(ResourceAccess access) { (*builder.task) += access; return builder; @@ -67,7 +67,7 @@ namespace redGrapes { } - PatchBuilder add_resources(std::initializer_list> list) + PatchBuilder add_resources(std::initializer_list list) { Patch& p = builder.patch; for(auto const& acc : list) @@ -75,7 +75,7 @@ namespace redGrapes return builder; } - PatchBuilder remove_resources(std::initializer_list> list) + PatchBuilder remove_resources(std::initializer_list list) { Patch& p = builder.patch; for(auto const& acc : list) @@ -90,30 +90,30 @@ namespace redGrapes REMOVE }; - std::list>> diff; + std::list> diff; void operator+=(Patch const& other) { this->diff.insert(std::end(this->diff), std::begin(other.diff), std::end(other.diff)); } - void operator+=(ResourceAccess const& ra) + void operator+=(ResourceAccess const& ra) { this->diff.push_back(std::make_pair(DiffType::ADD, ra)); } - void operator-=(ResourceAccess const& ra) + void operator-=(ResourceAccess const& ra) { this->diff.push_back(std::make_pair(DiffType::REMOVE, ra)); } }; - inline void operator+=(ResourceAccess const& ra) + inline void operator+=(ResourceAccess const& ra) { this->add_resource_access(ra); } - inline void operator-=(ResourceAccess const& ra) + inline void operator-=(ResourceAccess const& ra) { this->rm_resource_access(ra); } @@ -121,7 +121,7 @@ namespace redGrapes // Only to be called inside a running task to update property void apply_patch(Patch const& patch) { - ResourceUser before(*this, (*TaskCtx::current_task)->worker_id); + ResourceUser before(*this, static_cast(current_task)->worker_id); for(auto x : patch.diff) { @@ -154,6 +154,6 @@ struct fmt::formatter> template auto format(redGrapes::ResourceProperty const& label_prop, FormatContext& ctx) { - return fmt::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 e53f858c..4571a7b9 100644 --- a/redGrapes/task/task.hpp +++ b/redGrapes/task/task.hpp @@ -48,8 +48,8 @@ namespace redGrapes std::atomic removal_countdown; scheduler::IScheduler>* scheduler_p; - Task(WorkerId _worker_id, scheduler::IScheduler>& scheduler) - : TaskProperties(_worker_id) + Task(WorkerId _worker_id, unsigned scope_depth, scheduler::IScheduler>& scheduler) + : TaskProperties(_worker_id, scope_depth) , worker_id(_worker_id) , removal_countdown(2) , scheduler_p(&scheduler) @@ -70,7 +70,8 @@ namespace redGrapes { Result result_data; - ResultTask(WorkerId worker_id, scheduler::IScheduler& scheduler) : TTask(worker_id, scheduler) + ResultTask(WorkerId worker_id, unsigned scope_depth, scheduler::IScheduler& scheduler) + : TTask(worker_id, scope_depth, scheduler) { } @@ -95,7 +96,8 @@ namespace redGrapes template struct ResultTask : TTask { - ResultTask(WorkerId worker_id, scheduler::IScheduler& scheduler) : TTask(worker_id, scheduler) + ResultTask(WorkerId worker_id, unsigned scope_depth, scheduler::IScheduler& scheduler) + : TTask(worker_id, scope_depth, scheduler) { } @@ -117,8 +119,8 @@ namespace redGrapes template struct FunTask : ResultTask, TTask> { - FunTask(WorkerId worker_id, scheduler::IScheduler& scheduler) - : ResultTask, TTask>(worker_id, scheduler) + FunTask(WorkerId worker_id, unsigned scope_depth, scheduler::IScheduler& scheduler) + : ResultTask, TTask>(worker_id, scope_depth, scheduler) { } diff --git a/redGrapes/task/task_builder.hpp b/redGrapes/task/task_builder.hpp index 303a90b5..5855155b 100644 --- a/redGrapes/task/task_builder.hpp +++ b/redGrapes/task/task_builder.hpp @@ -6,7 +6,6 @@ */ #pragma once -#include "redGrapes/TaskCtx.hpp" #include "redGrapes/task/future.hpp" #include "redGrapes/task/task.hpp" #include "redGrapes/task/task_space.hpp" @@ -47,12 +46,16 @@ namespace redGrapes using Impl = typename std::invoke_result_t, Callable, Args...>; using Result = typename std::invoke_result_t; - std::shared_ptr> space; + std::shared_ptr space; FunTask* task; - TaskBuilder(FunTask* task, Callable&& f, Args&&... args) + TaskBuilder( + FunTask* task, + std::shared_ptr const& current_space, + Callable&& f, + Args&&... args) : TTask::TaskProperties::template Builder(*this) - , space(TaskCtx::current_task_space()) + , space(current_space) , task{task} { // init properties from args diff --git a/redGrapes/task/task_space.hpp b/redGrapes/task/task_space.hpp index e7439a7e..b8eaa331 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/resource/resource_user.hpp" #include "redGrapes/task/property/id.hpp" #include "redGrapes/util/trace.hpp" @@ -20,12 +21,11 @@ namespace redGrapes /*! TaskSpace handles sub-taskspaces of child tasks */ - template - struct TaskSpace : std::enable_shared_from_this> + struct TaskSpace : std::enable_shared_from_this { std::atomic task_count; unsigned depth; - TTask* parent; + ResourceUser* parent; // top space TaskSpace() : task_count(0), depth(0), parent(nullptr) @@ -33,12 +33,17 @@ namespace redGrapes } // sub space - - TaskSpace(TTask* parent) : task_count(0), depth(parent->space->depth + 1), parent(parent) + template + requires std::is_base_of_v + TaskSpace(TTask* parent) : task_count(0) + , depth(parent->space->depth + 1) + , parent(parent) { } // add a new task to the task-space + template + requires std::is_base_of_v void submit(TTask* task) { TRACE_EVENT("TaskSpace", "submit()"); @@ -52,16 +57,18 @@ namespace redGrapes assert(parent->is_superset_of(*task)); // add dependency to parent SPDLOG_TRACE("add event dep to parent"); - task->post_event.add_follower(parent->get_post_event()); + task->post_event.add_follower(static_cast(parent)->get_post_event()); } for(auto r = task->unique_resources.rbegin(); r != task->unique_resources.rend(); ++r) { - r->task_entry = r->resource->users.push(task); + r->user_entry = r->resource->users.push(task); } } // remove task from task-space + template + requires std::is_base_of_v && std::is_base_of_v void free_task(TTask* task) { TRACE_EVENT("TaskSpace", "free_task()"); @@ -80,7 +87,7 @@ namespace redGrapes // SPDLOG_INFO("kill task... {} remaining", count); // to wake after barrier the check tells us that the root space is empty - // if(TaskCtx::root_space->empty()) cant be written because TaskCtx include root space + // if(all_tasks_done()) if(count == 0 && depth == 0) { SPDLOG_TRACE("Wake up parser due to free task and no more tasks"); diff --git a/test/random_graph.cpp b/test/random_graph.cpp index d4fa6b10..e2a41326 100644 --- a/test/random_graph.cpp +++ b/test/random_graph.cpp @@ -102,10 +102,9 @@ TEST_CASE("RandomGraph") generate_access_pattern(); - using TTask = redGrapes::Task<>; auto rg = redGrapes::init(n_threads); { - std::vector, TTask>> resources(n_resources); + std::vector>> resources(n_resources); for(unsigned i = 0; i < n_tasks; ++i) switch(access_pattern[i].size()) diff --git a/test/resource.cpp b/test/resource.cpp index 142c2f53..2ad23711 100644 --- a/test/resource.cpp +++ b/test/resource.cpp @@ -45,47 +45,45 @@ struct fmt::formatter TEST_CASE("Resource ID") { auto rg = redGrapes::init(1); - using RGTask = decltype(rg)::RGTask; auto a = rg.createResource(); auto b = rg.createResource(); // same resource - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a.make_access(Access{})) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), b.make_access(Access{})) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a.make_access(Access{})) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), b.make_access(Access{})) == true); // same resource, but copied - redGrapes::Resource a2(a); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a2.make_access(Access{})) == true); + redGrapes::Resource a2(a); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a2.make_access(Access{})) == true); // different resource - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), b.make_access(Access{})) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), a.make_access(Access{})) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), b.make_access(Access{})) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), a.make_access(Access{})) == false); } TEST_CASE("IOResource") { auto rg = redGrapes::init(1); - using RGTask = decltype(rg)::RGTask; - redGrapes::IOResource a, b; + redGrapes::IOResource a, b; - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.read()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.write()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.write()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.read()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.read()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.write()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.write()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.read()) == true); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.write()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.write()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.write()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.write()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.write()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.write()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.write()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.read()) == false); + REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.write()) == false); } diff --git a/test/resource_user.cpp b/test/resource_user.cpp index acd37b46..5d36fdbb 100644 --- a/test/resource_user.cpp +++ b/test/resource_user.cpp @@ -8,15 +8,14 @@ TEST_CASE("Resource User") { auto rg = redGrapes::init(1); - using RGTask = decltype(rg)::RGTask; - redGrapes::IOResource a, b; + redGrapes::IOResource a, b; - redGrapes::ResourceUser f1({a.read()}, 0); - redGrapes::ResourceUser f2({a.read(), a.write()}, 0); - redGrapes::ResourceUser f3({b.read()}, 0); - redGrapes::ResourceUser f4({b.read(), b.write()}, 0); - redGrapes::ResourceUser f5({a.read(), a.write(), b.read(), b.write()}, 0); + redGrapes::ResourceUser f1({a.read()}, 0, 0); + redGrapes::ResourceUser f2({a.read(), a.write()}, 0, 0); + redGrapes::ResourceUser f3({b.read()}, 0, 0); + redGrapes::ResourceUser f4({b.read(), b.write()}, 0, 0); + redGrapes::ResourceUser f5({a.read(), a.write(), b.read(), b.write()}, 0, 0); REQUIRE(is_serial(f1, f1) == false); REQUIRE(is_serial(f1, f2) == true);