多个 scipy.integrate.ode 个实例
Multiple scipy.integrate.ode instances
我想在多线程(一个对于每个 CPU 核心)以便一次解决多个 IVP。但是文档说:“此积分器不可重入。您不能同时使用“vode”积分器有两个 ode 实例。”
(如果多次实例化 odeint 也会导致内部错误,尽管文档中没有这样说。)
知道可以做什么吗?
一种选择是使用 multiprocessing
(即使用进程而不是线程)。这是一个使用 multiprocessing.Pool
class.
的 map
函数的示例
函数 solve
采用一组初始条件和 returns 由 odeint
生成的解。主要部分中代码的 "serial" 版本重复调用 solve
,对 ics
中的每组初始条件调用一次。 "multiprocessing" 版本使用 multiprocessing.Pool
实例的 map
函数同时 运行 多个进程,每个进程调用 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
SciPy.integrate.ode 似乎使用 LLNL SUNDIALS solvers, although SciPy doesn't say so explicitly,但我认为它们应该使用。
CVODE 求解器的当前版本 3.2.2 是可重入的,这意味着它可以用于同时求解多个问题。相关信息出现在User Documentation for CVODE v3.2.0 (SUNDIALS v3.2.0).
All state information used by cvode to solve a given problem is saved in a structure, and a pointer
to that structure is returned to the user. There is no global data in the cvode package, and so, in this
respect, it is reentrant. State information specific to the linear solver is saved in a separate structure,
a pointer to which resides in the cvode memory structure. The reentrancy of cvode was motivated
by the anticipated multicomputer extension, but is also essential in a uniprocessor setting where two
or more problems are solved by intermixed calls to the package from within a single user program.
但我不知道 SciPy.integrate.ode 或 scikits.odes.ode 等其他解算器是否支持这种并发。
我想在多线程(一个对于每个 CPU 核心)以便一次解决多个 IVP。但是文档说:“此积分器不可重入。您不能同时使用“vode”积分器有两个 ode 实例。”
(如果多次实例化 odeint 也会导致内部错误,尽管文档中没有这样说。)
知道可以做什么吗?
一种选择是使用 multiprocessing
(即使用进程而不是线程)。这是一个使用 multiprocessing.Pool
class.
map
函数的示例
函数 solve
采用一组初始条件和 returns 由 odeint
生成的解。主要部分中代码的 "serial" 版本重复调用 solve
,对 ics
中的每组初始条件调用一次。 "multiprocessing" 版本使用 multiprocessing.Pool
实例的 map
函数同时 运行 多个进程,每个进程调用 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
SciPy.integrate.ode 似乎使用 LLNL SUNDIALS solvers, although SciPy doesn't say so explicitly,但我认为它们应该使用。
CVODE 求解器的当前版本 3.2.2 是可重入的,这意味着它可以用于同时求解多个问题。相关信息出现在User Documentation for CVODE v3.2.0 (SUNDIALS v3.2.0).
All state information used by cvode to solve a given problem is saved in a structure, and a pointer to that structure is returned to the user. There is no global data in the cvode package, and so, in this respect, it is reentrant. State information specific to the linear solver is saved in a separate structure, a pointer to which resides in the cvode memory structure. The reentrancy of cvode was motivated by the anticipated multicomputer extension, but is also essential in a uniprocessor setting where two or more problems are solved by intermixed calls to the package from within a single user program.
但我不知道 SciPy.integrate.ode 或 scikits.odes.ode 等其他解算器是否支持这种并发。