我的主要问题在这里发布。由于还没有人给出解决方案,我决定找到一种解决方法。我正在寻找一种方法来限制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)
版本:
- 蟒蛇 3.6
- joblib 0.13.2
- scikit-learn 0.20.2
- numpy 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)
更新:所以,在导入 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)
我正在寻找一种方法来限制 python 脚本 python 代码的 CPU 使用率(不是优先级,而是 CPU 内核的数量)。
使用taskset
或numactl
运行应用程序。
例如,要使您的应用程序仅使用前 4 个 CPU,请执行以下操作:
taskset --cpu-list 0-3 <app>
但是,这些工具将进程限制为使用特定的 CPU,而不是使用的 CPU 总数。为了获得最佳结果,它们要求将这些 CPU 与操作系统进程计划程序隔离,以便计划程序不会在这些 CPU 上运行任何其他进程。否则,如果指定的 CPU 当前正在运行其他线程,而其他 CPU 处于空闲状态,则线程将无法在其他空闲 CPU 上运行,并且必须排队等待这些特定 CPU,这并不理想。
使用cgroups
,您可以将进程/线程限制为使用特定部分的可用 CPU 资源,而不限制特定的 CPU,但cgroups
设置就不那么简单了。
我通过设置 BLAS 环境变量(从此链接)解决了原始问题中给出的示例代码中的问题。我的第一次尝试(第二次更新)是错误的。我需要设置线程数,而不是在导入 numpy 库之前,而是在库 (增量PCA) 导入 numpy.
那么,示例代码中的问题是什么?这不是一个实际的问题,而是numpy库使用的BLAS库的一个功能。尝试使用多处理库限制它不起作用,因为默认情况下 OpenBLAS 设置为使用所有可用的线程.
Credits:@Amir 和 @Darkonaut来源: OpenBLAS 1, OpenBLAS 2, Solution
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)
但是,您可以通过检查哪一个来显式设置正确的 BLAS 环境 由您的 Numpy 构建使用,如下所示:
>>>import numpy as np
>>>np.__config__.show()
给出了这些结果...
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)]
。这意味着OpenBLAS被我的numpy构建使用。我需要编写的只是os.environ["OPENBLAS_NUM_THREADS"] = "2"
以限制 numpy 库的线程使用。