Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/dask/system.py: 62%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3import math
4import os
5import sys
7try:
8 import psutil
9except ImportError:
10 psutil = None # type: ignore[assignment]
12from dask._compatibility import LINUX
14__all__ = ("cpu_count", "CPU_COUNT")
17def _try_extract_cgroup_cpu_quota():
18 # cgroup v1
19 # The directory name isn't standardized across linux distros, check both
20 for dirname in ["cpuacct,cpu", "cpu,cpuacct"]:
21 try:
22 with open(f"/sys/fs/cgroup/{dirname}/cpu.cfs_quota_us") as f:
23 quota = int(f.read())
24 with open(f"/sys/fs/cgroup/{dirname}/cpu.cfs_period_us") as f:
25 period = int(f.read())
26 return quota, period
27 except Exception:
28 pass
30 # cgroup v2
31 try:
32 with open("/proc/self/cgroup") as f:
33 group_path = f.read().strip().split(":")[-1]
34 if not group_path.endswith("/"):
35 group_path = f"{group_path}/"
36 with open(f"/sys/fs/cgroup{group_path}cpu.max") as f:
37 quota, period = map(int, f.read().split(" "))
38 return quota, period
39 except Exception:
40 pass
42 # No cgroup CPU quota found
43 return None, None
46def cpu_count() -> int:
47 """Get the available CPU count for this system.
49 Takes the minimum value from the following locations:
51 - Total system cpus available on the host.
52 - CPU Affinity (if set)
53 - Cgroups limit (if set)
54 """
55 if sys.version_info >= (3, 13):
56 # Embeds CPU affinity checks
57 count = os.process_cpu_count()
58 elif hasattr(os, "sched_getaffinity"):
59 # https://docs.python.org/3/library/os.html#interface-to-the-scheduler
60 # "only available on some Unix platforms"; neither MacOS nor Windows
61 count = len(os.sched_getaffinity(0))
62 else:
63 # Does not account for CPU affinity.
64 # On exotic alternative Python implementations, it may return None.
65 count = os.cpu_count() or 1
66 assert count
68 # Additional CPU affinity check with psutil.
69 # NOTE: do not limit this to Python <3.13: on Windows,
70 # `psutil.Process().cpu_affinity(value)` does not change the reading of
71 # os.process_cpu_count().
72 if psutil is not None:
73 proc = psutil.Process()
74 if hasattr(proc, "cpu_affinity"):
75 affinity = proc.cpu_affinity()
76 if affinity is not None:
77 assert affinity
78 count = min(count, len(affinity))
80 # Check cgroups if available
81 if LINUX:
82 quota, period = _try_extract_cgroup_cpu_quota()
83 if quota is not None and period is not None:
84 # We round up on fractional CPUs
85 cgroups_count = math.ceil(quota / period)
86 if cgroups_count > 0:
87 count = min(count, cgroups_count)
89 return count
92CPU_COUNT = cpu_count()