检测 Python 中*可用* CPU 数量的便携式方法
Portable way of detecting number of *usable* CPUs in Python
根据这个问题和答案————某些系统上 Python 的 multiprocessing.cpu_count()
函数的输出反映了 中活跃的 CPU 数量使用 ,而不是调用 Python 程序实际 可用 的 CPU 数量。
一个常见的Python习惯用法是使用cpu_count()
的return值来初始化Pool
中的进程数。但是,在使用这种 "dynamic CPU activation" 策略的系统上,该惯用语会严重中断(至少在相对静止的系统上)。
是否有一些直接(且便携)的方法来获取可用处理器的数量(相对于当前使用的数量) 来自 Python?
备注:
How to find out the number of CPUs using python 的公认答案未回答此问题,因为如 此 问题顶部链接的问题所述,打印 /proc/self/status
的内容显示程序可以使用所有 4 个内核。
在我看来,"portable" 排除了任何涉及解析 /proc/self/status
内容的方法,其格式可能因 Linux 版本的不同而不同,并且它甚至不存在于 OS X 上。(同样适用于任何其他伪文件。)
我不认为你会得到任何真正便携的答案,所以我会给出一个正确的答案。
Linux 的正确* 答案是 len(os.sched_getaffinity(pid))
,其中 pid
对于当前进程可能是 0
。此功能在 Python 3.3 及更高版本中公开;如果你更早需要它,你将不得不做一些花哨的 cffi
编码。
编辑:您可以尝试看看是否可以使用函数 int omp_get_num_procs();
如果它存在,这是我在 this question 上找到的唯一有意义的答案,但我还没有从 Python.
使用 psutil:
来自文档 https://psutil.readthedocs.io/en/latest/:
>>> import psutil
>>> psutil.cpu_count()
4
>>> psutil.cpu_count(logical=False) # Ignoring virtual cores
2
这是便携式的
这是一种方法,可以在实现 sched_getaffinity
和 Windows:
的系统上获取当前进程的可用 CPU 内核数
import ctypes
import ctypes.wintypes
import os
from platform import system
def num_available_cores() -> int:
if hasattr(os, 'sched_getaffinity'):
return len(os.sched_getaffinity(0))
elif system() == 'Windows':
kernel32 = ctypes.WinDLL('kernel32')
DWORD_PTR = ctypes.wintypes.WPARAM
PDWORD_PTR = ctypes.POINTER(DWORD_PTR)
GetCurrentProcess = kernel32.GetCurrentProcess
GetCurrentProcess.restype = ctypes.wintypes.HANDLE
GetProcessAffinityMask = kernel32.GetProcessAffinityMask
GetProcessAffinityMask.argtypes = (ctypes.wintypes.HANDLE, PDWORD_PTR, PDWORD_PTR)
mask = DWORD_PTR()
if not GetProcessAffinityMask(GetCurrentProcess(), ctypes.byref(mask), ctypes.byref(DWORD_PTR())):
raise Exception("Call to 'GetProcessAffinityMask' failed")
return bin(mask.value).count('1')
else:
raise Exception('Cannot determine the number of available cores')
在 Linux 和任何其他实现 sched_getaffinity
的系统上,我们使用 Python 的内置包装器。
在 Windows 我们使用 ctypes
to call GetProcessAffinityMask
。
据我所知,在 macOS 上 get/set CPU 亲和力没有用户 API 或工具。在大多数情况下,os.cpu_count()
可以正常工作,但如果您确实需要 可用 个核心数,您可能就不走运了。
根据这个问题和答案——multiprocessing.cpu_count()
函数的输出反映了 中活跃的 CPU 数量使用 ,而不是调用 Python 程序实际 可用 的 CPU 数量。
一个常见的Python习惯用法是使用cpu_count()
的return值来初始化Pool
中的进程数。但是,在使用这种 "dynamic CPU activation" 策略的系统上,该惯用语会严重中断(至少在相对静止的系统上)。
是否有一些直接(且便携)的方法来获取可用处理器的数量(相对于当前使用的数量) 来自 Python?
备注:
How to find out the number of CPUs using python 的公认答案未回答此问题,因为如 此 问题顶部链接的问题所述,打印
/proc/self/status
的内容显示程序可以使用所有 4 个内核。在我看来,"portable" 排除了任何涉及解析
/proc/self/status
内容的方法,其格式可能因 Linux 版本的不同而不同,并且它甚至不存在于 OS X 上。(同样适用于任何其他伪文件。)
我不认为你会得到任何真正便携的答案,所以我会给出一个正确的答案。
Linux 的正确* 答案是 len(os.sched_getaffinity(pid))
,其中 pid
对于当前进程可能是 0
。此功能在 Python 3.3 及更高版本中公开;如果你更早需要它,你将不得不做一些花哨的 cffi
编码。
编辑:您可以尝试看看是否可以使用函数 int omp_get_num_procs();
如果它存在,这是我在 this question 上找到的唯一有意义的答案,但我还没有从 Python.
使用 psutil:
来自文档 https://psutil.readthedocs.io/en/latest/:
>>> import psutil
>>> psutil.cpu_count()
4
>>> psutil.cpu_count(logical=False) # Ignoring virtual cores
2
这是便携式的
这是一种方法,可以在实现 sched_getaffinity
和 Windows:
import ctypes
import ctypes.wintypes
import os
from platform import system
def num_available_cores() -> int:
if hasattr(os, 'sched_getaffinity'):
return len(os.sched_getaffinity(0))
elif system() == 'Windows':
kernel32 = ctypes.WinDLL('kernel32')
DWORD_PTR = ctypes.wintypes.WPARAM
PDWORD_PTR = ctypes.POINTER(DWORD_PTR)
GetCurrentProcess = kernel32.GetCurrentProcess
GetCurrentProcess.restype = ctypes.wintypes.HANDLE
GetProcessAffinityMask = kernel32.GetProcessAffinityMask
GetProcessAffinityMask.argtypes = (ctypes.wintypes.HANDLE, PDWORD_PTR, PDWORD_PTR)
mask = DWORD_PTR()
if not GetProcessAffinityMask(GetCurrentProcess(), ctypes.byref(mask), ctypes.byref(DWORD_PTR())):
raise Exception("Call to 'GetProcessAffinityMask' failed")
return bin(mask.value).count('1')
else:
raise Exception('Cannot determine the number of available cores')
在 Linux 和任何其他实现 sched_getaffinity
的系统上,我们使用 Python 的内置包装器。
在 Windows 我们使用 ctypes
to call GetProcessAffinityMask
。
据我所知,在 macOS 上 get/set CPU 亲和力没有用户 API 或工具。在大多数情况下,os.cpu_count()
可以正常工作,但如果您确实需要 可用 个核心数,您可能就不走运了。