如何在没有终端或多处理库的情况下限制 python 脚本使用的 CPU 数量?

Meh*_*edB 8 python unix multiprocessing python-3.x python-multiprocessing

我的主要问题是在这里发布。由于还没有人给出解决方案,我决定找到一种解决方法。我正在寻找一种使用python 代码限制 python 脚本 CPU 使用率(不是优先级,而是 CPU 内核数)的方法。我知道我可以使用多处理库(池等)来做到这一点,但我不是使用多处理运行它的人。所以,我不知道该怎么做。而且我也可以通过终端来做到这一点,但是这个脚本是由另一个脚本导入的。不幸的是,我没有通过终端调用它的奢侈。

tl; dr:如何限制由另一个脚本导入的 python 脚本的CPU 使用率(核心数),我什至不知道为什么它并行运行,而不是通过终端运行它。请检查下面的代码片段。

导致问题的代码片段:

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)

transformer = IncrementalPCA(n_components=7, batch_size=200)

#PARTIAL FIT RUNS IN PARALLEL! GOD WHY?
---------------------------------------
transformer.partial_fit(X[:100, :])
---------------------------------------
X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)
Run Code Online (Sandbox Code Playgroud)

版本:

  • 蟒蛇 3.6
  • 作业库 0.13.2
  • scikit-learn 0.20.2
  • 麻木 1.16.2

更新:不起作用。感谢您澄清@Darkonaut。可悲的是,我已经知道这行不通,我已经在问题标题上明确说明了,但我猜人们不会阅读。 我想我做错了。我已经根据 @Ben Chaliah Ayoub 的回答更新了代码片段。似乎什么都没有改变。而且我还想指出一点:我不是要在多个内核上运行此代码。这条线transformer.partial_fit(X[:100, :])在多个核心上运行(出于某种原因)并且它没有n_jobs或任何东西。另请注意,我的第一个示例和我的原始代码没有用池或类似的东西初始化。我不能首先设置核心数(因为没有这样的地方)。但是现在它有一个位置,但它仍然在多个内核上运行。随意自己测试一下。(下面的代码)这就是我寻找解决方法的原因。

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import numpy as np
from multiprocessing import Pool, cpu_count
def run_this():
    X, _ = load_digits(return_X_y=True)
    #Copy-paste and increase the size of the dataset to see the behavior at htop.
    for _ in range(8):
        X = np.vstack((X, X))
    print(X.shape)
    #This is the exact same example taken from sckitlearn's IncrementalPCA website.
    transformer = IncrementalPCA(n_components=7, batch_size=200)
    transformer.partial_fit(X[:100, :])
    X_transformed = transformer.fit_transform(X)
    print(X_transformed.shape)
pool= Pool(processes=1)
pool.apply(run_this)
Run Code Online (Sandbox Code Playgroud)

更新:因此,在导入 numpy 之前,我尝试在我的代码中使用设置 blas 线程,但它不起作用(再次)。还有其他建议吗?最新阶段的代码可以在下面找到。

学分: @Amir

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import os
os.environ["OMP_NUM_THREADS"] = "1" # export OMP_NUM_THREADS=1
os.environ["OPENBLAS_NUM_THREADS"] = "1" # export OPENBLAS_NUM_THREADS=1
os.environ["MKL_NUM_THREADS"] = "1" # export MKL_NUM_THREADS=1
os.environ["VECLIB_MAXIMUM_THREADS"] = "1" # export VECLIB_MAXIMUM_THREADS=1
os.environ["NUMEXPR_NUM_THREADS"] = "1" # export NUMEXPR_NUM_THREADS=1

import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)
transformer = IncrementalPCA(n_components=7, batch_size=200)

transformer.partial_fit(X[:100, :])

X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)
Run Code Online (Sandbox Code Playgroud)

Max*_*kin 10

我正在寻找一种使用 python 代码限制 python 脚本 CPU 使用率(不是优先级,而是 CPU 内核数)的方法。

使用taskset. 例如,要将使用的 CPU 数量限制为 4,请执行以下操作:

taskset --cpu-list 0,1,2,3 <app>
Run Code Online (Sandbox Code Playgroud)

或者,numactl --physcpubind=cpus做什么taskset等等。


Meh*_*edB 6

我通过设置 BLAS 环境变量(从此链接)解决了原始问题中给出的示例代码中的问题。我的第一次尝试(第二次更新)是错误的。我需要在导入 numpy 库之前而不是在库(IncrementalPCA)导入 numpy 之前设置线程数。
那么,示例代码中存在什么问题呢?这不是一个实际问题,而是 numpy 库使用的 BLAS 库的一个功能。尝试使用多处理库限制它是行不通的,因为默认情况下 OpenBLAS 设置为使用所有可用线程。
鸣谢: @Amir 和 @Darkonaut 来源OpenBLAS 1OpenBLAS 2解决方案

import os
os.environ["OMP_NUM_THREADS"] = "1" # export OMP_NUM_THREADS=1
os.environ["OPENBLAS_NUM_THREADS"] = "1" # export OPENBLAS_NUM_THREADS=1
os.environ["MKL_NUM_THREADS"] = "1" # export MKL_NUM_THREADS=1
os.environ["VECLIB_MAXIMUM_THREADS"] = "1" # export VECLIB_MAXIMUM_THREADS=1
os.environ["NUMEXPR_NUM_THREADS"] = "1" # export NUMEXPR_NUM_THREADS=1
from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA


import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)
transformer = IncrementalPCA(n_components=7, batch_size=200)

transformer.partial_fit(X[:100, :])

X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)
Run Code Online (Sandbox Code Playgroud)

但是您可以通过检查您的 numpy 构建使用哪个环境来显式设置正确的 BLAS 环境,如下所示:

>>>import numpy as np
>>>np.__config__.show()
Run Code Online (Sandbox Code Playgroud)

给出这些结果...

blas_mkl_info:
  NOT AVAILABLE
blis_info:
  NOT AVAILABLE
openblas_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
blas_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_mkl_info:
  NOT AVAILABLE
openblas_lapack_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
Run Code Online (Sandbox Code Playgroud)

...意味着我的 numpy 构建使用了 OpenBLAS。我需要编写的只是os.environ["OPENBLAS_NUM_THREADS"] = "2"为了限制 numpy 库的线程使用。