Apakah proses anak muncul melalui objek berbagi multiprosesing yang dibuat sebelumnya dalam program?
Saya memiliki pengaturan berikut:
do_some_processing(filename):
for line in file(filename):
if line.split(',')[0] in big_lookup_object:
# something here
if __name__ == '__main__':
big_lookup_object = marshal.load('file.bin')
pool = Pool(processes=4)
print pool.map(do_some_processing, glob.glob('*.data'))
Saya memuat beberapa objek besar ke dalam memori, lalu membuat kumpulan pekerja yang perlu menggunakan objek besar itu. Objek besar diakses hanya-baca, saya tidak perlu meneruskan modifikasinya di antara proses.
Pertanyaan saya adalah: apakah objek besar dimuat ke dalam memori bersama, seperti jika saya menelurkan proses di unix / c, atau apakah setiap proses memuat salinan objek besar itu sendiri?
Pembaruan: untuk memperjelas lebih lanjut - big_lookup_object adalah objek pencarian bersama. Saya tidak perlu membaginya dan memprosesnya secara terpisah. Saya perlu menyimpan satu salinannya. Pekerjaan yang perlu saya bagi adalah membaca banyak file besar lainnya dan mencari item dalam file besar tersebut terhadap objek pencarian.
Pembaruan lebih lanjut: database adalah solusi yang bagus, memcache mungkin solusi yang lebih baik, dan file di disk (rak atau dbm) mungkin lebih baik. Dalam pertanyaan ini saya sangat tertarik pada solusi memori. Untuk solusi terakhir, saya akan menggunakan hadoop, tetapi saya ingin melihat apakah saya dapat memiliki versi dalam memori lokal juga.
sumber
marshal.load
orang tua dan untuk setiap anak (setiap proses mengimpor modul).Jawaban:
"Apakah proses turunan muncul melalui objek berbagi multiprosesing yang dibuat sebelumnya dalam program?"
Tidak (python sebelum 3.8), dan Ya di 3.8 ( https://docs.python.org/3/library/multiprocessing.shared_memory.html#module-multiprocessing.shared_memory )
Proses memiliki ruang memori independen.
Solusi 1
Untuk memanfaatkan sebaik-baiknya struktur besar dengan banyak pekerja, lakukan ini.
Tulis setiap pekerja sebagai "filter" - membaca hasil antara dari stdin, berfungsi, menulis hasil antara di stdout.
Hubungkan semua pekerja sebagai pipa:
Setiap proses membaca, bekerja, dan menulis.
Ini sangat efisien karena semua proses berjalan secara bersamaan. Penulisan dan pembacaan melewati langsung buffer bersama di antara proses.
Solusi 2
Dalam beberapa kasus, Anda memiliki struktur yang lebih kompleks - seringkali struktur "menyebar". Dalam hal ini Anda memiliki orang tua dengan banyak anak.
Induk membuka data sumber. Orang tua bercabang untuk sejumlah anak.
Induk membaca sumber, mengolah bagian-bagian dari sumber ke setiap turunan yang berjalan secara bersamaan.
Saat induk mencapai ujung, tutup pipa. Anak mendapatkan akhir file dan selesai secara normal.
Bagian-bagian anak menyenangkan untuk ditulis karena setiap anak hanya membaca
sys.stdin
.Orang tua memiliki sedikit gerakan kaki yang bagus dalam memijah semua anak dan mempertahankan pipa dengan benar, tetapi itu tidak terlalu buruk.
Fan-in adalah struktur kebalikannya. Sejumlah proses yang berjalan secara independen perlu menyisipkan masukan mereka ke dalam proses umum. Seorang kolektor tidak mudah menulis, karena harus membaca dari berbagai sumber.
Membaca dari banyak pipa bernama sering dilakukan dengan menggunakan
select
modul untuk melihat pipa mana yang memiliki input tertunda.Solusi 3
Pencarian bersama adalah definisi database.
Solusi 3A - muat database. Biarkan pekerja memproses data di database.
Solusi 3B - buat server yang sangat sederhana menggunakan werkzeug (atau serupa) untuk menyediakan aplikasi WSGI yang merespons HTTP GET sehingga pekerja dapat melakukan kueri ke server.
Solusi 4
Objek sistem file bersama. Unix OS menawarkan objek memori bersama. Ini hanyalah file yang dipetakan ke memori sehingga pertukaran I / O dilakukan alih-alih membaca buffer konvensi.
Anda dapat melakukan ini dari konteks Python dengan beberapa cara
Tulis program startup yang (1) memecah objek raksasa asli Anda menjadi objek yang lebih kecil, dan (2) memulai pekerja, masing-masing dengan objek yang lebih kecil. Objek yang lebih kecil dapat dijadikan acar objek Python untuk menghemat sedikit waktu membaca file.
Tulis program startup yang (1) membaca objek raksasa asli Anda dan menulis file berkode byte terstruktur halaman menggunakan
seek
operasi untuk memastikan bahwa setiap bagian mudah ditemukan dengan pencarian sederhana. Inilah yang dilakukan mesin database - memecah data menjadi beberapa halaman, membuat setiap halaman mudah ditemukan melalui fileseek
.Menelurkan pekerja dengan akses file berstruktur halaman besar ini. Setiap pekerja dapat mencari bagian yang relevan dan melakukan pekerjaan mereka di sana.
sumber
Apakah proses anak muncul melalui objek berbagi multiprosesing yang dibuat sebelumnya dalam program?
Tergantung. Untuk variabel read-only global sering dianggap demikian (selain dari memori yang dikonsumsi) jika tidak.
dokumentasi multiprocessing mengatakan:
Better to inherit than pickle/unpickle
Explicitly pass resources to child processes
Global variables
Contoh
Di Windows (CPU tunggal):
Dengan
sleep
:Tanpa
sleep
:sumber
z
tidak dibagikan. Ini dengan demikian menjawab pertanyaan dengan: "tidak, di bawah Windows setidaknya, variabel induk tidak dibagi antara anak-anak".z
kasus) itu dapat dianggap dibagikan.S. Lott benar. Pintasan multiprosesing Python secara efektif memberi Anda potongan memori yang terpisah dan digandakan.
Pada kebanyakan sistem * nix, menggunakan panggilan tingkat rendah ke
os.fork()
akan, pada kenyataannya, memberi Anda memori copy-on-write, yang mungkin seperti yang Anda pikirkan. AFAIK, secara teori, dalam program yang paling sederhana, Anda dapat membaca dari data itu tanpa membuatnya digandakan.Namun, hal-hal tidak sesederhana itu dalam interpreter Python. Data objek dan meta-data disimpan dalam segmen memori yang sama, jadi meskipun objek tidak pernah berubah, sesuatu seperti penghitung referensi untuk objek yang bertambah akan menyebabkan penulisan memori, dan karenanya akan disalin. Hampir semua program Python yang melakukan lebih dari "print 'hello'" akan menyebabkan peningkatan jumlah referensi, jadi Anda mungkin tidak akan pernah menyadari manfaat dari copy-on-write.
Bahkan jika seseorang berhasil meretas solusi memori bersama dengan Python, mencoba mengoordinasikan pengumpulan sampah di seluruh proses mungkin akan sangat menyakitkan.
sumber
Jika Anda menjalankan di bawah Unix, mereka mungkin berbagi objek yang sama, karena cara kerja fork (yaitu, proses anak memiliki memori terpisah tetapi ini adalah copy-on-write, jadi itu dapat dibagikan selama tidak ada yang memodifikasinya). Saya mencoba yang berikut ini:
dan mendapatkan hasil sebagai berikut:
Tentu saja ini tidak membuktikan bahwa salinan belum dibuat, tetapi Anda harus dapat memverifikasi itu dalam situasi Anda dengan melihat output dari
ps
untuk melihat berapa banyak memori nyata yang digunakan setiap subproses.sumber
Proses yang berbeda memiliki ruang alamat yang berbeda. Seperti menjalankan berbagai contoh penerjemah. Itulah gunanya IPC (komunikasi antarproses).
Anda dapat menggunakan antrian atau pipa untuk tujuan ini. Anda juga dapat menggunakan rpc melalui tcp jika Anda ingin mendistribusikan proses melalui jaringan nanti.
http://docs.python.org/dev/library/multiprocessing.html#exchanging-objects-between-processes
sumber
Tidak terkait langsung dengan multiprocessing itu sendiri, tetapi dari contoh Anda, sepertinya Anda bisa menggunakan modul rak atau semacamnya. Apakah "big_lookup_object" harus benar-benar ada di memori?
sumber
Tidak, tetapi Anda dapat memuat data Anda sebagai proses anak dan mengizinkannya untuk membagikan datanya dengan anak lain. Lihat di bawah.
sumber
Untuk platform Linux / Unix / MacOS, forkmap adalah solusi cepat dan kotor.
sumber