2017-09-05 51 views
5

Jaka jest różnica między ThreadPool i Pool w module multiprocessing. Kiedy próbuję mój kod na zewnątrz, to jest główna różnica widzę:Jaka jest różnica między ThreadPool a Pool w module wieloprocesorowym Python

from multiprocessing import Pool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = Pool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

widzę następujący wynik:

hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
inside hello() 
Proccess id: 13268 
inside hello() 
Proccess id: 11104 
inside hello() 
Proccess id: 13064 
[0, 1, 4] 

z "puli wątków":

from multiprocessing.pool import ThreadPool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = ThreadPool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

widzę następujące wyjście:

hi outside of main() 
inside hello() 
inside hello() 
Proccess id: 15204 
Proccess id: 15204 
inside hello() 
Proccess id: 15204 
[0, 1, 4] 

Moje pytania ia są:

  • dlaczego jest „poza __main __()” prowadzony za każdym razem w Pool?

  • multiprocessing.pool.ThreadPool nie odradza nowych procesów? Po prostu tworzy nowe wątki?

  • Jeśli tak, to jaka jest różnica między używaniem multiprocessing.pool.ThreadPool, a nie tylko modułu threading?

Nie widzę żadnej oficjalnej dokumentacji dla ThreadPool w dowolnym miejscu, czy ktoś może mi pomóc, gdzie mogę ją znaleźć?

+0

Jak wiem, z powodu GIL w Pythonie, wielowątkowość Pythona wygląda jak wielowątkowy, ale nie jest prawdziwy. Jeśli chcesz skorzystać z wielu rdzeni z pythonem, musisz użyć wielu procesów. W nowoczesnym komputerze tworzenie procesu i tworzenie wątku ma prawie taki sam koszt. – Yves

+0

Tworzenie wątku może mieć podobny koszt do tworzenia procesu, ale komunikacja między wątkami ma bardzo różny koszt komunikacji między procesami (chyba że używasz pamięci współdzielonej). Również twoja uwaga na temat GIL jest tylko częściowo prawdziwa: jest uwalniana podczas operacji we/wy i niektórych bibliotek (na przykład numpy) nawet podczas operacji związanych z CPU. Mimo to GIL jest ostatecznie powodem używania oddzielnych procesów w Pythonie. –

Odpowiedz

5

Zachowuje się tak samo jak multiprocessing.pool.ThreadPool jak multiprocessing.Pool z tą różnicą, że używa wątków zamiast procesów do uruchamiania logiki robotów.

Powodem widać

hi outside of main() 

drukowane kilka razy z multiprocessing.Pool Wynika to z faktu, że basen będzie spawn 5 niezależne procesy. Każdy proces, który zainicjuje własny interpreter języka Python i załaduje moduł, powodując ponowne wykonanie najwyższego poziomu print.

Należy zauważyć, że dzieje się tak tylko wtedy, gdy używana jest metoda tworzenia procesu spawn (tylko metoda dostępna w systemie Windows). Jeśli użyjesz jednego (Unix), zobaczysz wiadomość wydrukowaną tylko raz tak jak dla wątków.

Urządzenie nie jest dokumentowane, ponieważ jego implementacja nigdy nie została zakończona. Brakuje testów i dokumentacji. Możesz zobaczyć jego implementację w source code.

Sądzę, że następnym naturalnym pytaniem jest: kiedy używać puli opartej na wątkach i kiedy używać opartego na procesach?

Zasadą jest:

  • IO związane pracy ->multiprocessing.pool.ThreadPool
  • CPU związany pracy ->multiprocessing.Pool
  • hybrydowe pracy -> zależy od obciążenia, zazwyczaj wolą multiprocessing.Pool powodu izolacja procesu korzyści przynosi

W Pythonie 3 możesz chcieć rzucić okiem na implementacje puli .

+0

Dzięki za odpowiedź. Chcę tylko zrozumieć to stwierdzenie: Należy zauważyć, że dzieje się tak tylko wtedy, gdy używana jest metoda tworzenia procesu odradzania (tylko metoda dostępna w systemie Windows). Jeśli użyjesz fork (Unix), zobaczysz wiadomość wydrukowaną tylko raz, tak jak dla wątków. Zakładam, że "spawn" i "fork" są niejawne, gdy nazywam "map()" lub "Pool()"? Czy jest to coś, co mogę kontrolować? – ozn

+0

Wyjaśnienie znajduje się w linku podałem powyżej, gdy wspomniano o metodzie początkowej [spawn] (https://docs.python.org/3.6/library/multiprocessing.html#contexts-and-start-methods). Możesz to kontrolować, ale dostępność metod początkowych zależy od platformy systemu operacyjnego. Zakładam, że korzystasz z systemu Windows, ponieważ domyślną strategią początkową jest "odradzanie". Jeśli tak, nie ma wiele do zrobienia, ponieważ system Windows obsługuje tylko 'spawn'. – noxdafox