2013-04-03 9 views
11

C'è un modo semplice per utilizzare Multiprocessing per fare l'equivalente di questo?Elaborazione multipla Python - applica un metodo di classe a un elenco di oggetti

for sim in sim_list: 
    sim.run() 

dove gli elementi della sim_list sono oggetti "simulazione" e run() è un metodo della classe di simulazione che fa modificare gli attributi degli oggetti. Es .:

class simulation: 
    __init__(self): 
    self.state['done']=False 
    self.cmd="program" 
def run(self): 
    subprocess.call(self.cmd) 
    self.state['done']=True 

Tutte le sim in sim_list sono indipendenti, quindi la strategia non deve essere thread-safe.

Ho provato quanto segue, che è ovviamente difettoso perché l'argomento è passato da deepcopy e non è modificato sul posto.

from multiprocessing import Process 

for sim in sim_list: 
    b = Process(target=simulation.run, args=[sim]) 
    b.start() 
    b.join() 
+3

Non si desidera unire() ai processi nel ciclo o li si eseguirà uno dopo l'altro anziché in parallelo. Per rispondere alla tua domanda, potresti inviare un multiprocessing.Queue object quando avvii il processo e poi mettiti in coda quando hai finito. –

+0

Ok per un commento su join(). Per quanto riguarda l'uso di Queue, non sono sicuro di come dovrebbe funzionare. Il mio oggetto sim non sarà comunque passato attraverso la deepcopy? – calys

+0

@calys Su windows si otterrà un 'PicklingError' perché si sta tentando di decollare un metodo, su UNIX non c'è" deepcopy ", semplicemente ogni processo ottiene una copia perfetta dell'intero spazio di indirizzamento. È necessario sostituire il cambiamento di stato nell'istanza con una comunicazione di interprocessa esplicita. – Bakuriu

risposta

11

Un modo per fare ciò che si desidera è di avere la classe di calcolo (simulation nel tuo caso) essere una sottoclasse di Process. Se inizializzate correttamente, le istanze di questa classe verranno eseguite in processi separati e sarà possibile impostare un gruppo di esse da un elenco come desiderato.

Ecco un esempio, sulla base quello che hai scritto sopra:

import multiprocessing 
import os 
import random 

class simulation(multiprocessing.Process): 
    def __init__(self, name): 
     # must call this before anything else 
     multiprocessing.Process.__init__(self) 

     # then any other initialization 
     self.name = name 
     self.number = 0.0 
     sys.stdout.write('[%s] created: %f\n' % (self.name, self.number)) 

    def run(self): 
     sys.stdout.write('[%s] running ... process id: %s\n' 
         % (self.name, os.getpid())) 

     self.number = random.uniform(0.0, 10.0) 
     sys.stdout.write('[%s] completed: %f\n' % (self.name, self.number)) 

Poi basta fare una lista di oggetti e iniziare ognuna con un ciclo:

sim_list = [] 
sim_list.append(simulation('foo')) 
sim_list.append(simulation('bar')) 

for sim in sim_list: 
    sim.start() 

Quando si esegue questo si dovrebbe vedere ogni oggetto eseguito nel proprio processo. Non dimenticare di chiamare Process.__init__(self) come la prima cosa nell'inizializzazione della tua classe, prima di ogni altra cosa.

Ovviamente non ho incluso alcuna comunicazione di interprocesso in questo esempio; dovrai aggiungere che se la tua situazione lo richiede (non è chiaro dalla tua domanda se ne hai avuto bisogno o meno).

Questo approccio funziona bene per me e non sono a conoscenza di eventuali inconvenienti. Se qualcuno conosce dei pericoli nascosti che ho trascurato, faccelo sapere.

Spero che questo aiuti.

+1

Grazie mille. Funziona :) – calys

+0

Ottima risposta, grazie –

Problemi correlati