mstar.utils.cpus#
The CPUs this process may use, and the plan every process of a deployment reads.
os.cpu_count() reports the host’s CPUs. In a container the cgroup CPU quota
can be far smaller, and a thread pool sized to the host then runs more threads
than the quota lets run, so a fork-join op waits on whichever thread the
scheduler parked.
CpuPlan holds the process mask, how many of its CPUs the quota lets run,
the CPUs the step_thread_core knob pins (each worker’s step threads and the
API server’s result threads, see mstar.utils.threads), and the pool sizes,
taken from the CPUs left after those. The API server and every worker build it
with deployment_plan from the same inputs (the knob, the mask, the
deployment’s devices), so they agree on it without talking.
Placement under auto is by the device’s rank among the host’s GPUs on its
NUMA node, as sysfs lists them (every GPU of the host, not only the ones this
process was given), so servers on different GPUs pick different CPUs without
knowing about each other. A worker takes the core at its device’s rank from the
bottom of the node’s allowed CPUs, the API server the core at its first
device’s rank from the top, so the cores a GPU picks from must hold two per GPU
or auto pins nothing. Servers on one GPU can’t be told apart that way, so
the first holds a lock on it (claim_gpus) and the next pins nothing.
Functions
|
The tightest cgroup v2 |
|
Hold a lock on each GPU for the life of this process; if one can't be had, hold none of them and say why. |
|
The plan for a deployment whose workers' devices sit at PCI |
|
The PCI address of each worker's device ( |
|
|
|
|
|
The host's GPUs in PCI address order: the functions with the vendor and class of the device at |
|
Make |
|
The CPUs in a list such as |
|
This process's plan: the one |
The CPUs this process may run on; every CPU where affinity is unknown. |
|
|
The hardware threads of |
CPUs this process may run on (its affinity, else |
Classes
|
See the module docstring. |
|
One of the host's GPUs as sysfs lists it: its PCI address, NUMA node and the node's CPUs (None where sysfs doesn't say). |
|
The CPUs one worker's main, GPU and plan threads share (one core's hardware threads in the mask), and how they were chosen, for the log. |
Exceptions
A |
- class mstar.utils.cpus.CpuPlan(mask, usable, workers=(), result=None, why='step_thread_core off')[source]#
Bases:
objectSee the module docstring.
workershas one entry per worker of the deployment, in the conductor’s worker order (empty, or all None, when nothing is pinned).- Parameters:
- property copy_workers: int#
Threads a large output read copies over (
host_copy.HostCopier): one encode’s share of the CPUs left. Reads run one at a time on the data worker’s thread, each ahead of its own encode.
- property encode_workers: int#
Outputs the data worker encodes at once. A PNG deflates on
png_threadsof its own, so the pool times that stays within the CPUs left.
- property left: int#
what the pools are sized from.
- Type:
The CPUs the quota lets run, less the pinned ones
- exception mstar.utils.cpus.CpuPlanError[source]#
Bases:
ValueErrorA
step_thread_corevalue the process mask can’t honour.
- class mstar.utils.cpus.HostGpu(address, node, local)[source]#
Bases:
NamedTupleOne of the host’s GPUs as sysfs lists it: its PCI address, NUMA node and the node’s CPUs (None where sysfs doesn’t say).
- class mstar.utils.cpus.StepCpus(cpus, why)[source]#
Bases:
NamedTupleThe CPUs one worker’s main, GPU and plan threads share (one core’s hardware threads in the mask), and how they were chosen, for the log.
- mstar.utils.cpus.cgroup_cpu_quota(root=_CGROUP_ROOT, proc_cgroup='/proc/self/cgroup')[source]#
The tightest cgroup v2
cpu.maxquota over this process’s cgroup and its ancestors, in CPUs; None when no level sets one (or cgroup v2 is absent).
- mstar.utils.cpus.claim_gpus(addresses)[source]#
Hold a lock on each GPU for the life of this process; if one can’t be had, hold none of them and say why.
autodepends only on the PCI address and the mask, so two servers on one GPU (two MIG instances report one address) would take the same CPUs. The kernel drops anflockhowever the process exits, so a dead server leaves nothing to clean up. The file is never unlinked: another process may already hold an fd on this inode, and removing it would let a third lock a different one. The lock only reaches servers that share_GPU_LOCK_DIR.
- mstar.utils.cpus.deployment_plan(setting, addresses, *, mask=None, usable=None, pci_root=_PCI_DEVICES, siblings=smt_siblings)[source]#
The plan for a deployment whose workers’ devices sit at PCI
addresses, in the conductor’s worker order (None for a device sysfs doesn’t place, such as a CPU worker; onlyautoreads them).offpins nothing. A CPU number is the first worker’s CPU; the next workers take the next cores above it, and the API server the last core of the mask; a number outside the mask, or too near its top for every worker, raisesCpuPlanError.autoplaces by device rank (module docstring), and pins nothing, saying why inCpuPlan.why, when the mask is too small. Either way at least one CPU of the mask stays unpinned.
- mstar.utils.cpus.device_addresses(devices)[source]#
The PCI address of each worker’s device (
cuda:1); None for a CPU worker, or where the platform doesn’t report one.
- mstar.utils.cpus.devices_plan(setting, devices)[source]#
deployment_planfor the workers’ device strings, in the conductor’s worker order: the same call in the API server and in every worker.
- mstar.utils.cpus.host_gpus(like, root=_PCI_DEVICES)[source]#
The host’s GPUs in PCI address order: the functions with the vendor and class of the device at
like(0000:40:00.0). Every process on the host sees the same list, whatever GPUs it was given; empty without sysfs.
- mstar.utils.cpus.install(new)[source]#
Make
newthis process’s plan (None: back to nothing pinned).- Parameters:
new (CpuPlan | None)
- Return type:
None
- mstar.utils.cpus.parse_cpu_list(text)[source]#
The CPUs in a list such as
0-3,8,10-11(as sysfs andtasksetwrite them); empty for an empty string.
- mstar.utils.cpus.plan()[source]#
This process’s plan: the one
installset, else nothing pinned.- Return type:
- mstar.utils.cpus.process_mask()[source]#
The CPUs this process may run on; every CPU where affinity is unknown.