2013-06-29 16 views
17

La prima domanda è qual è la differenza tra Valore e Manager(). Valore?Variabile condivisa nel multiprocesso di Python

In secondo luogo, è possibile condividere la variabile intera senza utilizzare Valore? Di seguito è riportato il mio codice di esempio. Quello che voglio è ottenere un dict con un valore intero, non valore. Quello che ho fatto è cambiarlo tutto dopo il processo. C'è un modo più semplice?

from multiprocessing import Process, Manager 

def f(n): 
    n.value += 1 

if __name__ == '__main__': 
    d = {} 
    p = [] 

    for i in range(5): 
     d[i] = Manager().Value('i',0) 
     p.append(Process(target=f, args=(d[i],))) 
     p[i].start() 

    for q in p: 
     q.join() 

    for i in d: 
     d[i] = d[i].value 

    print d 
+0

Pertinente: http://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing –

risposta

19

Quando si utilizza Value si ottiene un oggetto ctypes nella memoria condivisa che di default è sincronizzato con RLock. Quando si utilizza Manager si ottiene un oggetto SynManager che controlla un processo del server che consente la manipolazione dei valori degli oggetti da parte di altri processi. È possibile creare più proxy utilizzando lo stesso gestore; non v'è alcuna necessità di creare una nuova gestione nel ciclo:

manager = Manager() 
for i in range(5): 
    new_value = manager.Value('i', 0) 

Il Manager possono essere condivisi tra i computer, mentre Value è limitata a un solo computer. Value sarà più veloce (esegui il codice seguente per vedere), quindi penso che dovresti usarlo a meno che non sia necessario supportare oggetti arbitrari o accedervi tramite una rete.

import time 
from multiprocessing import Process, Manager, Value 

def foo(data, name=''): 
    print type(data), data.value, name 
    data.value += 1 

if __name__ == "__main__": 
    manager = Manager() 
    x = manager.Value('i', 0) 
    y = Value('i', 0) 

    for i in range(5): 
     Process(target=foo, args=(x, 'x')).start() 
     Process(target=foo, args=(y, 'y')).start() 

    print 'Before waiting: ' 
    print 'x = {0}'.format(x.value) 
    print 'y = {0}'.format(y.value) 

    time.sleep(5.0) 
    print 'After waiting: ' 
    print 'x = {0}'.format(x.value) 
    print 'y = {0}'.format(y.value) 

In sintesi:

  1. Usa Manager per creare più oggetti condivisi, tra cui dicts e liste. Utilizzare Manager per condividere i dati tra computer su una rete.
  2. Usa Value o Array quando non è necessario condividere le informazioni attraverso una rete e il tipo di ctypes sono sufficienti per le vostre esigenze .
  3. Value è più veloce di Manager.

Attenzione

Tra l'altro, la condivisione dei dati tra processi/thread dovrebbe essere evitato se possibile. Il codice sopra verrà probabilmente eseguito come previsto, ma aumenterà il tempo necessario per eseguire foo e le cose diventeranno strane. Confrontare il precedente con:

def foo(data, name=''): 
    print type(data), data.value, name 
    for j in range(1000): 
     data.value += 1 

Avrete bisogno di un Lock per fare correttamente questo lavoro.

Non sono particolarmente ben informato su tutto questo, quindi forse qualcun altro verrà e offrirà più informazioni. Ho pensato che avrei dato una risposta dato che la domanda non stava attirando l'attenzione. Spero che questo aiuti un po '.

+0

è possibile aggiungere qualsiasi valore all'array? Non riesco ad aggiungere alcun valore a Array. – user2435611

+2

@ user2435611, ['Array'] (http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Array) fornirà un array ctypes condiviso. È necessario decidere in anticipo quale tipo di dati si stanno archiviando e fornire un [codice tipo] (http://docs.python.org/2/library/array.html#module-array). Ad esempio, 'a = Array ('c', 10)' crea un array di stringhe di un carattere di lunghezza 10. Nuove voci possono essere aggiunte all'array in questo modo: 'a [0] = 'b''.Non è possibile aggiungere * qualsiasi * valore a un array, consultare [l'elenco dei codici tipo] (http://docs.python.org/2/library/array.html#module-array). – ChrisP

+0

Quindi dovremmo decidere in anticipo la dimensione della matrice e non possiamo espanderla? se è così, è meglio per me usare manager.list(). Grazie per l'aiuto :) – user2435611

Problemi correlati