2015-12-15 20 views
11

I birden çok iş parçacığı scipy.integrate.ode (veya scipy.integrate.odeint) örneklerini kullanmak isteyen birden fazla Korunum çözmek için (her CPU çekirdek için bir tane) bir zaman. Ancak dokümantasyon diyor ki: "Aynı zamanda entegratörü‘her ne kadar birden çok kez örneği ise Vode’. Bu entegratörü kullanarak iki gazel örneklerini değil yeniden katılımcıya olamaz edilir"Çoklu scipy.integrate.ode örnekleri

(Ayrıca iç hatalara neden olur odeint dokümantasyon böyle söylemiyor.)

Neler yapılabilir?

+2

gördün mü [Bu yorumu] (http://stackoverflow.com/questions/23574146/solving-two-uncoupled-odes-within -a-döngü-kullanarak-python-ve-scipy-integrate-ode # comment36180664_23574361) ve ilgili mesajlar? Ayrıca, aynı soruna odeint [duyarlı olmayabilir] (http://comments.gmane.org/gmane.comp.python.scientific.user/36151). –

+0

@AndrasDeak: Ona baktığın için teşekkürler! .pdf bağlantısı artık işe yaramadı. Bununla birlikte, açık birinden daha örtülü bir çözücüye ihtiyacım var ve Runge Kutta açık bir bence. Ode yerine mutithreaded odeint kullanmaya çalıştığımda da iç hatalar var. Sanırım ode.set_integrator ('lsoda'), odeint ile aynı uygulama. – Matthias

cevap

8

Bir seçenek multiprocessing (yani iş parçacıkları yerine süreçleri kullanmaktır) kullanmaktır. İşte, multiprocessing.Pool sınıfının map işlevini kullanan bir örnek.

solve işlevi, bir dizi başlangıç ​​koşulunu alır ve odeint tarafından oluşturulan bir çözümü döndürür. Ana bölümdeki kodun "seri" versiyonu, ics'daki her başlangıç ​​koşulu kümesi için bir kez art arda solve'u çağırır. "Çoklu işlem" sürümü, solve numaralı çağıran her bir işlemi aynı anda çalıştırmak için multiprocessing.Pool örneğinin map işlevini kullanır. map işlevi, bağımsız değişkenleri solve olarak doldurarak ilgilenir.

Bilgisayarımın dört çekirdeği var ve ben num_processes'u artırdığımda, hız yaklaşık 3.6'da maksimuma çıkıyor.

benim bilgisayarda
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.") 

, çıkışı:

multiprocessing: 6.904 seconds 
serial:   24.756 seconds 
num_processes = 5, speedup = 3.59 
+0

Örnek için çok teşekkürler! İstediğim buydu. – Matthias

+0

CPU yükünün her zaman başlangıç ​​koşullarının ayarlanmış boyutundan ziyade işlem sayısına (çekirdek sayısına kadar) karşılık geldiğinin farkında mısınız? – Matthias

+0

Bu kulağa mantıklı geliyor. Sonuçta, CPU yükü çekirdek sayısını nasıl aşabilir? –