Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.4k
gh-109649: Add os.process_cpu_count() function#109907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
e3554fa
to69c8bf4
CompareSee previous discussions: |
Adding a new process_cpu_count() makes it easier to extend the function later for new use cases, instead of modifying the existing os.cpu_count():
About thepid parameter. First, I would like to implement this function on Windows (get process affinity), and then check if it would be possible to get the CPU affinity of another process on Windows, before considering to add apid parameter. |
In psutil, this function is called Process.cpu_affinity():https://psutil.readthedocs.io/en/latest/#psutil.Process.cpu_affinity |
69c8bf4
to7832caa
CompareI prefer adding a new
|
corona10 commentedSep 29, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I will take a look at it by tomorrow! |
Uh oh!
There was an error while loading.Please reload this page.
@gpshead: I updated my PR to reimplement os.process_cpu_count() in Python. |
Uh oh!
There was an error while loading.Please reload this page.
cpu_set=sched_getaffinity(0)num_cpus=cpu_count()returnmin(len(cpu_set),num_cpus)ifcpu_setelsenum_cpus Why do you want to return cpu_count() if it's smaller than len(sched_getaffinity(0))? It should not happen. If it happens, I would prefer to not workaround bugs, but fix the OS instead. For me, it should not happen.
When I added I recall that Python detects broken poll() implementation on macOS. In that case, we go further: weremove the function at runtime! (at Python startup) I prefer to not make assumptions about hypothetical bugs, but wait until we get real concrete bug reports, and then decide how to deal with them. Anyway, thanks for thinking about all corner cases, it's a good thing! |
corona10 commentedSep 30, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
If we pass the -Xcpu_count= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Overall LGTM, for the detail, I will delegate it to@gpshead
I would prefer that the discussion separately the implementation and the expected behavior. Also, can we discussion -Xcpu_count later? This PR is about adding process_cpu_count(), nothing more. |
Doc/library/os.rst Outdated
@@ -5202,6 +5200,17 @@ Miscellaneous System Information | |||
.. availability:: Unix. | |||
.. function:: process_cpu_count() | |||
Get the number of logical CPUs usable by the current process. Returns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It is probably more accurate to say "usable by the calling thread of the current process". I believe each thread can have its own affinity.
(For parallelism planning purposes, the main thread prior to spawning others is likely what people would be calling this from anyways)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sadly, you're right. I updated the doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
One documentation improvement suggested but otherwise good.
@gpshead is right, the number of CPUs is "per thread" in thread. Example: importosimportthreadingdefsched_remove_one_cpu():mask=os.sched_getaffinity(0)mask.pop()os.sched_setaffinity(0,mask)defset_affinity():tid=threading.get_native_id()print(f"thread{tid}: remove a second CPU")sched_remove_one_cpu()print(f"thread{tid}:{os.process_cpu_count()=}")tid=threading.get_native_id()print(f"main thread{tid}: remove a CPU")sched_remove_one_cpu()print(f"main thread{tid} before:{os.cpu_count()=}")print(f"main thread{tid} before:{os.process_cpu_count()=}")print()thread=threading.Thread(target=set_affinity)thread.start()thread.join()print()print(f"main thread{tid} after:{os.cpu_count()=}")print(f"main thread{tid} after:{os.process_cpu_count()=}") Output on Linux:
You can see that the main thread loses a CPU when sched_remove_one_cpu() is called: os.process_cpu_count() is affected, but os.cpu_count() is not affected. When a thread removes a second CPU, it affects os.process_cpu_count() in the thread,but the second CPU removal does not affected the main thread. New thread inherit the mask of the caller thread, but a change in a child thread does not affect the parent thread. Well, that's the expected behavior. |
Uh oh!
There was an error while loading.Please reload this page.
* Refactor os_sched_getaffinity_impl(): move variable definitions to their first assignment.* Fix test_posix.test_sched_getaffinity(): restore the old CPU mask when the test completes!* Doc: Specify that os.cpu_count() counts *logicial* CPUs.* Doc: Specify that os.sched_getaffinity(0) is related to the calling thread.
803f717
to74ed3db
CompareI made a few further changes to clarify differences between cpu_count(), process_cpu_count() and sched_affinity(). |
I created issueGH-110160 for this bug. |
Unrelated CI failures:
|
bedevere-bot commentedSep 30, 2023
|
if you're inclined to do so, the documentation improvements to the existing APIs in this PR would be worthwhile backporting to the 3.12 branch so that they show up on the default /3/ docs on python.org soon. |
It makes sense. I wrote PRgh-110169 for Python 3.12 (and added "backport to 3.11" label). |
* Refactor os_sched_getaffinity_impl(): move variable definitions to their first assignment.* Fix test_posix.test_sched_getaffinity(): restore the old CPU mask when the test completes!* Doc: Specify that os.cpu_count() counts *logicial* CPUs.* Doc: Specify that os.sched_getaffinity(0) is related to the calling thread.
Uh oh!
There was an error while loading.Please reload this page.
📚 Documentation preview 📚:https://cpython-previews--109907.org.readthedocs.build/