2012-10-19 15 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.

Powiązane problemy