podstawie tej question Sądziłem, że nowy proces tworzenia powinny być prawie tak szybko jak tworzenia nowy wątek w Linuksie. Jednak mały test wykazał bardzo różne wyniki. Oto mój kod:Python gwintowania vs. multiprzetwarzania w Linuksie
from multiprocessing import Process, Pool
from threading import Thread
times = 1000
def inc(a):
b = 1
return a + b
def processes():
for i in xrange(times):
p = Process(target=inc, args=(i,))
p.start()
p.join()
def threads():
for i in xrange(times):
t = Thread(target=inc, args=(i,))
t.start()
t.join()
Testy:
>>> timeit processes()
1 loops, best of 3: 3.8 s per loop
>>> timeit threads()
10 loops, best of 3: 98.6 ms per loop
więc procesy są prawie 40 razy wolniej tworzenia! Dlaczego tak się dzieje? Czy jest to specyficzne dla Pythona lub tych bibliotek? Czy po prostu źle zinterpretowałem powyższą odpowiedź?
UPD 1. Żeby było jasne. Rozumiem, że ten fragment kodu w rzeczywistości nie wprowadza żadnej współbieżności. Celem jest przetestowanie czasu potrzebnego do utworzenia procesu i wątku. Aby korzystać z prawdziwą współbieżność Pythonie można użyć czegoś takiego:
def pools():
pool = Pool(10)
pool.map(inc, xrange(times))
który naprawdę działa znacznie szybciej niż wersja gwintowany.
UPD 2. dodałem wersję z os.fork()
:
for i in xrange(times):
child_pid = os.fork()
if child_pid:
os.waitpid(child_pid, 0)
else:
exit(-1)
Wyniki są następujące:
$ time python test_fork.py
real 0m3.919s
user 0m0.040s
sys 0m0.208s
$ time python test_multiprocessing.py
real 0m1.088s
user 0m0.128s
sys 0m0.292s
$ time python test_threadings.py
real 0m0.134s
user 0m0.112s
sys 0m0.048s
Cóż, pytanie, z którym się łączysz, polega na porównaniu kosztu wywołania 'fork (2)' vs. 'pthread_create (3)', podczas gdy twój kod robi całkiem sporo więcej. Co powiesz na porównanie 'os.fork()' z 'thread.start_new_thread()'? – Aya
@Aya: Nie mogłem znaleźć żadnego rodzaju 'join' w module' thread', aby stworzyć podobny test, ale nawet w porównaniu z wersją 'threading' na wysokim poziomie z' os.fork() 'jest nadal znacznie wolniejsze. W rzeczywistości jest najwolniejsza (choć dodatkowe warunki mogą wpływać na wydajność). Zobacz moją aktualizację. – ffriend
Musisz użyć muteksu, aby poczekać na wątek, jeśli używasz niskiego poziomu 'thread' module, tak jak moduł' threading' wyższego poziomu implementuje 'join()'. Ale jeśli próbujesz zmierzyć czas potrzebny do utworzenia nowego procesu/wątku, nie powinieneś wywoływać 'join()'. Zobacz także moją odpowiedź poniżej. – Aya