Один из вариантов заключается в использовании 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
Вы видели [этот комментарий] (http://stackoverflow.com/questions/23574146/solving-two-uncoupled-odes-within -a-loop-using-python-and-scipy-integrate-ode # comment36180664_23574361) и соответствующие сообщения? Кроме того, odeint [не может быть восприимчивым] (http://comments.gmane.org/gmane.comp.python.scientific.user/36151) к той же проблеме. –
@ AndrasDeak: Спасибо, что посмотрели! Ссылка на .pdf больше не работала. Однако мне скорее нужен неявный решатель, чем явный, и Рунге Кутта явный, я думаю. У меня также были внутренние ошибки, когда я пытался использовать mutithreaded odeint, а не ode. Я думаю, что 'ode.set_integrator ('lsoda')' является той же реализацией, что и odeint. – Matthias