Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit74ed3db

Browse files
committed
gh-109649: Add os.process_cpu_count() function
* 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.
1 parent2c23419 commit74ed3db

File tree

8 files changed

+124
-47
lines changed

8 files changed

+124
-47
lines changed

‎Doc/library/os.rst

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5141,8 +5141,12 @@ operating system.
51415141

51425142
..function::sched_getaffinity(pid, /)
51435143

5144-
Return the set of CPUs the process with PID *pid* (or the current process
5145-
if zero) is restricted to.
5144+
Return the set of CPUs the process with PID *pid* is restricted to.
5145+
5146+
If *pid* is zero, return the set of CPUs the calling thread of the current
5147+
process is restricted to.
5148+
5149+
See also the:func:`process_cpu_count` function.
51465150

51475151

51485152
.. _os-path:
@@ -5183,12 +5187,11 @@ Miscellaneous System Information
51835187

51845188
..function::cpu_count()
51855189

5186-
Return the number of CPUs in the system. Returns ``None`` if undetermined.
5187-
5188-
This number is not equivalent to the number of CPUs the current process can
5189-
use. The number of usable CPUs can be obtained with
5190-
``len(os.sched_getaffinity(0))``
5190+
Return the number of logical CPUs in the **system**. Returns ``None`` if
5191+
undetermined.
51915192

5193+
The:func:`process_cpu_count` function can be used to get the number of
5194+
logical CPUs usable by the calling thread of the **current process**.
51925195

51935196
..versionadded::3.4
51945197

@@ -5202,6 +5205,20 @@ Miscellaneous System Information
52025205
..availability::Unix.
52035206

52045207

5208+
..function::process_cpu_count()
5209+
5210+
Get the number of logical CPUs usable by the calling thread of the **current
5211+
process**. Returns ``None`` if undetermined. It can be less than
5212+
:func:`cpu_count` depending on the CPU affinity.
5213+
5214+
The:func:`cpu_count` function can be used to get the number of logical CPUs
5215+
in the **system**.
5216+
5217+
See also the:func:`sched_getaffinity` functions.
5218+
5219+
..versionadded::3.13
5220+
5221+
52055222
..function::sysconf(name, /)
52065223

52075224
Return integer-valued system configuration values. If the configuration value

‎Doc/whatsnew/3.13.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ opcode
163163
documented or exposed through ``dis``, and were not intended to be
164164
used externally.
165165

166+
os
167+
--
168+
169+
* Add:func:`os.process_cpu_count` function to get the number of logical CPUs
170+
usable by the calling thread of the current process.
171+
(Contributed by Victor Stinner in:gh:`109649`.)
172+
166173
pathlib
167174
-------
168175

‎Lib/os.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,3 +1136,16 @@ def add_dll_directory(path):
11361136
cookie,
11371137
nt._remove_dll_directory
11381138
)
1139+
1140+
1141+
if_exists('sched_getaffinity'):
1142+
defprocess_cpu_count():
1143+
"""
1144+
Get the number of logical CPUs usable by the current process.
1145+
1146+
Return None if indeterminable.
1147+
"""
1148+
returnlen(sched_getaffinity(0))
1149+
else:
1150+
# Just an alias to cpu_count() (same docstring)
1151+
process_cpu_count=cpu_count

‎Lib/test/test_os.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3996,14 +3996,42 @@ def test_oserror_filename(self):
39963996
self.fail(f"No exception thrown by{func}")
39973997

39983998
classCPUCountTests(unittest.TestCase):
3999+
defcheck_cpu_count(self,cpus):
4000+
ifcpusisNone:
4001+
self.skipTest("Could not determine the number of CPUs")
4002+
4003+
self.assertIsInstance(cpus,int)
4004+
self.assertGreater(cpus,0)
4005+
39994006
deftest_cpu_count(self):
40004007
cpus=os.cpu_count()
4001-
ifcpusisnotNone:
4002-
self.assertIsInstance(cpus,int)
4003-
self.assertGreater(cpus,0)
4004-
else:
4008+
self.check_cpu_count(cpus)
4009+
4010+
deftest_process_cpu_count(self):
4011+
cpus=os.process_cpu_count()
4012+
self.assertLessEqual(cpus,os.cpu_count())
4013+
self.check_cpu_count(cpus)
4014+
4015+
@unittest.skipUnless(hasattr(os,'sched_setaffinity'),
4016+
"don't have sched affinity support")
4017+
deftest_process_cpu_count_affinity(self):
4018+
ncpu=os.cpu_count()
4019+
ifncpuisNone:
40054020
self.skipTest("Could not determine the number of CPUs")
40064021

4022+
# Disable one CPU
4023+
mask=os.sched_getaffinity(0)
4024+
iflen(mask)<=1:
4025+
self.skipTest(f"sched_getaffinity() returns less than "
4026+
f"2 CPUs:{sorted(mask)}")
4027+
self.addCleanup(os.sched_setaffinity,0,list(mask))
4028+
mask.pop()
4029+
os.sched_setaffinity(0,mask)
4030+
4031+
# test process_cpu_count()
4032+
affinity=os.process_cpu_count()
4033+
self.assertEqual(affinity,ncpu-1)
4034+
40074035

40084036
# FD inheritance check is only useful for systems with process support.
40094037
@support.requires_subprocess()

‎Lib/test/test_posix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ def test_sched_getaffinity(self):
12051205
@requires_sched_affinity
12061206
deftest_sched_setaffinity(self):
12071207
mask=posix.sched_getaffinity(0)
1208+
self.addCleanup(posix.sched_setaffinity,0,list(mask))
12081209
iflen(mask)>1:
12091210
# Empty masks are forbidden
12101211
mask.pop()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add:func:`os.process_cpu_count` function to get the number of logical CPUs
2+
usable by the calling thread of the current process. Patch by Victor Stinner.

