diff --git a/app/benchmark_fft/main.cpp b/app/benchmark_fft/main.cpp index 64f2915..5a35e16 100644 --- a/app/benchmark_fft/main.cpp +++ b/app/benchmark_fft/main.cpp @@ -37,7 +37,7 @@ void conquer(fft::complex_vector::iterator data, int n) { constexpr int MAX_NUM_THREADS = 8; constexpr int MAX_NUM_TASKS = 32; -constexpr int MAX_STACK_SIZE = 1024 * 64; +constexpr int MAX_STACK_SIZE = 1024 * 32; static_scheduler_memory { public: pls_matrix() : matrix::matrix() {} - void pls_multiply(const matrix::matrix &a, const matrix::matrix &b) { - pls::algorithm::for_each_range(0, SIZE, [this, &a, &b](int i) { + void multiply(const matrix::matrix &a, const matrix::matrix &b) override { + pls::algorithm::for_each_range(0, SIZE, [&](int i) { this->multiply_column(i, a, b); }); } @@ -23,7 +23,7 @@ class pls_matrix : public matrix::matrix { constexpr int MAX_NUM_THREADS = 8; constexpr int MAX_NUM_TASKS = 32; -constexpr int MAX_STACK_SIZE = 1024 * 4; +constexpr int MAX_STACK_SIZE = 1024 * 1; static_scheduler_memory diff --git a/lib/pls/include/pls/internal/scheduling/task.h b/lib/pls/include/pls/internal/scheduling/task.h index fa2977c..c8696a8 100644 --- a/lib/pls/include/pls/internal/scheduling/task.h +++ b/lib/pls/include/pls/internal/scheduling/task.h @@ -34,6 +34,8 @@ struct alignas(base::system_details::CACHE_LINE_SIZE) task { depth_ = depth; thread_id_ = thread_id; + + is_synchronized_ = false; } template @@ -44,9 +46,11 @@ struct alignas(base::system_details::CACHE_LINE_SIZE) task { // TODO: Proper access control and split it up into responsibilities // Stack/Continuation Management char *stack_memory_; - size_t stack_size_; + size_t stack_size_; // TODO: maybe remove it, not needed in here context_switcher::continuation continuation_; + bool is_synchronized_; + // TODO: Clean up responsibilities // Work-Stealing std::atomic external_trading_deque_cas_{}; std::atomic resource_stack_next_{}; diff --git a/lib/pls/include/pls/internal/scheduling/task_manager_impl.h b/lib/pls/include/pls/internal/scheduling/task_manager_impl.h index 4c4d740..ba11377 100644 --- a/lib/pls/include/pls/internal/scheduling/task_manager_impl.h +++ b/lib/pls/include/pls/internal/scheduling/task_manager_impl.h @@ -28,6 +28,7 @@ void task_manager::spawn_child(F &&lambda) { last_task->continuation_ = std::move(cont); // we are now executing the new task, allow others to steal the last task continuation. + spawned_task->is_synchronized_ = true; spawning_task_manager->active_task_ = spawned_task; spawning_task_manager->deque_.push_bot(last_task); diff --git a/lib/pls/src/internal/scheduling/scheduler.cpp b/lib/pls/src/internal/scheduling/scheduler.cpp index c414208..484337a 100644 --- a/lib/pls/src/internal/scheduling/scheduler.cpp +++ b/lib/pls/src/internal/scheduling/scheduler.cpp @@ -108,6 +108,7 @@ void scheduler::work_thread_work_section() { // Execute the stolen task by jumping to it's continuation. PLS_ASSERT(stolen_task->continuation_.valid(), "A task that we can steal must have a valid continuation for us to start working."); + stolen_task->is_synchronized_ = false; context_switcher::switch_context(std::move(stolen_task->continuation_)); // We will continue execution in this line when we finished the stolen work. } diff --git a/lib/pls/src/internal/scheduling/task_manager.cpp b/lib/pls/src/internal/scheduling/task_manager.cpp index eeff837..c0c7e12 100644 --- a/lib/pls/src/internal/scheduling/task_manager.cpp +++ b/lib/pls/src/internal/scheduling/task_manager.cpp @@ -128,23 +128,29 @@ void task_manager::sync() { auto *last_task = spawning_task_manager->active_task_; auto *spawned_task = spawning_task_manager->active_task_->next_; - auto continuation = spawned_task->run_as_task([=](context_switcher::continuation cont) { - last_task->continuation_ = std::move(cont); - spawning_task_manager->active_task_ = spawned_task; - - context_switcher::continuation result_cont; - if (spawning_task_manager->try_clean_return(result_cont)) { - // We return back to the main scheduling loop - return result_cont; - } else { - // We finish up the last task - return result_cont; - } - }); - - PLS_ASSERT(!continuation.valid(), - "We only return to a sync point, never jump to it directly." - "This must therefore never return an unfinished fiber/continuation."); + if (last_task->is_synchronized_) { + return; // We are already the sole owner of last_task + } else { + auto continuation = spawned_task->run_as_task([=](context_switcher::continuation cont) { + last_task->continuation_ = std::move(cont); + spawning_task_manager->active_task_ = spawned_task; + + context_switcher::continuation result_cont; + if (spawning_task_manager->try_clean_return(result_cont)) { + // We return back to the main scheduling loop + return result_cont; + } else { + // We finish up the last task + return result_cont; + } + }); + + PLS_ASSERT(!continuation.valid(), + "We only return to a sync point, never jump to it directly." + "This must therefore never return an unfinished fiber/continuation."); + + return; // We cleanly synced to the last one finishing work on last_task + } } bool task_manager::try_clean_return(context_switcher::continuation &result_cont) { @@ -195,6 +201,7 @@ bool task_manager::try_clean_return(context_switcher::continuation &result_cont) // We are the last one working on this task. Thus the sync must be finished, continue working. active_task_ = last_task; + last_task->is_synchronized_ = true; result_cont = std::move(last_task->continuation_); PLS_ASSERT(result_cont.valid(), "Must return a valid continuation."); return false;