22#ifndef PECLET_CORE_COMMON_CPU_BUDGET_HPP
23#define PECLET_CORE_COMMON_CPU_BUDGET_HPP
44 if (sched_getaffinity(0,
sizeof(set), &set) == 0)
45 return CPU_COUNT(&set);
52 std::ifstream in(path);
54 if (in && std::getline(in, line))
61inline std::string
cgroupPath(
const std::string& procSelfCgroup,
const std::string& controller) {
62 std::ifstream in(procSelfCgroup);
64 while (std::getline(in, line)) {
66 const auto c1 = line.find(
':');
67 if (c1 == std::string::npos)
69 const auto c2 = line.find(
':', c1 + 1);
70 if (c2 == std::string::npos)
72 const std::string ctrl = line.substr(c1 + 1, c2 - c1 - 1);
73 const std::string path = line.substr(c2 + 1);
74 if (controller.empty()) {
77 }
else if (ctrl.find(controller) != std::string::npos) {
90 if (!(in >> quota >> period) || quota ==
"max" || period <= 0)
92 const long q = std::strtol(quota.c_str(),
nullptr, 10);
93 return q > 0 ?
static_cast<int>((q + period - 1) / period) : 0;
98 const long q = std::strtol(
readFirstLine(dir +
"/cpu.cfs_quota_us").c_str(),
nullptr, 10);
99 const long p = std::strtol(
readFirstLine(dir +
"/cpu.cfs_period_us").c_str(),
nullptr, 10);
100 if (q <= 0 || p <= 0)
102 return static_cast<int>((q + p - 1) / p);
107inline int cgroupQuota(
const std::string& cgroupRoot,
const std::string& procSelfCgroup) {
109 const auto tighten = [&best](
int n) {
110 if (n > 0 && (best == 0 || n < best))
115 std::string path =
cgroupPath(procSelfCgroup,
"");
120 const auto slash = path.rfind(
'/');
121 path = (slash == std::string::npos) ? std::string{} : path.substr(0, slash);
130 const auto slash = path.rfind(
'/');
131 path = (slash == std::string::npos) ? std::string{} : path.substr(0, slash);
143 int n = affinity > 0 ? affinity : quota;
144 if (quota > 0 && (n == 0 || quota < n))
146 return std::max(1, n);
173 if (
const char* v = std::getenv(
"KOKKOS_NUM_THREADS"); v && *v)
175 if (
const char* v = std::getenv(
"OMP_NUM_THREADS"); v && *v) {
176 if (hostBackendSizesItself)
178 if (
const int n = std::atoi(v); n > 0)
184 if (!hostBackendSizesItself)
187 return (affinity > 0 && usable < affinity) ? usable : 0;
std::string cgroupPath(const std::string &procSelfCgroup, const std::string &controller)
The cgroup path of this process for controller ("" = the v2 unified hierarchy), e....
int quotaFromCfs(const std::string &dir)
The same for cgroup v1's pair of files in dir. 0 = no limit here.
int cgroupQuota(const std::string &cgroupRoot, const std::string &procSelfCgroup)
The tightest CPU quota binding this process, walking from its own cgroup up to the root.
int quotaFromCpuMax(const std::string &file)
CPUs allowed by one cgroup-v2 cpu.max file ("max 100000" or "200000 100000"), rounded UP so a fractio...
int affinityCpus()
CPUs in this process's affinity mask, or 0 if that cannot be determined.
std::string readFirstLine(const std::string &path)
First whitespace-separated fields of a file, or an empty string if it cannot be read.
int defaultHostThreads(bool hostBackendSizesItself)
The host thread count to hand a backend that has not been told one, or 0 for "say nothing".
int usableCpus()
How many CPUs this process may actually use: the affinity count, lowered by any cgroup quota binding ...