Python multiprocessing & scipy optimize leastsq线程安全问题

来源:互联网 发布:mac的dashboard 编辑:程序博客网 时间:2024/05/22 11:44

错误状态描述:单线程运行时,没有任何错误,多线程运行时,时不时收到SystemError: null argument to internal routine。通过traceback确认是optimize.leastsq的问题!

SystemError: null argument to internal routine
Traceback (most recent call last):
File “autoflow/look_alike.py”, line 175, in choose
delta1 = math_utils.least2_coef(xlist, ylist, p0=1, mode=1)[0]
File “utils/math_utils.py”, line 39, in least2_coef
plesq = optimize.leastsq(residuals, p0, args=(np.array(ylist), np.array(xlist)))
File “/usr/local/lib/python2.7/site-packages/scipy/optimize/minpack.py“, line 387, in leastsq
gtol, maxfev, epsfcn, factor, diag)
error: Internal error constructing argument list.


参考下面几篇资料,基本可以确定是scipy.optimize中的方法不是线程安全的,具体导致leastsq挂掉的原因有可能最终能追溯到curve_fit。根据stackoverflow中的说法,加一个线程锁应该可以解决问题。
http://www.it1352.com/513190.html
[SciPy-User] thread-safe scipy.optimize.leastsq:https://mail.scipy.org/pipermail/scipy-user/2014-March/035556.html
Parallelism with SciPy.optimize:https://stackoverflow.com/questions/4598339/parallelism-with-scipy-optimize
Python: threading + curve_fit: null argument to internal routine: https://stackoverflow.com/questions/22612213/python-threading-curve-fit-null-argument-to-internal-routine


分析自己的代码,多线程使用multiprocessing的pool.map方法.在afunc方法中调用了least2_coef(内部调用scipy.optimize.leastsq)

多线程调用.py

from multiprocessing.dummy import Pool as ThreadPoolpool = ThreadPool(poolSize) # Sets the pool size to 4results = []try:    results = pool.map(afunc, alist)except:    traceback.print_exc()#close the pool and wait for the work to finish pool.close() pool.join() 

最小二乘拟合.py

from scipy import optimizeimport numpy as npimport threadinglock = threading.Lock() # -- add here --def least2_coef(xlist, ylist, p0, mode=1):    def func1(x, p):        u"""        """        A = p        return A * x    def func2(x, p):        u"""        """        k, b = p        return k * x + b    optionMode = {        2 : func2,        1 : func1,    }    func = optionMode[mode]      def residuals(p, y, x):        u"""        """        return y-func(x, p)    lock.acquire() ## --- add here --    plesq = optimize.leastsq(residuals, p0, args=(np.array(ylist), np.array(xlist))) # optimize.leastsq不是线程安全的    lock.release() ## --- add here --    return plesq[0]

在最小二乘拟合.py中加入lock锁之后,错误就解决了!