From cd06496d2c793961ee3c3927aa719e189f1c1bda Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fischer@muhq.space>
Date: Wed, 10 Nov 2021 18:48:47 +0100
Subject: [PATCH] make the victim count in work-stealing configurable

Add two new mutual exclusive meson_options:
* work_stealing_victim_count: Which sets an absolute number of victims
* work_stealing_victim_denominator: Set victim count to #workers/denominator
---
 emper/Emper.hpp                                    |  4 ++++
 emper/strategies/AbstractWorkStealingScheduler.cpp | 13 +++++++++++--
 meson.build                                        |  8 ++++++++
 meson_options.txt                                  | 12 ++++++++++++
 4 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/emper/Emper.hpp b/emper/Emper.hpp
index 34b0459e..ff3c27f2 100644
--- a/emper/Emper.hpp
+++ b/emper/Emper.hpp
@@ -2,12 +2,16 @@
 // Copyright © 2020-2021 Florian Schmaus
 #pragma once
 
+#include <cstddef>
 #include <string>
 
 #include "emper-config.h"
 
 namespace emper {
 
+static const size_t WS_VICTIM_COUNT = EMPER_WS_VICTIM_COUNT;
+static const size_t WS_VICTIM_DENOMINATOR = EMPER_WS_VICTIM_DENOMINATOR;
+
 static const bool STATS =
 #ifdef EMPER_STATS
 		true
diff --git a/emper/strategies/AbstractWorkStealingScheduler.cpp b/emper/strategies/AbstractWorkStealingScheduler.cpp
index fa954ad6..83ca8769 100644
--- a/emper/strategies/AbstractWorkStealingScheduler.cpp
+++ b/emper/strategies/AbstractWorkStealingScheduler.cpp
@@ -212,8 +212,17 @@ popBottom:
 		const workerid_t checkAnywhereQueueAt = workerCount * CHECK_ANYWHERE_QUEUE_AT_PERCENTAGE;
 
 		workerid_t startWorkerId = currentWorker->nextRandomWorkerId();
-		// TODO: See how reducing the loop bound affects things.
-		for (workerid_t i = 0; i < workerCount; ++i) {
+		// TODO: See how changing the victim count affects things.
+		const workerid_t victimCount = [&] {
+			if constexpr (emper::WS_VICTIM_COUNT)
+				return emper::WS_VICTIM_COUNT;
+			else if constexpr (emper::WS_VICTIM_DENOMINATOR)
+				return workerCount / emper::WS_VICTIM_DENOMINATOR;
+			else
+				return workerCount;
+		}();
+
+		for (workerid_t i = 0; i < victimCount; ++i) {
 			workerid_t victim = (startWorkerId + i) % workerCount;
 
 			// Don't steal from ourselves.
diff --git a/meson.build b/meson.build
index aeaf05dc..570e7856 100644
--- a/meson.build
+++ b/meson.build
@@ -75,6 +75,14 @@ conf_data.set('EMPER_' + locked_unbounded_queue_impl.to_upper() + '_LOCKED_UNBOU
 default_scheduling_strategy = get_option('default_scheduling_strategy')
 conf_data.set('EMPER_DEFAULT_SCHEDULING_STRATEGY_' + default_scheduling_strategy.to_upper(), true)
 
+ws_victim_count = get_option('work_stealing_victim_count')
+ws_victim_denominator = get_option('work_stealing_victim_denominator')
+if ws_victim_count != 0 and ws_victim_denominator !=0
+	error('work_stealing_victim_count and work_stealing_victim_denominator are mutally exclusive')
+endif
+conf_data.set('EMPER_WS_VICTIM_COUNT', ws_victim_count)
+conf_data.set('EMPER_WS_VICTIM_DENOMINATOR', ws_victim_denominator)
+
 log_level = get_option('log_level')
 if log_level == 'automatic'
 	# output only error messages in release builds
diff --git a/meson_options.txt b/meson_options.txt
index 2a6e5627..7eef4ea7 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -93,6 +93,18 @@ option(
   ],
   value: 'work_stealing',
 )
+option(
+  'work_stealing_victim_count',
+  type: 'integer',
+  value: 0,
+  description: 'Absolute count of victims tried in the work-stealing'
+)
+option(
+  'work_stealing_victim_denominator',
+  type: 'integer',
+  value: 0,
+  description: 'Fraction of all workers to steal work from'
+)
 option(
   'overflow_queue',
   type: 'boolean',
-- 
GitLab