Python Scipy&x27;s优化与多处理不兼容?

Python Scipy&x27;s优化与多处理不兼容?,python,optimization,scipy,multiprocessing,Python,Optimization,Scipy,Multiprocessing,在尝试使用Scipy的优化算法最小化子流程中计算其值的函数时,我发现基于梯度的算法(到目前为止,basinhopping和L-BFGS-B)在optimize.py的第562行遇到以下错误: TypeError:-:“非类型”和“非类型”的操作数类型不受支持 下面是生成此错误的简单代码示例: import multiprocessing as mp from scipy.optimize import basinhopping def runEnvironment(x): return

在尝试使用Scipy的优化算法最小化子流程中计算其值的函数时,我发现基于梯度的算法(到目前为止,basinhopping和L-BFGS-B)在optimize.py的第562行遇到以下错误:

TypeError:-:“非类型”和“非类型”的操作数类型不受支持

下面是生成此错误的简单代码示例:

import multiprocessing as mp
from scipy.optimize import basinhopping

def runEnvironment(x):
    return x**2

def func(x):
    if __name__ == '__main__':
        print "x:",x
        pool = mp.Pool(processes=1)

        results=pool.apply(runEnvironment,(x,))
        pool.close()
        return results

x0=5    
ret=basinhopping(func, x0, niter=100, T=1.0, stepsize=0.1, minimizer_kwargs=None, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=None)

请注意,如果删除了多处理组件,或者使用了非基于梯度的算法(如COBYLA),则此代码运行良好。有人能想出发生这种情况的原因吗?

创建多个小型
mp.Pool
s是低效的,每个人只有一个工作人员 过程每次调用
func
创建一个池也是低效的,因为
func
被多次调用

相反,在程序开始时创建一个
,并将该池传递给对
func
的每个调用:

if __name__ == '__main__':
    pool = mp.Pool()
    x0=5    
    ret = optimize.basinhopping(
        func, x0, niter=100, T=1.0, stepsize=0.1,
        minimizer_kwargs=dict(args=pool), 
        take_step=None, accept_test=None, callback=None,
        interval=50, disp=False, niter_success=None)
    pool.close()
    print(ret)
minimizer\u kwargs=dict(args=pool)
告诉
optimize.basinhopping
pool
作为
func
的附加参数传递


你也可以使用

logger = mp.log_to_stderr(logging.INFO)
获取日志记录语句,这些语句显示调用函数的过程。比如说,

import multiprocessing as mp
from scipy import optimize
import logging
logger = mp.log_to_stderr(logging.INFO)

def runEnvironment(x):
    logger.info('runEnvironment({}) called'.format(x))
    return x**2

def func(x, pool):
    logger.info('func({}) called'.format(x))
    results = pool.apply(runEnvironment,(x,))
    return results

if __name__ == '__main__':
    pool = mp.Pool()
    x0=5    
    ret = optimize.basinhopping(
        func, x0, niter=100, T=1.0, stepsize=0.1,
        minimizer_kwargs=dict(args=pool), 
        take_step=None, accept_test=None, callback=None,
        interval=50, disp=False, niter_success=None)
    pool.close()
    print(ret)
印刷品

[INFO/PoolWorker-1] child process calling self.run()
[INFO/PoolWorker-2] child process calling self.run()
[INFO/PoolWorker-3] child process calling self.run()
[INFO/PoolWorker-4] child process calling self.run()
[INFO/MainProcess] func([ 5.]) called
[INFO/PoolWorker-1] runEnvironment([ 5.]) called
[INFO/MainProcess] func([ 5.00000001]) called
[INFO/PoolWorker-2] runEnvironment([ 5.00000001]) called
[INFO/MainProcess] func([ 5.]) called
[INFO/PoolWorker-3] runEnvironment([ 5.]) called
[INFO/MainProcess] func([-5.]) called
[INFO/PoolWorker-4] runEnvironment([-5.]) called
这表明
func
始终由主进程调用,而
runEnvironment
由辅助进程运行

请注意,对
func
的调用是按顺序进行的。从中得到好处
pool
,每次调用
func
您的
时,如果
习惯用法位于错误的位置,您将不得不使用更多的处理器。按此方式重新排列:

import multiprocessing as mp
from scipy.optimize import basinhopping

def runEnvironment(x):
    return x**2

def func(x):

    print "x:",x
    pool = mp.Pool(processes=1)

    results=pool.apply(runEnvironment,(x,))
    pool.close()
    return results

if __name__ == '__main__':
    x0=5
    ret=basinhopping(func, x0, niter=100, T=1.0, stepsize=0.1, minimizer_kwargs=None, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=None)

为什么
func
有一个
如果u u name\u_=='\uu u main\u__'
测试?那工作得很好!虽然我不知道为什么这里是if name=='main':语句的正确位置。@Peter:因为Windows没有
os.fork
,而是
多处理
模块。如果不使用
保护对
basinhopping
的调用,如果uuu name\uuuu=='\uuuuu main\uuuu'
则子进程调用
basinhopping
,它将调用
func
。由于
func
中存在
if
if
if
if
if
return
语句,因此该
func
调用将返回
None
,达到no
return
语句时的默认值……@Peter:
basinhopping
期望
func
返回一个数值,因此,当
func
返回
None
时,会引发
TypeError
。啊,好的,这是有意义的。@unutbu类方法也有奇怪的行为,这是预期的吗?我的最新问题解释了这一点,但我正在为每个函数调用创建一个池,以便在计算函数后立即释放内存。我正在与一些似乎存在内存泄漏问题的第三方库合作,这是一项快速而肮脏的工作。这是在
func
内部使用
mp.Pool
的一个很好的理由。
import multiprocessing as mp
from scipy.optimize import basinhopping

def runEnvironment(x):
    return x**2

def func(x):

    print "x:",x
    pool = mp.Pool(processes=1)

    results=pool.apply(runEnvironment,(x,))
    pool.close()
    return results

if __name__ == '__main__':
    x0=5
    ret=basinhopping(func, x0, niter=100, T=1.0, stepsize=0.1, minimizer_kwargs=None, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=None)