并行代码先运行时挂起,后运行非并行代码时正常

3 投票
2 回答
4113 浏览
提问于 2025-04-18 07:59

这听起来有点复杂,但我最近在使用joblib时遇到了一个问题,它会创建很多进程,然后就卡在那里(也就是说,每个进程占用内存,但不使用CPU时间)。

这是我能找到的最简单的代码,可以重现这个问题:

from sklearn import linear_model
import numpy as np
from sklearn import cross_validation as cval
from joblib import Parallel, delayed

def fit_hanging_model(n=10000, nx=10, ny=32, ndelay=10,
                       n_cvs=5, n_jobs=None):
    # Create data
    X = np.random.randn(n, ny*ndelay)
    y = np.random.randn(n, nx)

    # Create model + CV
    model = linear_model.Ridge(alpha=1000.)
    cvest = cval.KFold(n, n_folds=n_cvs, shuffle=True)

    # Fit model
    par = Parallel(n_jobs=n_jobs, verbose=10)
    parfunc = delayed(_fit_model_cvs)
    par(parfunc(X, y, train, test, model)
                      for i, (train, test) in enumerate(cvest))

def _fit_model_cvs(X, Y, train, test, model):
    model.fit(X, Y)  

n = 10
a = np.random.randn(n, 32) 
b = np.random.randn(32, 10)

##########
c = np.dot(a, b)
##########

fit_hanging_model(n_jobs=3)

接下来发生的事情是:

  • 如果我运行上面的所有代码,它会启动三个进程,然后就卡住了
  • 如果我运行上面的所有代码,但把n_jobs设置为1,那么就没问题了
  • 如果我第一次用n_jobs设置为1运行上面的所有代码,然后再第二次运行,不管我用多少个进程,它都能正常工作
  • 如果我运行上面的所有代码,但不包括######之间的代码,那么它也能正常运行
  • 但是,如果我之后运行######之间的代码,并尝试用n_jobs大于1来运行fit_hanging_model,它又会卡住

这是在joblib版本0.8.0和sklearn版本0.15-git下发生的。

注意,这个问题出现在CentOS的Linux系统上。我在其他机器上无法重现这个问题,所以可能很难找到原因。

有没有人知道这可能是什么原因呢?看起来那个点积操作有些奇怪,但我不知道具体是什么问题……我快要崩溃了……

2 个回答

1

根据我的经验,当调用的函数再进行一次并行处理时,joblib 会出现卡住的情况。

按照 @choldgraf 的回答中的解决方案,你需要通过 MKL 禁用内部的并行处理:

import os
os.environ['MKL_NUM_THREADS'] = '1'
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['MKL_DYNAMIC'] = 'FALSE'

这个方法也适用于其他并行计算库,比如 OpenMP

7

我搞明白了。原来这是因为Joblib在创建多个Python进程的时候,MKL也在同时尝试进行多线程处理。你可以在这里查看这个问题和解决办法(需要设置一些环境变量):

https://github.com/joblib/joblib/issues/138

撰写回答