GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Support python -Xcpu_count=<n> feature for container environment. · Issue #109595 · python/cpython

Support python -Xcpu_count=<n> feature for container environment. #109595

New issue
Copy link
New issue
Copy link
Closed
Closed
Support python -Xcpu_count=<n> feature for container environment.#109595
Copy link
Assignees
corona10
Labels
3.13only security fixesonly security fixestype-featureA feature request or enhancementA feature request or enhancement

Description

@corona10
corona10
opened on Sep 20, 2023
Issue body actions

Feature or enhancement

As #80235, there are requests for isolating CPU count in k8s or container environment, and this is a very important feature these days. (Practically my corp, a lot of workloads are running under container environments, and controlling CPU count is very important to resolve busy neighborhood issues)

There were a lot of discussions, and following the cgroup spec requires a lot of complexity and performance issues (due to fallback).
JDK 21 chooses not to depend on CPU Shares to compute active processor count and they choose to use -XX:ActiveProcessorCount=<n>.
see: https://bugs.openjdk.org/browse/JDK-8281571

I think that this strategy will be worth using from the CPython side too.
So if the user executes the python with -Xcpu_count=3option os.cpu_count will return 3, instead of the actual CPU count that was calculated from os.cpu_count.

cc @vstinner @indygreg

Linked PRs

  • gh-109595: Add -Xcpu_count=<n> cmdline for container users #109667
  • gh-110649: Update -Xcpu_count=<n> cmdline to support process mode #110639
Reacted by LYK and Ed Morley

Activity

