检测 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?

备注:

  1. How to find out the number of CPUs using python 的公认答案未回答此问题,因为如 问题顶部链接的问题所述,打印 /proc/self/status 的内容显示程序可以使用所有 4 个内核。

  2. 在我看来,"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() 可以正常工作,但如果您确实需要 可用 个核心数,您可能就不走运了。