为什么 scikit-learn 中的 GridSearchCV 会产生如此多的线程

Why GridSearchCV in scikit-learn spawn so many threads

提问人:zyxue 提问时间:9/22/2017 最后编辑:zyxue 更新时间:10/13/2017 访问量:3280

问:

这是我当前正在运行的 GridSearch 的输出,我很好奇发生了什么进程,有些事情我还无法解释。pstree

 ├─bash─┬─perl───20*[bash───python─┬─5*[python───31*[{python}]]]
 │      │                          └─11*[{python}]]
 │      └─tee
 └─bash───pstree

我删除了不相关的东西。大括号表示线。

  • perl 的出现是因为我曾经启动过我的 python 作业。正如你所看到的,确实显示有 20 个进程。parallel -j 2020*
  • 每个 python 进程之前的进程是由于使用 激活了 Anaconda 虚拟环境。bashsource activate venv
  • 在每个 python 进程中,还生成了另外 5 个 python 进程 ()。这是因为我指定了 .5*n_jobs=5GridSearchCV

我的理解到此为止。

问题:谁能解释一下为什么还有另外 11 个 python 线程 () 以及网格搜索,以及 31 个网格搜索作业中每个 5 个 python 线程 () ?11*[{python}]31*[{python}]

更新:添加了调用代码GridSearchCV

Cs = 10 ** np.arange(-2, 2, 0.1)
skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=0)
clf = LogisticRegression()
gs = GridSearchCV(
    clf,
    param_grid={'C': Cs, 'penalty': ['l1'],
                'tol': [1e-10], 'solver': ['liblinear']},
    cv=skf,
    scoring='neg_log_loss',
    n_jobs=5,
    verbose=1,
    refit=True)
gs.fit(Xs, ys)

更新(2017-09-27):

我在 gist 上打包了一个测试代码,以便您有兴趣时可以轻松重现。

我在一台 Mac Pro 和多台 Linux 机器上测试了相同的代码,并重现了@igrinis的结果,但仅限于 Mac Pro。在 linux 机器上,我得到的数字与以前不同,但始终如一。因此,生成的线程数可能取决于 GridSearchCV 的特定数据馈送。

python─┬─5*[python───31*[{python}]]
       └─3*[{python}]

请注意,homebrew/linuxbrew 在 Mac Pro 和 linux 机器上安装的 pstree 是不同的。在这里,我发布了我使用的确切版本:

苹果:

pstree $Revision: 2.39 $ by Fred Hucht (C) 1993-2015
EMail: fred AT thp.uni-due.de

Linux系统:

pstree (PSmisc) 22.20
Copyright (C) 1993-2009 Werner Almesberger and Craig Small

Mac 版本似乎没有显示线程的选项,我认为这可能是为什么在结果中看不到它们的原因。我还没有找到一种在Mac Pro上轻松检查线程的方法。如果您碰巧知道一种方法,请发表评论。

更新 (2017-10-12)

在另一组实验中,我确认设置环境变量会有所不同。OMP_NUM_THREADS

在此之前,有许多(在本例中为 63 个)没有不明确用途的线程生成,如上所述:export OMP_NUM_THREADS=1

bash───python─┬─23*[python───63*[{python}]]
              └─3*[{python}]

这里不使用 linux。.paralleln_jobs=23

之后,没有产生线程,但 3 个 Python 进程仍然存在,我仍然不知道它们的用途。export OMP_NUM_THREADS=1

bash───python─┬─23*[python]
              └─3*[{python}]

我最初遇到因为它会导致我的一些 GridSearchCV 作业出错,错误消息是这样的OMP_NUM_THREADS

OMP: Error #34: System unable to allocate necessary resources for OMP thread:
OMP: System error #11: Resource temporarily unavailable
OMP: Hint: Try decreasing the value of OMP_NUM_THREADS.
python 多线程 scikit-learn 网格搜索

评论

0赞 Gambit1614 9/22/2017
您能否显示带有 GridSearchCV 确切参数值的函数调用?
0赞 zyxue 9/22/2017
@MohammedKashif,请看我添加的代码
0赞 igrinis 9/28/2017
ActivityMonitor 显示 Mac 上的线程数。 1 个进程有 4 个线程,其他 5 个进程只有 1 个线程。
0赞 zyxue 10/12/2017
设置,这可能起到一定作用export OMP_NUM_THREADS=1

答:

4赞 igrinis 9/24/2017 #1

来自文档:sklearn.GridSearchCV

n_jobs:int,默认值=1 要并行运行的作业数。

pre_dispatch:int 或 string,可选 控制在并行执行期间分派的作业数。减少此数字有助于避免在分派的作业数量超过 CPU 可以处理的作业数量时内存消耗激增。此参数可以是: None,在这种情况下,所有作业都会立即创建并生成。将其用于轻量级和快速运行的作业,以避免由于按需生成作业而导致的延迟 int,给出生成的作业总数的确切数量 一个字符串,给出一个表达式作为 n_jobs 的函数,如“2*n_jobs”

如果我正确理解文档,它会生成一堆线程作为网格点的数量,并且只能同时运行。我相信数字 31 是 40 个可能值的某种上限限制。尝试使用参数的值。GridSearchCVn_jobspre_dispatch

我认为另外 11 个线程与它本身无关,因为它显示在同一级别上。我认为这是其他命令的遗留物。GridSearchCV

顺便说一句,我在 Mac 上没有观察到这种行为(只看到 5 个进程生成),因此它可能来自不兼容的库。尝试手动更新。GridSearchCVsklearnnumpy

这是我的输出(为了隐私而删除的部分路径):pstree

 └─┬= 00396 *** -fish
   └─┬= 21743 *** python /Users/***/scratch_5.py
     ├─── 21775 *** python /Users/***/scratch_5.py
     ├─── 21776 *** python /Users/***/scratch_5.py
     ├─── 21777 *** python /Users/***/scratch_5.py
     ├─── 21778 *** python /Users/***/scratch_5.py
     └─── 21779 *** python /Users/***/scratch_5.py

对第二条评论的回答:

这实际上是你的代码。刚刚生成了可分离的一维两类问题:

N = 50000
Xs = np.concatenate( (np.random.random(N) , 3+np.random.random(N)) ).reshape(-1, 1)
ys = np.concatenate( (np.zeros(N), np.ones(N)) )

100k 个样本足以让 CPU 忙了大约一分钟。

评论

0赞 zyxue 9/24/2017
你能展示一下你的输出是什么样子的吗?pstree
0赞 zyxue 9/24/2017
你能也出示你的代码吗?我会尝试重现你的实验
0赞 zyxue 9/27/2017
我在 Mac OS 上重现了您的结果,但我在多台 Linux 机器上测试的完全相同的代码仍然会产生许多线程。我已经在 gist 上发布了我的整个测试代码,请查看更新。
0赞 zyxue 9/28/2017
你能在 Linux 机器上尝试这个实验,看看效果如何吗?
0赞 zyxue 9/30/2017
嗨,@igrinis,你认为你已经弄清楚了原因吗?我倾向于给你赏金,但不确定你的结果是否有资格作为答案。