From 8c5ed0a18ad38d769568caedbc983e7adc0d7ac7 Mon Sep 17 00:00:00 2001 From: Florian Schmaus <flow@cs.fau.de> Date: Sat, 8 May 2021 14:32:44 +0200 Subject: [PATCH] Already check if fiber is runnable in scheduliing subsystem Already check if the fiber is in-fact runnable in the scheduling subsystem. This should not make a difference when WS scheduling is used, but makes a difference when LAWS is used. --- emper/Dispatcher.hpp | 1 + emper/Fiber.hpp | 2 ++ emper/RuntimeStrategy.hpp | 1 + emper/Scheduler.cpp | 4 +++- emper/Scheduler.hpp | 8 ++++++- .../AbstractWorkStealingScheduler.cpp | 24 +++++++++++++++---- .../AbstractWorkStealingScheduler.hpp | 5 +++- emper/strategies/laws/LawsScheduler.cpp | 3 ++- emper/strategies/laws/LawsScheduler.hpp | 3 ++- emper/strategies/laws/LawsStrategy.cpp | 2 +- emper/strategies/ws/WsScheduler.cpp | 3 ++- emper/strategies/ws/WsScheduler.hpp | 3 ++- emper/strategies/ws/WsStrategy.cpp | 2 +- 13 files changed, 48 insertions(+), 13 deletions(-) diff --git a/emper/Dispatcher.hpp b/emper/Dispatcher.hpp index 4aca48c4..9b2d390e 100644 --- a/emper/Dispatcher.hpp +++ b/emper/Dispatcher.hpp @@ -57,4 +57,5 @@ class Dispatcher : public Logger<LogSubsystem::DISP> { static auto isDispatchedControlFlow() -> bool { return getCurrentFiberPtr() != nullptr; } friend ContextManager; + friend class Scheduler; }; diff --git a/emper/Fiber.hpp b/emper/Fiber.hpp index 7caf6080..9f6965f9 100644 --- a/emper/Fiber.hpp +++ b/emper/Fiber.hpp @@ -112,6 +112,8 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { void print() const; + [[nodiscard]] auto isRunnable() const -> bool { return runnable; } + friend auto operator<<(std::ostream& strm, const Fiber& fiber) -> std::ostream&; static inline auto from(fiber_fun_t function, void* arg) -> Fiber* { diff --git a/emper/RuntimeStrategy.hpp b/emper/RuntimeStrategy.hpp index 2cbe48bd..6fc77235 100644 --- a/emper/RuntimeStrategy.hpp +++ b/emper/RuntimeStrategy.hpp @@ -11,6 +11,7 @@ class RuntimeStrategyStats; class RuntimeStrategy { friend class Runtime; + friend class Scheduler; private: virtual auto getScheduler() -> Scheduler& = 0; diff --git a/emper/Scheduler.cpp b/emper/Scheduler.cpp index eb4dde0b..534edfbe 100644 --- a/emper/Scheduler.cpp +++ b/emper/Scheduler.cpp @@ -4,8 +4,10 @@ #include "CallerEnvironment.hpp" #include "Runtime.hpp" +#include "RuntimeStrategy.hpp" -Scheduler::Scheduler(Runtime& runtime) : runtime(runtime) {} +Scheduler::Scheduler(Runtime& runtime, RuntimeStrategy& strategy) + : runtime(runtime), dispatcher(strategy.getDispatcher()) {} void Scheduler::addNewWorkerHook(const std::function<void(workerid_t)>& hook) { runtime.addNewWorkerHook(hook); diff --git a/emper/Scheduler.hpp b/emper/Scheduler.hpp index d71ba18b..bb1d34bf 100644 --- a/emper/Scheduler.hpp +++ b/emper/Scheduler.hpp @@ -7,12 +7,14 @@ #include "CallerEnvironment.hpp" #include "Debug.hpp" // for LogSubsystem, LogSubsystem::SCHED, Logger +#include "Dispatcher.hpp" #include "Emper.hpp" #include "Fiber.hpp" // for Fiber #include "emper-common.h" // for workeraffinity_t #include "lib/adt/LockedUnboundedQueue.hpp" class Runtime; +class RuntimeStrategy; struct NextFiberResult; class Scheduler : public Logger<LogSubsystem::SCHED> { @@ -24,7 +26,9 @@ class Scheduler : public Logger<LogSubsystem::SCHED> { protected: Runtime& runtime; - Scheduler(Runtime& runtime); + Dispatcher& dispatcher; + + Scheduler(Runtime& runtime, RuntimeStrategy& strategy); virtual ~Scheduler() = default; @@ -55,6 +59,8 @@ class Scheduler : public Logger<LogSubsystem::SCHED> { virtual void scheduleFromAnywhereInternal(Fiber& fiber) = 0; virtual void scheduleFromAnywhereInternal(Fiber** fibers, unsigned count) = 0; + void recycle(Fiber* fiber) { dispatcher.recycle(fiber); }; + public: void schedule(Fiber& fiber) { LOGD("Scheduling fiber " << &fiber); diff --git a/emper/strategies/AbstractWorkStealingScheduler.cpp b/emper/strategies/AbstractWorkStealingScheduler.cpp index 7ca37227..62ecb93c 100644 --- a/emper/strategies/AbstractWorkStealingScheduler.cpp +++ b/emper/strategies/AbstractWorkStealingScheduler.cpp @@ -7,21 +7,21 @@ #include "Common.hpp" // for unlikely, likely #include "Debug.hpp" // for ABORT #include "Emper.hpp" // for OVERFLOW_QUEUE +#include "Fiber.hpp" #include "NextFiberResult.hpp" #include "Runtime.hpp" // for Runtime #include "emper-common.h" // for workerid_t #include "strategies/AbstractWorkStealingStrategy.hpp" #include "strategies/AbstractWorkStealingWorkerStats.hpp" -class Fiber; - using awss = AbstractWorkStealingStrategy; thread_local AbstractWorkStealingScheduler::WsQueue<AbstractWorkStealingScheduler::QUEUE_SIZE> AbstractWorkStealingScheduler::queue; -AbstractWorkStealingScheduler::AbstractWorkStealingScheduler(Runtime& runtime) - : Scheduler(runtime) { +AbstractWorkStealingScheduler::AbstractWorkStealingScheduler(Runtime& runtime, + RuntimeStrategy& strategy) + : Scheduler(runtime, strategy) { const workerid_t workerCount = runtime.getWorkerCount(); queues = new AbstractWorkStealingScheduler::WsQueue<QUEUE_SIZE>*[workerCount]; @@ -48,14 +48,24 @@ void AbstractWorkStealingScheduler::scheduleViaWorkStealing(Fiber& fiber) { onNewWork(); } +auto AbstractWorkStealingScheduler::maybeRecycle(Fiber* fiber) -> bool { + if (fiber->isRunnable()) return false; + + recycle(fiber); + return true; +} + auto AbstractWorkStealingScheduler::nextFiberViaWorkStealing() -> std::pair<Fiber*, FiberSource> { FiberSource fiberSource = FiberSource::local; Fiber* fiber; +popBottom: bool poped = queue.popBottom(&fiber); if (likely(poped)) { emper::statsIncr(awss::stats.nextFiberFromLocal); + if (maybeRecycle(fiber)) goto popBottom; + goto out; } @@ -70,21 +80,27 @@ auto AbstractWorkStealingScheduler::nextFiberViaWorkStealing() -> std::pair<Fibe // Don't steal from ourselves. if (unlikely(victim == myWorkerId)) continue; + popTop: poped = queues[victim]->popTop(&fiber); if (poped) { emper::statsIncr(awss::stats.nextFiberStolen); + if (maybeRecycle(fiber)) goto popTop; + fiberSource = FiberSource::stolen; goto out; } } } +dequeueFromAnywhere: // Try the "scheduled from anywhere" queue to get work as last resort. fiber = dequeueFiberFromAnywhereQueue(); if (fiber) { emper::statsIncr(awss::stats.nextFiberFromAnywhereQueue); + if (maybeRecycle(fiber)) goto dequeueFromAnywhere; + fiberSource = FiberSource::anywhereQueue; } diff --git a/emper/strategies/AbstractWorkStealingScheduler.hpp b/emper/strategies/AbstractWorkStealingScheduler.hpp index 64071b71..e482243b 100644 --- a/emper/strategies/AbstractWorkStealingScheduler.hpp +++ b/emper/strategies/AbstractWorkStealingScheduler.hpp @@ -17,6 +17,7 @@ class Fiber; class Runtime; +class RuntimeStrategy; class AbstractWorkStealingScheduler : public Scheduler { template <size_t SIZE> @@ -41,10 +42,12 @@ class AbstractWorkStealingScheduler : public Scheduler { void scheduleViaWorkStealing(Fiber& fiber); + auto maybeRecycle(Fiber* fiber) -> bool; + auto nextFiberViaWorkStealing() -> std::pair<Fiber*, FiberSource>; auto nextFiberResultViaWorkStealing() -> NextFiberResult; public: - AbstractWorkStealingScheduler(Runtime& runtime); + AbstractWorkStealingScheduler(Runtime& runtime, RuntimeStrategy& strategy); }; diff --git a/emper/strategies/laws/LawsScheduler.cpp b/emper/strategies/laws/LawsScheduler.cpp index 138d9ef4..8066c5cb 100644 --- a/emper/strategies/laws/LawsScheduler.cpp +++ b/emper/strategies/laws/LawsScheduler.cpp @@ -14,7 +14,8 @@ thread_local LawsScheduler::LawsMpscQueue LawsScheduler::priorityQueue; -LawsScheduler::LawsScheduler(Runtime& runtime) : AbstractWorkStealingScheduler(runtime) { +LawsScheduler::LawsScheduler(Runtime& runtime, RuntimeStrategy& strategy) + : AbstractWorkStealingScheduler(runtime, strategy) { const workerid_t workerCount = runtime.getWorkerCount(); priorityQueues = new LawsScheduler::LawsMpscQueue*[workerCount]; diff --git a/emper/strategies/laws/LawsScheduler.hpp b/emper/strategies/laws/LawsScheduler.hpp index 8f9c1682..f4b0f242 100644 --- a/emper/strategies/laws/LawsScheduler.hpp +++ b/emper/strategies/laws/LawsScheduler.hpp @@ -8,6 +8,7 @@ #include "strategies/AbstractWorkStealingScheduler.hpp" class Runtime; +class RuntimeStrategy; struct NextFiberResult; class LawsScheduler : public AbstractWorkStealingScheduler { @@ -27,7 +28,7 @@ class LawsScheduler : public AbstractWorkStealingScheduler { void scheduleFromAnywhereInternal(Fiber** fibers, unsigned count) override; public: - LawsScheduler(Runtime& runtime); + LawsScheduler(Runtime& runtime, RuntimeStrategy& strategy); auto nextFiber() -> NextFiberResult override; }; diff --git a/emper/strategies/laws/LawsStrategy.cpp b/emper/strategies/laws/LawsStrategy.cpp index 57116344..603391b4 100644 --- a/emper/strategies/laws/LawsStrategy.cpp +++ b/emper/strategies/laws/LawsStrategy.cpp @@ -13,7 +13,7 @@ thread_local LawsWorkerStats LawsStrategy::stats; LawsStrategy::LawsStrategy(Runtime& runtime) : AbstractWorkStealingStrategy(runtime), - scheduler(runtime), + scheduler(runtime, *this), dispatcher(runtime), allWorkerStats([] { return &stats; }, runtime) {} diff --git a/emper/strategies/ws/WsScheduler.cpp b/emper/strategies/ws/WsScheduler.cpp index b57510cb..ae98ce21 100644 --- a/emper/strategies/ws/WsScheduler.cpp +++ b/emper/strategies/ws/WsScheduler.cpp @@ -2,4 +2,5 @@ // Copyright © 2020-2021 Florian Schmaus #include "WsScheduler.hpp" -WsScheduler::WsScheduler(Runtime& runtime) : AbstractWorkStealingScheduler(runtime) {} +WsScheduler::WsScheduler(Runtime& runtime, RuntimeStrategy& strategy) + : AbstractWorkStealingScheduler(runtime, strategy) {} diff --git a/emper/strategies/ws/WsScheduler.hpp b/emper/strategies/ws/WsScheduler.hpp index c122f301..c0ce9c3b 100644 --- a/emper/strategies/ws/WsScheduler.hpp +++ b/emper/strategies/ws/WsScheduler.hpp @@ -8,6 +8,7 @@ class Fiber; class Runtime; +class RuntimeStrategy; class WsScheduler : public AbstractWorkStealingScheduler { protected: @@ -23,7 +24,7 @@ class WsScheduler : public AbstractWorkStealingScheduler { } public: - WsScheduler(Runtime& runtime); + WsScheduler(Runtime& runtime, RuntimeStrategy& strategy); auto nextFiber() -> NextFiberResult override { return nextFiberResultViaWorkStealing(); }; }; diff --git a/emper/strategies/ws/WsStrategy.cpp b/emper/strategies/ws/WsStrategy.cpp index 11fcd3d0..b6eb19e0 100644 --- a/emper/strategies/ws/WsStrategy.cpp +++ b/emper/strategies/ws/WsStrategy.cpp @@ -10,7 +10,7 @@ class Runtime; class RuntimeStrategyStats; WsStrategy::WsStrategy(Runtime& runtime) - : AbstractWorkStealingStrategy(runtime), scheduler(runtime), dispatcher(runtime) {} + : AbstractWorkStealingStrategy(runtime), scheduler(runtime, *this), dispatcher(runtime) {} auto WsStrategy::getScheduler() -> WsScheduler& { return scheduler; } -- GitLab