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

问题描述 投票:1回答:3

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

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)

版本:

  • Python 3.6
  • joblib 0.13.2
  • scikit-learn 0.20.2
  • numpy 1.16.2

更新:不起作用。谢谢你澄清@Darkonaut。可悲的是,我已经知道这不起作用,我已经清楚地在问题标题上说明了但人们不读我猜。我想我做错了。我已根据@Ben Chaliah Ayoub answer更新了代码片段。似乎没有任何改变。而且我还想指出一些事情:我不是试图在多个核心上运行此代码。这行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之前在我的代码中使用this设置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-3.x unix multiprocessing python-multiprocessing
3个回答
5
投票

如果要限制使用的核心数,则使用multiprocessing.Pool,它根据系统上可用的最大内核数生成工作进程池,然后在核心可用时基本上提供任务:

pool= Pool(processes=(multiprocessing.cpu_count() - 1))

nice也是降低流程优先级的好方法:

from multiprocessing import Pool, cpu_count
import math, os, psutil, platform


def foo(x):
    return math.cos(x)

def limit_cpu():
    p = psutil.Process(os.getpid())
    if platform.system() == 'Linux':
        p.nice(19)
    elif platform.system() == 'Windows':
        p.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS)


if __name__ == '__main__':
    pool = Pool(None, limit_cpu)
    for p in pool.imap(foo, range(10**8)):
        pass

如果您想确保该流程不占用100%的核心:

from time import sleep
def foo(x):
    sleep(0.01)
    return math.sqrt(x)

这将使您的操作系统schedule out成为每次计算的0.01秒的过程,并为其他应用程序腾出空间。

你可以在PCA里面运行foo


1
投票

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

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)

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

>>>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)]

...意思是我的numpy构建使用OpenBLAS。我需要编写的所有内容都是os.environ["OPENBLAS_NUM_THREADS"] = "2",以便限制numpy库的线程使用。


0
投票

我正在寻找一种方法来限制python脚本CPU使用(不是优先级,但CPU核心数)与python代码。

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

taskset --cpu-list 0,1,2,3 <app>
© www.soinside.com 2019 - 2024. All rights reserved.