2012-10-19 3 views
6

Mam taki scenariusz: Utworzono obiekt elementu klasy zawierający semafor.Wieloprocesorowość w języku Python, przekazywanie odwołania do obiektu zawierającego semafor

import multiprocessing as mpr 

class Element(object): 
    def __init__(self): 
     self.sem = mpr.Semaphore() 
     self.xyz = 33 

def fun(ch): 
    a = ch.recv() 
    print(a[0]) 
    print(a[1].xyz) 
    a[1].xyz = 99 
    print(a[1].xyz) 


el = Element() 

(pa , ch) = mpr.Pipe() 
proc = mpr.Process(target=fun , args=(ch,)) 

proc.start() 
pa.send([ "Hallo" , el ]) 

print(el.xyz) 

proc.join() 

Ten powrót Kod ten błąd:

File "/usr/lib/python2.7/multiprocessing/forking.py", line 51, in assert_spawning 
    ' through inheritance' % type(self).__name__ 
RuntimeError: Semaphore objects should only be shared between processes through inheritance 

Ale jeśli usunąć semafora z deklaracją Element kod działa, ale wartość przypisana a [1] będzie .xyz zostać utracone.

Teraz potrzebuję zsynchronizować dużą kolekcję obiektów za pośrednictwem semphore i multiprocessing. A więc jest jakaś metoda ustawienia semafora w każdym obiekcie i przekazywania tylko odniesienia do głównego obiektu?

import multiprocessing as mpr 

class Element(object): 
    def __init__(self): 
     self.xyz = 33 

def fun(ch): 
    a = ch.recv() 
    print(a[0]) 
    print(a[1].xyz) 
    a[1].xyz = 99 
    print(a[1].xyz) 


el = Element() 

(pa , ch) = mpr.Pipe() 
proc = mpr.Process(target=fun , args=(ch,)) 

proc.start() 
pa.send([ "Hallo" , el ]) 

print(el.xyz) 

proc.join() 

Druga wersja dot't wytwarzają żadnego błędu, ale wartość przypisana do a[1].xyz = 99 zostaną utracone w procesie głównym.

+0

Twój błąd jest jasny, mówi, że semafor powinien być atrybutem procesu i nie możesz go wysłać do niego. Zasadniczo musisz dziedziczyć po Process i zdefiniować 'run' etc ... Ale jest to bardziej niejasne, co próbujesz zrobić. –

+0

Być może mógłbyś przydzielić dużą liczbę semaforów na początku i przejściu po prostu zachować sem_index wewnątrz obiektu Element? – cdleonard

+0

Przekazywanie tablicy powoduje odtworzenie tego samego problemu w inny sposób, problem występuje w semaforze, a nie w kontenerze. – Giggi

Odpowiedz

13

Nie sądzę, że rozumiesz, jak działa moduł multiprocessing.

Podczas wysyłania czegoś przez rurę, zostaje się marynowany, a następnie niepickowany w podprocesie. Oznacza to, że podproces faktycznie ma kopię oryginalnego obiektu! Dlatego zmiana jest "stracona". Dodanie semafora nic nie zmieni.

Jeśli chcesz obiekt w pamięci współdzielonej, powinieneś użyć multiprocessing.Value, nawet jeśli nie obsługuje to typów arbitralnych. Prawdopodobnie multiprocessing.Manager jest tym, czego szukasz.

Innym sposobem byłoby wysłanie odpowiedzi do głównego procesu dostarczającego zmodyfikowany obiekt.