From 7cb1a82826e92462df199ecbf635fb5658b9abfd Mon Sep 17 00:00:00 2001 From: Florian Fischer <florian.fischer@muhq.space> Date: Fri, 2 Jul 2021 16:58:31 +0200 Subject: [PATCH] [Runtime] use pthread_getaffinity_np to determine default worker count The value reported by std::thread::hardware_concurrency() can be more than the available CPUs to the current process for example if EMPER runs in a container or qemu. GNU nproc(1) does the right thing and we can take inspiration from them. The solution is to use pthread_getaffinity_np which fills a CPU set with all CPU a pthread can be scheduled on. We use this more precise CPU count if possible. --- emper/Runtime.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index 5ab9afc2..14a68bf8 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -264,6 +264,23 @@ auto Runtime::getDefaultWorkerCount() -> workerid_t { return static_cast<workerid_t>(workerCountInt); } + // The CPU count reported by sysconf(_SC_NPROCESSORS_ONLN), sysconf(_SC_NPROCESSORS_CONF) + // or std::thread::hardware_concurrency() may not match the CPU count available + // to the emper process. + // This can happen for example if we run EMPER in a container or qemu.o + // GNU nproc(1) does report the correct CPU count using pthread_getaffinity_np + // which fills a cpu_set with the CPUs the current process can be scheduled on + // therefore we use this more precise CPU count if possible. + // Code inspiration taken from: + // https://github.com/coreutils/gnulib/blob/90e79512d8b385801218d6e9c4d88ff77186560b/lib/nproc.c#L206 + cpu_set_t set; + if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0) { + unsigned long count = CPU_COUNT(&set); + if (count > 0) { + return count; + } + } + return std::thread::hardware_concurrency(); } -- GitLab