Next
  1. corona10
    self-assigned this
    on Sep 20, 2023
  2. corona10
    added
    type-featureA feature request or enhancementA feature request or enhancement
    3.13only security fixesonly security fixes
    on Sep 20, 2023
  3. vstinner commented on Sep 20, 2023

    @vstinner
    vstinner
    on Sep 20, 2023
    Member
    More actions

    I would prefer to first fix os.cpu_count() to take sched_getaffinity() in account. But we should provide the two values: taking affinity in account, and "total" number of CPUs. It might be tricky to change the default :-(

  4. corona10 commented on Sep 20, 2023

    @corona10
    corona10
    on Sep 20, 2023
    MemberAuthor
    More actions

    It might be tricky to change the default :-(

    Providing -Xcpu_count will not touch any default behavior until the user explicitly set the value. So it will be the expected side-effect from the user side.

    I would prefer to first fix os.cpu_count() to take sched_getaffinity() in account

    We need to understand the actual user's usecase. AFAIK k8s users or container users never use something like taskset to isolate CPU resources. They just write a Docker file and set the resources to k8s pods.
    Even if we update os.cpu_count to reflect sched_getaffinity, it will not be directly helpful to actual container people.

    I think that that's why JDK still provides -XX:ActiveProcessorCount=<n>.
    Until we do not provide a practical way to limit CPU resources, there is no way to reflect os.cpu_count to follow their limitation.
    And as you know, container application is veeeery important use case in modern applications.

  5. vstinner commented on Sep 21, 2023

    @vstinner
    vstinner
    on Sep 21, 2023
    Member
    More actions

    os.cpu_count() is used in other use cases than containers, where CPU affinity is used.

    If we modify cpu_count() to take affinity in account and/or if your -X option is implemented, we should add an option to get "total number of CPUs".

  6. indygreg commented on Sep 21, 2023

    @indygreg
    indygreg
    on Sep 21, 2023
    Contributor
    More actions

    AFAIK k8s users or container users never use something like taskset to isolate CPU resources.

    I have used taskset in Kubernetes. It is useful to pin processes to specific CPU cores without using something more advanced/modern like the CPU Manager feature.

    One of the things I used it for was testing the behavior of a JVM when passing -XX:ActiveProcessorCount= to a different value than the number of CPUs being allowed to schedule on.

    There's also the scenario where you have a container running multiple processes and don't want a process to use all available CPUs. In this scenario, in the absence of [something like] taskset you need something like -XX:ActiveProcessorCount= to forcefully override the default heuristics. (This use case is important for people who realize how inefficient the artificial containers are only 1 process rule is and have chosen to eschew it.)

    Reacted by Donghee Na and LYK
  7. vstinner commented on Sep 21, 2023

    @vstinner
    vstinner
    on Sep 21, 2023
    Member
    More actions

    I created issue #109649: os.cpu_count(): add "affinity" parameter to get the number of "usable" CPUs.

    UPDATE: I renamed the usable parameter to affinity.

    Reacted by Donghee Na
  8. corona10 commented on Sep 21, 2023

    @corona10
    corona10
    on Sep 21, 2023
    MemberAuthor
    More actions

    There's also the scenario where you have a container running multiple processes and don't want a process to use all available CPUs. In this scenario, in the absence of [something like] taskset you need something like -XX:ActiveProcessorCount= to forcefully override the default heuristics. (This use case is important for people who realize how inefficient the artificial containers are only 1 process rule is and have chosen to eschew it.)

    Yeah, this is exactly what I want to say :) Thank you for emphasizing!

  9. corona10
    added a commit that references this issue on Sep 21, 2023

    pythongh-109595: Add -Xcpu_count=<n> cmdline for container users

    41be170
  10. corona10 commented on Sep 22, 2023

    @corona10
    corona10
    on Sep 22, 2023
    MemberAuthor
    More actions

    The reason I don't support cgroup directly is the following reasons.

    • cgroups 've existed even before docker or podman borned: https://docs.kernel.org/admin-guide/cgroup-v1/cgroups.html
    • so there are few variation of representing CPU resources and it makes hard to decide which value that the user want to use
    docker run ... --cpu-shares=512 java .... ==> os::active_processor_count() = 1
    docker run ... --cpu-shares=1024 java ... ==> os::active_processor_count() = 32 (total CPUs on this system)
    docker run ... --cpu-shares=2048 java ... ==> os::active_processor_count() = 2
    
    • It will increase overhead itself to os.cpu_count itself, if we decide to parse cgroup, we need to parse cgroup anyway by default, AFAIK there is no way to avoid this path if we decide to support cgroup as seamless approach to what people really want.
    • Supporting cgroupv2 is much harder than cgroupv1, it will increase the maintenance cost for cpython codebase, and we need to follow up new specifications if cgroupv3 is released.
    • Let's not follow what JDK already tried and failed: https://bugs.openjdk.org/browse/JDK-8281571
    • Adding a new flag to os.cpu_count() will not propagate to all libraries that the program depends on but this solution will do.
  11. indygreg commented on Sep 22, 2023

    @indygreg
    indygreg
    on Sep 22, 2023
    Contributor
    More actions

    Is there an appetite for allowing non-integer / special values to -Xcpu_count= that define the mechanism to derive the CPU count? e.g.

    • -Xcpu_count=system-processor-count would use the equivalent of os.cpu_count() today.
    • -Xcpu_count=cgroups-shares-1024 would read from cgroups cpu.shares and divide by 1024.
    • -Xcpu_count=sched-affinity would compute CPU count from scheduler affinity.

    Obviously we would need to bikeshed the names and behavior bit. But I see this as a potential elegant solution that not only allows forceful count overrides but also allows dynamic derivation using well-defined semantics. It also gives CPython more flexibility to introduce new variants/behavior without breaking backwards compatibility. It seemingly placates all parties.

  12. vstinner commented on Sep 22, 2023

    @vstinner
    vstinner
    on Sep 22, 2023
    Member
    More actions

    -Xcpu_count=sched-affinity would compute CPU count from scheduler affinity.

    As the author of PR #109649, I'm interested by this mode 😁

  13. vstinner commented on Sep 22, 2023

    @vstinner
    vstinner
    on Sep 22, 2023
    Member
    More actions

    It seemingly placates all parties.

    It seems like there is no good default behavior fitting all use cases. Giving more choices should please more people.

  14. vstinner commented on Sep 22, 2023

    @vstinner
    vstinner
    on Sep 22, 2023
    Member
    More actions

    Since you added PYTHONCPUCOUNT env var, the effect of the env var is wider than a single process, child processes are affected as well.

    Can you please add a -X cpu_count value to ignore PYTHONCPUCOUNT: in short, get Python 3.12 behavior (total number of CPUs) when it is really what I want? Maybe it can just be:-X cpu_count=default.

    See my example for a concrete use case: #109652 (comment)

    In the UTF-8 mode, I did something similar: PYTHONUTF8=1 python -X utf8=0 ignores PYTHONUTF8 env var and ensures that the UTF-8 Mode is not enabled to this command.

    Reacted by Donghee Na
  15. 7 remaining items

  16. gpshead commented on Sep 29, 2023

    @gpshead
    gpshead
    on Sep 29, 2023
    Member
    More actions

    I propose to:

    • Add os.process_cpu_count(): PR gh-109649: Add os.process_cpu_count() function #109907
    • Add PYTHONCPUCOUNT=value env var and -X cpu_count=value which overrides os.cpu_count() and os.process_cpu_count() with a number.
    • For use case (B), display the number of system CPUS, I would like to support -X cpu_count=default (affect current process) which overrides PYTHONCPUCOUNT (system wide).

    I like these proposals, they are along the lines of what we can actually accomplish and provide clear concrete results. We're exposing raw os information and allowing the user to override that when they deem appropriate for practical purposes.

    Answering deeper questions such as things pertaining to efficiency vs performance, throughput, latency, Linux cgroup shares, other container configs, cpu hotplug, or what VM cores actually are vs what an underlying hypervisor may be configured to actually schedule "core" processes on... are IMNSHO better left to continually evolving PyPI libraries. Because those are pretty fluid concepts.

    For example, for practical reasons, software may choose to adopt higher level concept libraries such as https://pypi.org/project/threadpoolctl/ which @mdboom mentioned on Discord. Because application processes and libraries are often not isolated and work best if they coordinate which fractions of available compute resources they each use with the other cross-language libraries and processes all being used at once for their common goal. A raw numbers of available logical cores alone can't accomplish that.

    I like most of your "Later, we would consider" proposals (as followup work) - except for the cgroups one: Per the above, I view that as too ill-defined of a concept for us to dictate any mapping of that to "cores" as a stdlib API.

    Reacted by Donghee Na
  17. vstinner commented on Sep 29, 2023

    @vstinner
    vstinner
    on Sep 29, 2023
    Member
    More actions

    I like most of your "Later, we would consider" proposals (as followup work) - except for the cgroups one: Per the above, I view that as too ill-defined of a concept for us to dictate any mapping of that to "cores" as a stdlib API.

    I have mixed feeling about reading cgroups in Python stdlib. What I care the most here is to make sure that with the proposed designed, tomorrow, we can still change our mind, and read cgroups.

    I'm saying that because my first proposition was to add an affinity parameter to os.cpu_count(). It's simple. It's easy. Why not? Well. If tomorrow, we read cgroups, what does it mean? We have to add a second cgroups parameters? Now what? The correct would look like:

    kwargs = {}
    if sys.version_info >= (3, 13):
        kwargs['affinity'] = True
    if sys.version_info >= (3, 14):
        kwargs['cgroups'] = True
    cpu_count = os.cpu_count(**kwargs)

    Hu! That's not convenient.

    I prefer a separated function which has no parameter: process_cpu_count(). It gets CPU affinity if available, or not. If tomorrow we consider reading cgroups, again, it would still fit into "return the number of CPU usable by the current process".

  18. corona10 commented on Sep 30, 2023

    @corona10
    corona10
    on Sep 30, 2023
    MemberAuthor
    More actions

    Yeah, I like the proposal #109595 (comment), it will makes better situation for exceptional environment of Python users :)

  19. corona10
    added 4 commits that reference this issue on Sep 30, 2023

    Merge remote-tracking branch 'upstream/main' into pythongh-109595

    ac5329b

    Merge remote-tracking branch 'upstream/main' into pythongh-109595

    a0cfb21

    Merge remote-tracking branch 'upstream/main' into pythongh-109595

    8daa3b7

    gh-109595: Add -Xcpu_count=<n> cmdline for container users (#109667)

    0362cbf
  20. corona10 commented on Oct 10, 2023

    @corona10
    corona10
    on Oct 10, 2023
    MemberAuthor
    More actions

    FYI, I am preparing -Xcpu_count=process option with the separate PR.

    Reacted by Erlend E. Aasland
  21. vstinner commented on Oct 10, 2023

    @vstinner
    vstinner
    on Oct 10, 2023
    Member
    More actions

    Would you mind to create a separated PR for -Xcpu_count=process?

  22. corona10
    added a commit that references this issue on Oct 10, 2023

    pythongh-109595: Update -Xcpu_count=<n> cmdline to support process mode

    920fb83
  23. corona10
    closed this as completedon Oct 10, 2023
  24. vstinner commented on Oct 10, 2023

    @vstinner
    vstinner
    on Oct 10, 2023
    Member
    More actions

    Follow-up issue: #110649: Add -Xcpu_count=process cmdline mode to redirect os.cpu_count as os.process_cpu_count.

  25. blackliner commented on May 23, 2024

    @blackliner
    blackliner
    on May 23, 2024
    More actions

    did the PYTHONCPUCOUNT env var survive to the main branch? If not, how can I control this behavior from the environment, without touching existing code? (Hoping os.cpu_count() will return the reduced number of cores)

  26. vstinner commented on May 23, 2024

    @vstinner
    vstinner
    on May 23, 2024
    Member
    More actions

    did the PYTHONCPUCOUNT env var survive to the main branch?

    It was added to Python 3.13 (you can test beta1) and it's documented at: https://docs.python.org/dev/using/cmdline.html#envvar-PYTHON_CPU_COUNT

    Reacted by Florian Berchtold
  27. Glyphack
    added a commit that references this issue on Sep 2, 2024

    pythongh-109595: Add -Xcpu_count=<n> cmdline for container users (pyt…

    cb98434
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @corona10
    corona10

Labels

3.13only security fixesonly security fixestype-featureA feature request or enhancementA feature request or enhancement

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.