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

zyx*_*xue 9 python multithreading scikit-learn grid-search

这是pstree我当前运行的GridSearch 的输出,我很想知道正在进行什么过程,还有一些我无法解释的东西.

 ??bash???perl???20*[bash???python???5*[python???31*[{python}]]]
 ?      ?                          ??11*[{python}]]
 ?      ??tee
 ??bash???pstree
Run Code Online (Sandbox Code Playgroud)

我删除了无关的东西.粗括号意味着线程.

  • perl的出现是因为我曾经parallel -j 20开始我的python工作.如您所见,20*确实显示有20个过程.
  • bash每个蟒过程的前处理是由于与水蟒虚拟环境的活化source activate venv.
  • 在每个python进程中,还有另外5个python进程(5*)生成.这是因为我指定n_jobs=5GridSearchCV.

我的理解在此结束.

问题:任何人都可以解释为什么还有另外11个python线程(11*[{python}])以及网格搜索,并且31*[{python}]在5个网格搜索作业中每个都会产生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)
Run Code Online (Sandbox Code Playgroud)

更新(2017-09-27):

我在gist上包含了一个测试代码,如果您感兴趣,可以轻松复制.

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

python???5*[python???31*[{python}]]
       ??3*[{python}]
Run Code Online (Sandbox Code Playgroud)

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

苹果电脑:

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

Linux的:

pstree (PSmisc) 22.20
Copyright (C) 1993-2009 Werner Almesberger and Craig Small
Run Code Online (Sandbox Code Playgroud)

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

更新(2017-10-12)

在另一组实验中,我确认设置环境变量OMP_NUM_THREADS会产生影响.

以前export OMP_NUM_THREADS=1,有许多(在这种情况下为63)线程没有不明确的使用产生如上所述:

bash???python???23*[python???63*[{python}]]
              ??3*[{python}]
Run Code Online (Sandbox Code Playgroud)

parallel这里没有使用linux .n_jobs=23.

之后export OMP_NUM_THREADS=1,没有线程产生,但3个Python进程仍然存在,其使用我仍然没有意识到.

bash???python???23*[python]
              ??3*[{python}]
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

igr*_*nis 4

sklearn.GridSearchCV文档:

\n\n
\n

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

\n\n

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

\n
\n\n

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

\n\n

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

\n\n

顺便说一句,我在 Mac 上没有观察到这种行为(正如GridSearchCV人们所期望的那样,只看到 5 个进程产生),因此它可能来自不兼容的库。尝试更新sklearnnumpy手动。

\n\n

这是我的pstree输出(出于隐私原因删除了部分路径):

\n\n
 \xe2\x94\x94\xe2\x94\x80\xe2\x94\xac= 00396 *** -fish\n   \xe2\x94\x94\xe2\x94\x80\xe2\x94\xac= 21743 *** python /Users/***/scratch_5.py\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 21775 *** python /Users/***/scratch_5.py\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 21776 *** python /Users/***/scratch_5.py\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 21777 *** python /Users/***/scratch_5.py\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 21778 *** python /Users/***/scratch_5.py\n     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 21779 *** python /Users/***/scratch_5.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

回答第二条评论:

\n\n

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

\n\n
N = 50000\nXs = np.concatenate( (np.random.random(N) , 3+np.random.random(N)) ).reshape(-1, 1)\nys = np.concatenate( (np.zeros(N), np.ones(N)) )\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n