Python Scipy&x27;s优化与多处理不兼容?
在尝试使用Scipy的优化算法最小化子流程中计算其值的函数时,我发现基于梯度的算法(到目前为止,basinhopping和L-BFGS-B)在optimize.py的第562行遇到以下错误: TypeError:-:“非类型”和“非类型”的操作数类型不受支持 下面是生成此错误的简单代码示例: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
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
中存在ifififififreturn
语句,因此该func
调用将返回None
,达到noreturn
语句时的默认值……@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)