Saya menyesal tidak dapat mereproduksi kesalahan dengan contoh yang lebih sederhana, dan kode saya terlalu rumit untuk dikirim. Jika saya menjalankan program di shell IPython bukan Python biasa, semuanya berjalan dengan baik.
Saya mencari beberapa catatan sebelumnya tentang masalah ini. Mereka semua disebabkan oleh penggunaan pool untuk memanggil fungsi yang didefinisikan dalam fungsi kelas. Tapi ini tidak terjadi pada saya.
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 313, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
Saya sangat menghargai bantuan apa pun.
Pembaruan : Fungsi saya acar didefinisikan di tingkat atas modul. Padahal itu memanggil fungsi yang berisi fungsi bersarang. yaitu, f()
panggilan g()
panggilan h()
yang memiliki fungsi bersarang i()
, dan saya menelepon pool.apply_async(f)
. f()
, g()
, h()
Semua didefinisikan di tingkat atas. Saya mencoba contoh sederhana dengan pola ini dan itu berhasil.
dill
dan memanfaatkanpathos
. Namun, saya tidak beruntung dengan salah satu solusi ketika bekerja dengan vtkobjects :( Adakah yang telah berhasil menjalankan kode python dalam pemrosesan paralel vtkPolyData?Jawaban:
Berikut adalah daftar apa yang bisa diasinkan . Secara khusus, fungsi hanya dapat dipilih jika mereka didefinisikan di tingkat atas modul.
Sepotong kode ini:
menghasilkan kesalahan yang hampir identik dengan yang Anda posting:
Masalahnya adalah bahwa
pool
semua metode menggunakan amp.SimpleQueue
untuk melewati tugas ke proses pekerja. Segala sesuatu yang melewatimp.SimpleQueue
harus dapat dipilih, danfoo.work
tidak dapat dipilih karena tidak ditentukan di tingkat atas modul.Itu dapat diperbaiki dengan mendefinisikan fungsi di tingkat atas, yang memanggil
foo.work()
:Pemberitahuan yang
foo
dapat dipilih, karenaFoo
ditentukan di tingkat atas danfoo.__dict__
dapat dipilih.sumber
pool = Pool()
baris di sini ). Saya tidak berharap itu, dan ini mungkin menjadi alasan mengapa masalah OP berlanjut.functool.partial
ke fungsi tingkat atas juga dapat dilakukan oleh acar, bahkan jika fungsi tersebut ditetapkan di dalam fungsi lain.Saya akan menggunakan
pathos.multiprocesssing
, bukanmultiprocessing
.pathos.multiprocessing
adalah garpumultiprocessing
yang menggunakandill
.dill
dapat membuat cerita bersambung hampir apa saja dengan python, sehingga Anda dapat mengirim lebih banyak secara paralel. Thepathos
garpu juga memiliki kemampuan untuk bekerja secara langsung dengan beberapa fungsi argumen, yang Anda butuhkan untuk metode kelas.Dapatkan
pathos
(dan jika Anda sukadill
) di sini: https://github.com/uqfoundationsumber
sudo pip install git+https://github.com/uqfoundation/dill.git@master
dansudo pip install git+https://github.com/uqfoundation/pathos.git@master
sudo
(dari sumber eksternal seperti github khususnya). Sebaliknya, saya akan merekomendasikan untuk menjalankan:pip install --user git+...
pip install pathos
tidak bekerja dengan sedih dan memberikan pesan ini:Could not find a version that satisfies the requirement pp==1.5.7-pathos (from pathos)
pip install pathos
sekarang berfungsi, danpathos
python 3 kompatibel.multiprocess
adalah sebuah garpu dimultiprocessing
manadill
telah digantipickle
di beberapa tempat dalam kode ... tetapi pada dasarnya, itu saja.pathos
menyediakan beberapa lapisan API tambahanmultiprocess
dan juga memiliki backend tambahan. Tapi, itulah intinya.Seperti yang orang lain katakan
multiprocessing
hanya dapat mentransfer objek Python ke proses pekerja yang dapat diasamkan. Jika Anda tidak dapat mengatur ulang kode Anda seperti yang dijelaskan oleh unutbu, Anda dapat menggunakandill
kapabilitas pickling / pembongkaran yang diperluas untuk mentransfer data (terutama data kode) seperti yang saya perlihatkan di bawah ini.Solusi ini hanya memerlukan instalasi
dill
dan tidak ada perpustakaan lain sepertipathos
:sumber
dill
danpathos
penulis ... dan sementara Anda benar, bukankah jauh lebih bagus dan bersih dan lebih fleksibel untuk digunakanpathos
seperti dalam jawaban saya? Atau mungkin saya agak bias ...pathos
pada saat penulisan dan ingin memberikan solusi yang sangat dekat dengan jawabannya. Sekarang saya telah melihat solusi Anda, saya setuju bahwa ini adalah cara untuk pergi.Doh… I didn't even think of doing it like that.
Jadi itu agak keren.for
loop eksplisit . Saya biasanya melihat paralel paralel mengambil daftar dan mengembalikan daftar tanpa loop.Saya telah menemukan bahwa saya juga dapat menghasilkan output kesalahan persis pada sepotong kode yang berfungsi dengan baik dengan mencoba menggunakan profiler di atasnya.
Perhatikan bahwa ini ada di Windows (di mana forking agak kurang elegan).
Saya berlari:
Dan menemukan bahwa menghapus profil menghapus kesalahan dan menempatkan profil mengembalikannya. Membuatku batty juga karena aku tahu kode yang digunakan untuk bekerja. Saya sedang memeriksa untuk melihat apakah ada sesuatu yang diperbarui pool.py ... kemudian punya perasaan tenggelam dan menghilangkan profil dan hanya itu.
Posting di sini untuk arsip seandainya ada orang lain yang melihatnya.
sumber
pass
tidak 'acar'.Ketika masalah ini muncul dengan
multiprocessing
solusi sederhana adalah beralih dariPool
keThreadPool
. Ini dapat dilakukan tanpa perubahan kode selain imporIni berfungsi karena ThreadPool berbagi memori dengan utas utama, daripada membuat proses baru - ini berarti pengawetan tidak diperlukan.
Kelemahan dari metode ini adalah bahwa python bukan bahasa terbaik dengan penanganan utas - ia menggunakan sesuatu yang disebut Global Interpreter Lock untuk menjaga agar utas tetap aman, yang dapat memperlambat beberapa kasus penggunaan di sini. Namun, jika Anda terutama berinteraksi dengan sistem lain (menjalankan perintah HTTP, berbicara dengan database, menulis ke sistem file) maka kode Anda kemungkinan tidak terikat oleh CPU dan tidak akan mendapatkan banyak hasil. Bahkan saya telah menemukan ketika menulis tolok ukur HTTP / HTTPS bahwa model berulir yang digunakan di sini memiliki lebih sedikit overhead dan penundaan, karena overhead dari membuat proses baru jauh lebih tinggi daripada overhead untuk membuat thread baru.
Jadi, jika Anda memproses banyak hal dalam ruang python pengguna ini mungkin bukan metode terbaik.
sumber
Ini juga berfungsi untuk array numpy.
sumber
Kesalahan ini juga akan datang jika Anda memiliki fungsi inbuilt di dalam objek model yang diteruskan ke pekerjaan async.
Jadi pastikan untuk memeriksa objek model yang dilewati tidak memiliki fungsi bawaan. (Dalam kasus kami, kami menggunakan
FieldTracker()
fungsi django-model-utils di dalam model untuk melacak bidang tertentu). Inilah tautan ke masalah GitHub yang relevan.sumber
Membangun solusi @rocksportrocker, Masuk akal untuk mengisi saat mengirim dan MEMULIHKAN hasilnya.
sumber