‎Modules/clinic/posixmodule.c.h

Lines changed: 3 additions & 5 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Modules/posixmodule.c

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8133,39 +8133,45 @@ static PyObject *
81338133
os_sched_getaffinity_impl(PyObject*module,pid_tpid)
81348134
/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
81358135
{
8136-
intcpu,ncpus,count;
8136+
intncpus=NCPUS_START;
81378137
size_tsetsize;
8138-
cpu_set_t*mask=NULL;
8139-
PyObject*res=NULL;
8138+
cpu_set_t*mask;
81408139

8141-
ncpus=NCPUS_START;
81428140
while (1) {
81438141
setsize=CPU_ALLOC_SIZE(ncpus);
81448142
mask=CPU_ALLOC(ncpus);
8145-
if (mask==NULL)
8143+
if (mask==NULL) {
81468144
returnPyErr_NoMemory();
8147-
if (sched_getaffinity(pid,setsize,mask)==0)
8145+
}
8146+
if (sched_getaffinity(pid,setsize,mask)==0) {
81488147
break;
8148+
}
81498149
CPU_FREE(mask);
8150-
if (errno!=EINVAL)
8150+
if (errno!=EINVAL) {
81518151
returnposix_error();
8152+
}
81528153
if (ncpus>INT_MAX /2) {
8153-
PyErr_SetString(PyExc_OverflowError,"could not allocate "
8154-
"a large enough CPU set");
8154+
PyErr_SetString(PyExc_OverflowError,
8155+
"could not allocatea large enough CPU set");
81558156
returnNULL;
81568157
}
8157-
ncpus=ncpus*2;
8158+
ncpus*=2;
81588159
}
81598160

8160-
res=PySet_New(NULL);
8161-
if (res==NULL)
8161+
PyObject*res=PySet_New(NULL);
8162+
if (res==NULL) {
81628163
gotoerror;
8163-
for (cpu=0,count=CPU_COUNT_S(setsize,mask);count;cpu++) {
8164+
}
8165+
8166+
intcpu=0;
8167+
intcount=CPU_COUNT_S(setsize,mask);
8168+
for (;count;cpu++) {
81648169
if (CPU_ISSET_S(cpu,setsize,mask)) {
81658170
PyObject*cpu_num=PyLong_FromLong(cpu);
81668171
--count;
8167-
if (cpu_num==NULL)
8172+
if (cpu_num==NULL) {
81688173
gotoerror;
8174+
}
81698175
if (PySet_Add(res,cpu_num)) {
81708176
Py_DECREF(cpu_num);
81718177
gotoerror;
@@ -8177,12 +8183,12 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid)
81778183
returnres;
81788184

81798185
error:
8180-
if (mask)
8186+
if (mask) {
81818187
CPU_FREE(mask);
8188+
}
81828189
Py_XDECREF(res);
81838190
returnNULL;
81848191
}
8185-
81868192
#endif/* HAVE_SCHED_SETAFFINITY */
81878193

81888194
#endif/* HAVE_SCHED_H */
@@ -14333,44 +14339,49 @@ os_get_terminal_size_impl(PyObject *module, int fd)
1433314339
/*[clinic input]
1433414340
os.cpu_count
1433514341
14336-
Return the number of CPUs in the system; return None if indeterminable.
14342+
Return the number oflogicalCPUs in the system.
1433714343
14338-
This number is not equivalent to the number of CPUs the current process can
14339-
use. The number of usable CPUs can be obtained with
14340-
``len(os.sched_getaffinity(0))``
14344+
Return None if indeterminable.
1434114345
[clinic start generated code]*/
1434214346

1434314347
staticPyObject*
1434414348
os_cpu_count_impl(PyObject*module)
14345-
/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
14349+
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
1434614350
{
14347-
intncpu=0;
14351+
intncpu;
1434814352
#ifdefMS_WINDOWS
14349-
#ifdefMS_WINDOWS_DESKTOP
14353+
#ifdefMS_WINDOWS_DESKTOP
1435014354
ncpu=GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
14351-
#endif
14355+
# else
14356+
ncpu=0;
14357+
# endif
14358+
1435214359
#elif defined(__hpux)
1435314360
ncpu=mpctl(MPC_GETNUMSPUS,NULL,NULL);
14361+
1435414362
#elif defined(HAVE_SYSCONF)&& defined(_SC_NPROCESSORS_ONLN)
1435514363
ncpu=sysconf(_SC_NPROCESSORS_ONLN);
14364+
1435614365
#elif defined(__VXWORKS__)
1435714366
ncpu=_Py_popcount32(vxCpuEnabledGet());
14367+
1435814368
#elif defined(__DragonFly__)|| \
1435914369
defined(__OpenBSD__)|| \
1436014370
defined(__FreeBSD__)|| \
1436114371
defined(__NetBSD__)|| \
1436214372
defined(__APPLE__)
14363-
intmib[2];
14373+
ncpu=0;
1436414374
size_tlen=sizeof(ncpu);
14365-
mib[0]=CTL_HW;
14366-
mib[1]=HW_NCPU;
14367-
if (sysctl(mib,2,&ncpu,&len,NULL,0)!=0)
14375+
intmib[2]= {CTL_HW,HW_NCPU};
14376+
if (sysctl(mib,2,&ncpu,&len,NULL,0)!=0) {
1436814377
ncpu=0;
14378+
}
1436914379
#endif
14370-
if (ncpu >=1)
14371-
returnPyLong_FromLong(ncpu);
14372-
else
14380+
14381+
if (ncpu<1) {
1437314382
Py_RETURN_NONE;
14383+
}
14384+
returnPyLong_FromLong(ncpu);
1437414385
}
1437514386

1437614387

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp