Wykorzystanie pamięci wieloprocesorowej w Pythonie


Napisałem program, który można podsumować następująco:
def loadHugeData():
#load it
return datadef processHugeData(data, res_queue):
for item in data:
#process it
res_queue.put(result)
res_queue.put("END")def writeOutput(outFile, res_queue):
with open(outFile, 'w') as f
res=res_queue.get()
while res!='END':
f.write(res)
res=res_queue.get()res_queue = multiprocessing.Queue()if __name__ == '__main__':
data=loadHugeData()
p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue))
p.start()
processHugeData(data, res_queue)
p.join()

Prawdziwy kod (zwłaszcza
writeOutput ()
) jest znacznie bardziej skomplikowany.
writeOutput ()
używa tylko wartości, które przyjmuje jako argumenty (to znaczy nie patrz
data
)
Zasadniczo ładuje ogromny zbiór danych do pamięci i przetwarza go. Zapisywanie danych wyjściowych jest delegowane do podprocesu (w rzeczywistości zapisuje dane do wielu plików i zajmuje dużo czasu).
W ten sposób za każdym razem, gdy przetwarzana jest jedna część danych, jest ona wysyłana do podprocesu za pośrednictwem kolejki res_queue, która z kolei zapisuje wynik do plików w razie potrzeby.
Podproces nie musi w żaden sposób uzyskiwać dostępu, odczytywać ani modyfikować danych załadowanych przez
loadHugeData ()
. Podproces musi używać tylko tego, co główny proces wysyła do niego za pośrednictwem
res_queue
. I to prowadzi mnie do mojego problemu i pytania.
Wydaje mi się, że podproces pobiera go z kopii ogromnego zbioru danych (podczas sprawdzania użycia pamięci za pomocą
top
). to prawda? A jeśli tak, jak mogę uniknąć identyfikatora (zasadniczo używając podwójnej pamięci)?
Używam Pythona 2.6 i program działa na Linuksie.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Moduł
multiprocessing
jest w rzeczywistości oparty na wywołaniu systemowym
fork
, które tworzy kopię bieżącego procesu. Ponieważ ładujesz ogromne dane przed
fork
(lub tworzysz
multiprocessing.Process
), proces potomny dziedziczy kopię danych.
Jeśli jednak system operacyjny, na którym uruchamiasz, implementuje COW (kopiowanie przy zapisie), w pamięci fizycznej będzie tylko jedna kopia danych, chyba że zmienisz dane w procesie nadrzędnym lub podrzędnym (zarówno nadrzędny, jak i podrzędny użyje tych samych i tych samych stron pamięci fizycznej, aczkolwiek w różnych wirtualnych przestrzeniach adresowych); i nawet wtedy dodatkowa pamięć zostanie przydzielona tylko na zmiany (w przyrostach
pagesize
).
Możesz uniknąć tej sytuacji, wywołując
multiprocessing.Process
przed załadowaniem ogromnych danych. Wówczas dodatkowe alokacje pamięci nie zostaną odzwierciedlone w procesie potomnym podczas ładowania danych do elementu nadrzędnego.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się