多个 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 函数同时 运行 多个进程,每个进程调用 solvemap 函数负责将参数分配给 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 等其他解算器是否支持这种并发。