我想在多个线程(每个CPU核心一个)中使用scipy.integrate.ode(或scipy.integrate.odeint)实例,以便一次解决多个IVP.然而文档说:" 这个集成器不是可重入的.你不能同时使用"vode"集成器的两个ode实例. "
(如果文档没有说明,odeint会在多次实例化时导致内部错误.)
知道可以做些什么吗?
一种选择是使用multiprocessing
(即使用进程而不是线程).这是一个使用类map
功能的示例multiprocessing.Pool
.
该函数solve
采用一组初始条件并返回由此生成的解odeint
.主要部分中的代码的"串行"版本solve
重复调用,对于每组初始条件一次ics
."多处理"版本使用实例的map
功能multiprocessing.Pool
同时运行多个进程,每个进程都调用solve
.该map
函数负责处理参数solve
.
我的计算机有四个核心,随着我的增加num_processes
,加速最大值大约为3.6.
from __future__ import division, print_function import sys import time import multiprocessing as mp import numpy as np from scipy.integrate import odeint def lorenz(q, t, sigma, rho, beta): x, y, z = q return [sigma*(y - x), x*(rho - z) - y, x*y - beta*z] def solve(ic): t = np.linspace(0, 200, 801) sigma = 10.0 rho = 28.0 beta = 8/3 sol = odeint(lorenz, ic, t, args=(sigma, rho, beta), rtol=1e-10, atol=1e-12) return sol if __name__ == "__main__": ics = np.random.randn(100, 3) print("multiprocessing:", end='') tstart = time.time() num_processes = 5 p = mp.Pool(num_processes) mp_solutions = p.map(solve, ics) tend = time.time() tmp = tend - tstart print(" %8.3f seconds" % tmp) print("serial: ", end='') sys.stdout.flush() tstart = time.time() serial_solutions = [solve(ic) for ic in ics] tend = time.time() tserial = tend - tstart print(" %8.3f seconds" % tserial) print("num_processes = %i, speedup = %.2f" % (num_processes, tserial/tmp)) check = [(sol1 == sol2).all() for sol1, sol2 in zip(serial_solutions, mp_solutions)] if not all(check): print("There was at least one discrepancy in the solutions.")
在我的电脑上,输出是:
multiprocessing: 6.904 seconds serial: 24.756 seconds num_processes = 5, speedup = 3.59