Repository navigation
Tracking Issue for #![feature(available_parallelism)] #74479
Copy link
Copy link
Closed
Labels
A-concurrencyArea: ConcurrencyArea: ConcurrencyB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.Libs-SmallLibs issues that are considered "small" or self-containedLibs issues that are considered "small" or self-containedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.This issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.The final comment period is finished for this PR / Issue.
Description
The feature gate for the issue is #![feature(available_parallelism)].
This is a tracking issue for std::thread::available_parallelism; a portable API to determine how many threads to spawn in order to ensure a program can make use of all available parallelism available on a machine.
Public API
#![feature(available_parallelism)]
use std::thread;
fn main() -> std::io::Result<()> {
let count = thread::available_parallelism()?.get();
assert!(count >= 1);
Ok(())
}Tasks
- Resolve discussion on naming.
- Resolve discussion on function signature.
- Resolve discussion on terminology.
- Add support for externally-set limits on Linux (ref).
- Add support for externally-set limits on Windows (ref).
- Update documentation to remove mentions of "hardware" (ref).
- Smooth out the docs example.
Notes on Platform-specific behavior
available_parallelism is (for now) only considered a hint. The following platform limitations exist:
- On Windows the available concurrency may be undercounted when exceeding 64 threads Add
std::thread::available_concurrency#74480 (comment) - On Windows the available concurrency may be overcounted when limited by a process wide affinity mask or job object limitations Add
std::thread::available_concurrency#74480 (comment) - On Linux the available concurrency may be overcounted in the face of cgroup limits and task-wise affinity masks Add
std::thread::available_concurrency#74480 (comment)
Implementation history
- Add
std::thread::available_concurrency#74480 - Move
available_concurrencyimplementation tosys#85182 - Make
std::thread::available_concurrencysupport process-limited number of CPUs #89310 - Rename
std::thread::available_conccurrencytostd::thread::available_parallelism#89324 - Use cgroup quotas for calculating
available_parallelism#92697 - Add cgroupv1 support to available_parallelism #97925
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-concurrencyArea: ConcurrencyArea: ConcurrencyB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.Libs-SmallLibs issues that are considered "small" or self-containedLibs issues that are considered "small" or self-containedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.This issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.The final comment period is finished for this PR / Issue.
Activity
[-]Tracking Issue for #![feature(hardware_threads)][/-][+]Tracking Issue for #![feature(available_concurrency)][/+]yoshuawuyts commentedon Sep 16, 2020
A fix for the linux undercounting exists in
num_cpuswhich is license-compatible with the compiler. I believe the fix boils down to including this conditional for the linux detection code:cc/ @luser
the8472 commentedon Sep 16, 2020
@yoshuawuyts that would be insufficient due to cgroup CPU quotas which gets your entire cgroup frozen until the next time slice when the quota is used up. docker and other containerization services makes heavy use of that for resource allocation.
One can and other runtimes (e.g. java) do calculate the equivalent of available full-time cpu-cores per time slice from the quotas.
see https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
Rollup merge of rust-lang#74480 - yoshuawuyts:hardware_threads, r=dto…
Auto merge of rust-lang#74480 - yoshuawuyts:hardware_threads, r=dtolnay
strohel commentedon Oct 27, 2020
I would suggest that taking into account Linux a) cpusets (#74479 (comment)) and b) cgroup cpu bandwidth limits (#74479 (comment)) are considered blockers of stabilization of available_concurrency.
Rationale: the change b) in num_cpus was a source of significant CPU efficiency gains and potential memory savings in cloud-based environments. If available_concurrency is stabilized, then it is expected people will migrate to it from
num_cpus. That would currently cause a regression.This is complicated by the fact that associating "Kubernetes CPU limits" with "cgroups" and https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt is non-trivial as there are abstraction layers between them. (so people may not be aware of this even in the presence of documentation on available_concurrency)
The fix can also be to include some
num_cpuscode, but the cgroups part is more substantial than the cpusets one.yoshuawuyts commentedon Oct 27, 2020
@strohel I definitely agree we should support cpusets before stabilizing: we may currently over-report concurrency in containers which is something that should be fixed.
But I'm less sure about cgroup cpu bandwidth limits. If I'm understanding #74479 (comment) this would cause the reported number of CPUs to fluctuate during the runtime of the program. I believe this may cause issues when used in examples like the following:
If the boot sequence of a program is CPU-intensive, by the time the thread pool is initialized the CPU quota may have been expended. Which means that the thread pool may set a limit lower than the max supported concurrency for the program, causing an overall under-utilization of resources.
It would seem that the right use of a bandwidth-aware API would be to periodically update the concurrency. Not to statically initialize it once since that risks under-utilization if the quota is at a low. Did I interpret this accurately?
edit: On closer reading I think I may have indeed misinterpreted. The
quotavalue is statically set, and not constantly updated during a program's runtime. Which means it can indeed be used to calculate the max concurrency and does not need to be updated in a loop. If this is indeed the case, I agree we should account for this.strohel commentedon Oct 27, 2020
@yoshuawuyts I see you've just edited the comment; the clarification is correct.
It is true the one can change CPU quota of a running program, but the same AFAIK holds about cpu sets. Linux even supports runtime physical CPU hotplugging. That's a non-issue, the API can do nothing about it (beyond mentioning in the docs). Caching of the value is problematic for this reason.
the8472 commentedon Oct 27, 2020
Perhaps my post was not clear. There is a quota-configuration which you can read from sysfs (as quota per interval and interval length) and the runtime depletion of the quota. The depletion is dynamic, but the configuration does not change unless someone explicitly reconfigures them.
available_concurrency()would be based on the configuration, not the remaining quota available in the current time slice.51 remaining items
Rollup merge of rust-lang#92697 - the8472:cgroups, r=joshtriplett
Rollup merge of rust-lang#92697 - the8472:cgroups, r=joshtriplett
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.
Make runtime and worker threads configurable for actix and tokio.