From 0bf062abb9704f20cab7a99e9e7c4b170e01c7c1 Mon Sep 17 00:00:00 2001 From: Florian Fischer <florian.fischer@muhq.space> Date: Wed, 28 Apr 2021 22:00:43 +0200 Subject: [PATCH] [Runtime] override pinning behavior by setting EMPER_PIN_WORKERS environment variable --- emper/Runtime.cpp | 22 +++++++++++++++------- emper/Runtime.hpp | 8 +++++++- emper/lib/env.hpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 emper/lib/env.hpp diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index 8798bc84..cadd6ed4 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -102,10 +102,16 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory } } + bool pinWorkers = shouldPinWorkers(); + // Core id we start the worker pinning workerid_t pinningOffset = 0; char* pinningOffsetEnv = std::getenv("EMPER_PINNING_OFFSET"); if (pinningOffsetEnv) { + if (!pinWorkers) { + DIE_MSG("EMPER_PIN_WORKERS=false and EMPER_PINNING_OFFSET are mutual exclusive"); + } + int pinningOffsetInt = std::stoi(pinningOffsetEnv); if (pinningOffsetInt > UINT8_MAX) { DIE_MSG("Pinning offset " << pinningOffsetInt << " to big for its datatype"); @@ -118,14 +124,16 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory errno = pthread_attr_init(&attr); if (errno) DIE; - // Start non portable. - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET((i + pinningOffset) % nprocs, &cpuset); + if (pinWorkers) { + // Start non portable. + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET((i + pinningOffset) % nprocs, &cpuset); - errno = pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset); - if (errno) DIE_MSG_ERRNO("pthread_attr_setaffinity_np() failed"); - // End non portable. + errno = pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset); + if (errno) DIE_MSG_ERRNO("pthread_attr_setaffinity_np() failed"); + // End non portable. + } // This is not done by each thread individually because the randomEngine is // mutated and therefore produces data races. diff --git a/emper/Runtime.hpp b/emper/Runtime.hpp index 0837ec35..1fc424eb 100644 --- a/emper/Runtime.hpp +++ b/emper/Runtime.hpp @@ -11,6 +11,7 @@ #include <functional> // for function #include <memory> #include <mutex> +#include <optional> #include <random> #include <vector> // for vector @@ -20,7 +21,8 @@ #include "NextFiberResult.hpp" #include "Scheduler.hpp" // for Scheduler #include "Worker.hpp" -#include "emper-common.h" // for workerid_t +#include "emper-common.h" // for workerid_t +#include "lib/env.hpp" #include "lib/sync/Latch.hpp" // for Latch #include "lib/sync/Semaphore.hpp" #include "sleep_strategy/WorkerSleepStrategy.hpp" @@ -83,6 +85,10 @@ class Runtime : public Logger<LogSubsystem::RUNTI> { static auto getDefaultWorkerCount() -> workerid_t; + static auto shouldPinWorkers() -> bool { + return emper::lib::env::getBoolFromEnv("EMPER_PIN_WORKERS").value_or(true); + } + protected: void addNewWorkerHook(const std::function<void(workerid_t)>& hook) { newWorkerHooks.push_back(hook); diff --git a/emper/lib/env.hpp b/emper/lib/env.hpp new file mode 100644 index 00000000..65b6c4fc --- /dev/null +++ b/emper/lib/env.hpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright © 2021 Florian Fischer +#pragma once + +#include <string> + +#include "Debug.hpp" + +namespace emper::lib::env { + +static auto getBoolFromEnv(const std::string&& key) -> std::optional<bool> { + DBG("parse " << key << " environment variable"); + char* envVar = std::getenv(key.c_str()); + if (!envVar) { + return std::nullopt; + } + + std::string envStr(envVar); + if (envStr == "true") { + return true; + } + + if (envStr == "false") { + return false; + } + + DIE_MSG(key << " has invalid value: " << envStr << " (expected true or false)"); +} + +} // namespace emper::lib::env -- GitLab