Python threading vs. multiprocessing im Linux
Basierend auf dieser Frage ich davon ausgegangen, dass die Schaffung neuen Prozess sollte fast so schnell wie erstellen neuen thread in Linux. Allerdings, kleiner test zeigte ganz anderes Ergebnis. Hier ist mein code:
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()
Tests:
>>> timeit processes()
1 loops, best of 3: 3.8 s per loop
>>> timeit threads()
10 loops, best of 3: 98.6 ms per loop
So, die Prozesse sind fast 40 mal langsamer zu erstellen! Warum ist es passiert? Ist es spezifisch für Python oder diese Bibliotheken? Oder habe ich es nur falsch interpretiert die Antwort oben?
UPD 1. Zu machen, mehr klar. Ich verstehe, dass dieses Stück code nicht wirklich vorstellen jede Parallelität. Das Ziel hier ist das testen die Zeit, die benötigt wird, um einem Prozess und einem thread. Der Einsatz von real-Parallelität mit Python kann man so etwas wie dieses:
def pools():
pool = Pool(10)
pool.map(inc, xrange(times))
denen läuft wirklich viel schneller, als Gewinde-version.
UPD 2. Ich habe die version mit os.fork()
:
for i in xrange(times):
child_pid = os.fork()
if child_pid:
os.waitpid(child_pid, 0)
else:
exit(-1)
Ergebnisse:
$ 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
- Gut, die Frage, die Sie verknüpft, ist der Vergleich der Kosten von nur aufrufen
fork(2)
vs.pthread_create(3)
, während Ihr code wird schon ein bisschen mehr. Wie über den Vergleich vonos.fork()
mitthread.start_new_thread()
? - Ich konnte Sie nicht finden jede Art von
join
imthread
Modul zu erstellen, ähnlich wie Prüfungen, aber auch im Vergleich zu high-level -threading
version mitos.fork()
ist noch viel langsamer. In der Tat, es ist das langsamste ist (wenn zusätzliche Bedingungen können die Leistung beeinflussen). Siehe mein update. - Sie einen mutex verwenden müssen, zu warten, bis der thread, wenn Sie mit der low-level -
thread
- Modul, welches, wie die höheren-Ebenethreading
Modul implementiertjoin()
. Aber, wenn Sie nur versuchen die Zeit Messen, die es braucht, um erstellen Sie die neue Prozess/thread, dann sollten Sie nicht fordernjoin()
. Siehe auch meine Antwort unten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Frage, die Sie verknüpft, ist der Vergleich der Kosten von nur aufrufen
fork(2)
vs.pthread_create(3)
, während Ihr code wird schon ein bisschen mehr, z.B. überjoin()
warten, bis die Prozesse/threads beenden.Wenn, wie du sagst...
...dann sollten Sie nicht warten, um Sie abzuschließen. Sie sollten mit test-Programme, die wie diese...
fork.py
thread.py
...die geben die folgenden Ergebnisse...
...also es gibt nicht viel Unterschied in der Zeitpunkt der Erstellung von threads und Prozessen.
fork.py
nur neue threads erstellen und beenden, ohne zu warten, für die Kind-Prozesse abgeschlossen?ctypes
), um die meiste Arbeit zu tun.Ja, es ist wahr. Ein neuer Prozess gestartet wird (die sogenannte heavyweight process) ist teuer.
Als übersicht ...
Muß das Betriebssystem (in dem Fall linux) Gabel der erste Prozess, einrichten der Buchführung, für die neue Prozess, die neue stack, tun Sie den Kontext wechseln, kopieren Speicher, der verändert wird, und reißen alles runter, wenn der neue Prozess gibt.
Den thread reserviert einen neuen stack-und thread-Struktur, nicht den Kontext wechseln, und gibt, wenn die Arbeit getan ist.
... das ist, warum wir threads.
In meiner Erfahrung gibt es einen bedeutenden Unterschied zwischen dem erstellen eines Threads (mit
pthread_create
) und die Verzweigung eines Prozesses.Beispielsweise erstellte ich einen C-test ähnlich wie die python-test-thread mit code wie diesem:
und das Prozess-forking-code wie folgt:
Auf meinem system die code-forking dauerte etwa 8 mal so lange zum ausführen.
Jedoch, es ist erwähnenswert, dass die python-Implementierung ist sogar noch langsamer - bei mir war es ungefähr 16 mal so langsam. Ich vermute, dass es ist, weil zusätzlich zu den regelmäßigen Aufwand der Erstellung eines neuen Prozesses, es ist auch mehr python-overhead im Zusammenhang mit dem neuen Verfahren zu.