Belajar tentang Python Multiprocessing (dari artikel PMOTW ) dan akan menyukai beberapa klarifikasi tentang apa sebenarnya yang dilakukan join()
metode ini.
Dalam tutorial lama dari tahun 2008 disebutkan bahwa tanpa p.join()
panggilan dalam kode di bawah ini, "proses anak akan diam dan tidak berhenti, menjadi zombie yang harus Anda bunuh secara manual".
from multiprocessing import Process
def say_hello(name='world'):
print "Hello, %s" % name
p = Process(target=say_hello)
p.start()
p.join()
Saya menambahkan cetakan dari PID
serta a time.sleep
untuk diuji dan sejauh yang saya tahu, prosesnya berakhir dengan sendirinya:
from multiprocessing import Process
import sys
import time
def say_hello(name='world'):
print "Hello, %s" % name
print 'Starting:', p.name, p.pid
sys.stdout.flush()
print 'Exiting :', p.name, p.pid
sys.stdout.flush()
time.sleep(20)
p = Process(target=say_hello)
p.start()
# no p.join()
dalam 20 detik:
936 ttys000 0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000 0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001 0:00.13 -bash
setelah 20 detik:
947 ttys001 0:00.13 -bash
Perilakunya sama dengan p.join()
menambahkan kembali di akhir file. Python Module of the Week menawarkan penjelasan modul yang sangat mudah dibaca ; "Untuk menunggu hingga proses menyelesaikan pekerjaannya dan keluar, gunakan metode join ().", Tetapi tampaknya setidaknya OS X melakukannya.
Saya juga bertanya-tanya tentang nama metode tersebut. Apakah .join()
metode ini menggabungkan sesuatu di sini? Apakah itu menggabungkan proses dengan akhirnya? Atau apakah itu hanya berbagi nama dengan bahasa asli Python.join()
metode ?
sumber
CPU, Memory resources
dipisahkan dari proses induk, lalujoin
diedit kembali setelah proses anak selesai?Jawaban:
The
join()
metode, bila digunakan denganthreading
ataumultiprocessing
, tidak berhubungan denganstr.join()
- itu tidak benar-benar concatenating apapun bersama-sama. Sebaliknya, ini hanya berarti "tunggu [utas / proses] ini selesai". Namajoin
ini digunakan karenamultiprocessing
API modul dimaksudkan agar terlihat serupa denganthreading
API modul, danthreading
modul digunakanjoin
untukThread
objeknya. Menggunakan istilahjoin
berarti "menunggu utas selesai" adalah umum di banyak bahasa pemrograman, jadi Python juga mengadopsinya.Sekarang, alasan Anda melihat penundaan 20 detik dengan dan tanpa panggilan ke
join()
adalah karena secara default, saat proses utama siap untuk keluar, secara implisit akan memanggiljoin()
semuamultiprocessing.Process
instance yang berjalan . Ini tidak dinyatakan dengan jelas dimultiprocessing
dokumen sebagaimana mestinya, tetapi disebutkan di bagian Panduan Pemrograman :Anda dapat mengganti perilaku ini dengan menyetel
daemon
bendera padaProcess
menjadiTrue
sebelum memulai proses:Jika Anda melakukannya, proses turunan akan dihentikan segera setelah proses utama selesai :
sumber
p.daemon=True
itu untuk "memulai proses latar belakang yang berjalan tanpa memblokir program utama keluar". Tetapi jika "Proses daemon dihentikan secara otomatis sebelum program utama keluar", apa sebenarnya kegunaannya?daemonic
proses anak tidak terlalu aman, karena proses akan dihentikan tanpa mengizinkan untuk membersihkan sumber daya terbuka yang mungkin dimilikinya .. (lanjutan).multiprocessing
API dirancang untuk meniruthreading
API sedekat mungkin.threading.Thread
Objek daemonik dihentikan segera setelah utas utama keluar, sehinggamultiprocesing.Process
objek daemonik berperilaku dengan cara yang sama.Tanpa
join()
, proses utama dapat selesai sebelum proses anak selesai. Saya tidak yakin dalam keadaan apa yang menyebabkan zombieisme.Tujuan utama
join()
adalah untuk memastikan bahwa proses anak telah selesai sebelum proses utama melakukan apa pun yang bergantung pada pekerjaan proses anak.Etimologi dari
join()
adalah kebalikan darifork
, yang merupakan istilah umum dalam sistem operasi keluarga Unix untuk membuat proses anak. Sebuah proses tunggal "bercabang" menjadi beberapa, lalu "bergabung" kembali menjadi satu.sumber
join()
karenajoin()
itulah yang digunakan untuk menungguthreading.Thread
objek selesai, danmultiprocessing
API dimaksudkan untuk meniruthreading
API sebanyak mungkin.join()
diperlukan dalam kasus di mana utas utama memerlukan hasil pekerjaan sub-utas. Misalnya, jika Anda merender sesuatu dan menetapkan 1/4 gambar akhir ke masing-masing dari 4 subproses, dan ingin menampilkan seluruh gambar setelah selesai.Saya tidak akan menjelaskan secara rinci apa yang
join
dilakukannya, tetapi inilah etimologi dan intuisi di baliknya, yang akan membantu Anda mengingat maknanya dengan lebih mudah.Idenya adalah bahwa eksekusi " bercabang " menjadi beberapa proses yang salah satunya adalah master, pekerja lainnya (atau "budak"). Ketika pekerja selesai, mereka "bergabung" dengan master sehingga eksekusi serial dapat dilanjutkan.
The
join
Metode menyebabkan proses master untuk menunggu seorang pekerja untuk bergabung. Metode ini mungkin lebih baik disebut "tunggu", karena itulah perilaku sebenarnya yang ditimbulkannya di master (dan itulah yang disebut dalam POSIX, meskipun utas POSIX juga menyebutnya "bergabung"). Bergabung hanya terjadi sebagai akibat dari benang bekerjasama dengan baik, itu bukan sesuatu master tidak .Nama "fork" dan "join" telah digunakan dengan arti ini dalam multiprocessing sejak 1963 .
sumber
join
mungkin telah mendahului penggunaannya dalam merujuk pada penggabungan, sebagai lawan dari sebaliknya.join()
digunakan untuk menunggu proses pekerja keluar. Seseorang harus meneleponclose()
atauterminate()
sebelum menggunakanjoin()
.Seperti @Russell yang disebutkan, join seperti kebalikan dari fork (yang memunculkan sub-proses).
Untuk bergabung untuk menjalankan Anda harus menjalankan
close()
yang akan mencegah lebih banyak tugas dikirim ke kolam dan keluar setelah semua tugas selesai. Alternatifnya, menjalankanterminate()
hanya akan keluar dengan menghentikan semua proses pekerja segera."the child process will sit idle and not terminate, becoming a zombie you must manually kill"
Hal ini dimungkinkan ketika proses utama (induk) keluar tetapi proses anak masih berjalan dan setelah selesai tidak ada proses induk untuk mengembalikan status keluarnya.sumber
The
join()
panggilan memastikan bahwa baris berikutnya dari kode tidak disebut sebelum semua proses multiprocessing selesai.Misalnya, tanpa
join()
, kode berikut akan memanggilrestart_program()
bahkan sebelum proses selesai, yang mirip dengan asynchronous dan bukan yang kita inginkan (Anda dapat mencoba):sumber
Untuk menunggu sampai proses menyelesaikan pekerjaannya dan keluar, gunakan metode join ().
dan
Catatan Penting untuk menggabungkan () proses setelah menghentikannya untuk memberikan waktu mesin latar belakang untuk memperbarui status objek untuk mencerminkan penghentian.
Ini adalah contoh yang baik membantu saya memahaminya: di sini
Satu hal yang saya perhatikan secara pribadi adalah proses utama saya dihentikan sementara sampai anak menyelesaikan prosesnya menggunakan metode join () yang mengalahkan poin yang saya gunakan
multiprocessing.Process()
di tempat pertama.sumber