From 414467631261ad0bf92eb987af8c1be572bc1abc Mon Sep 17 00:00:00 2001
From: Florian Schmaus <flow@cs.fau.de>
Date: Tue, 12 Jan 2021 18:25:43 +0100
Subject: [PATCH] [LAWS] Attempt to steal from all other workers instead of
 just one

The LAWS strategy, unlike the WS strategy, previously only attempted
to steal from one victim, instead of trying all other workers. This
probably caused SimpleActorTest to sporadically timeout, as all
workers went to sleep.

With this change, LAWS attempts, just like WS, to steal from all other
workers. In a next step, we may want to reduce the duplicated code
resulting from this.

Fixes #6.
---
 emper/strategies/laws/LawsScheduler.cpp | 27 +++++++++++++++----------
 emper/strategies/ws/WsScheduler.cpp     |  2 ++
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/emper/strategies/laws/LawsScheduler.cpp b/emper/strategies/laws/LawsScheduler.cpp
index 75f8d468..1432b3d0 100644
--- a/emper/strategies/laws/LawsScheduler.cpp
+++ b/emper/strategies/laws/LawsScheduler.cpp
@@ -94,24 +94,29 @@ auto LawsScheduler::nextFiber() -> Fiber* {
 		return fiber;
 	}
 
+	// TODO: The code below is nearly duplicated, besides the statsk
+	// part, in WsScheduler, deduplicate.
+	const workerid_t myWorkerId = Runtime::getWorkerId();
 	const workerid_t workerCount = runtime.getWorkerCount();
 	workerid_t startWorkerId = Runtime::rand() % workerCount;
+	// TODO: See how reducing the loop bound affects things.
+	for (workerid_t i = 0; i < workerCount; ++i) {
+		workerid_t victim = (startWorkerId + i) % workerCount;
 
-	if (unlikely(startWorkerId == Runtime::getWorkerId())) startWorkerId++;
-	workerid_t victim = startWorkerId % workerCount;
+		// Don't steal from ourselves.
+		if (unlikely(victim == myWorkerId)) continue;
 
-	poped = queues[victim]->popTop(&fiber);
-	if (poped) {
-		if constexpr (emper::STATS) {
-			auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::stolen);
-			fiber->setFlag(flag);
-		}
+		poped = queues[victim]->popTop(&fiber);
+		if (poped) {
+			if constexpr (emper::STATS) {
+				auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::stolen);
+				fiber->setFlag(flag);
+			}
 
-		return fiber;
+			return fiber;
+		}
 	}
 
-	// TODO: Reduce pressure on mainThreadQueue by only checking every N-th time.
-
 	// Try the "scheduled from anywhere" queue to get work as last resort.
 	fiber = dequeFiberFromAnywhereQueue();
 	if (fiber) {
diff --git a/emper/strategies/ws/WsScheduler.cpp b/emper/strategies/ws/WsScheduler.cpp
index 2cb8a1d1..720a99a5 100644
--- a/emper/strategies/ws/WsScheduler.cpp
+++ b/emper/strategies/ws/WsScheduler.cpp
@@ -54,6 +54,8 @@ auto WsScheduler::nextFiber() -> Fiber* {
 		return fiber;
 	}
 
+	// TODO: The code below is nearly duplicated, besides the stats
+	// part, in LawsScheduler, deduplicate.
 	const workerid_t myWorkerId = Runtime::getWorkerId();
 	const workerid_t workerCount = runtime.getWorkerCount();
 	workerid_t startWorkerId = Runtime::rand() % workerCount;
-- 
GitLab