この質問は非常に一般的であり、十分に明確ではない可能性があるため、事前に謝罪する必要があります. 問題は、それ自体がいくつかのサブタスクにプロセスのプールを使用し、大量の I/O 操作を行う Python 関数をどのように並行して実行するかということです。それは有効なタスクですか?
もう少し情報を提供しようと思います。test_reduce()
たとえば、並列に実行する必要があるプロシージャがあります。私はそれを行うためにいくつかの方法を試しましたが (以下を参照)、それらすべてが失敗する理由を理解するための知識が不足しているようです。
このtest_reduce()
手順は多くのことを行います。それらのいくつかは、他のものよりも質問に関連しています(以下にリストします):
multiprocessing
モジュール(sic!)、つまりpool.Pool
インスタンスを使用します。- MongoDB 接続を使用し、
- libs に大きく依存して
numpy
おり、scikit-learn
- コールバックとラムダを使用し、
- ライブラリを使用して、
dill
いくつかのものをピクルスにします。
multiprocessing.dummy.Pool
最初に(スレッドプールのようです)を使用しようとしました。このプールの具体的な内容と、なぜ「ダミー」なのかはわかりません。すべてが機能し、結果が得られました。問題はCPU負荷です。並列化されたセクションでtest_reduce()
は、すべてのコアで 100% でした。同期セクションの場合、ほとんどの場合、約 40 ~ 50% でした。このタイプの「並列」実行の全体的な速度が向上したとは言えません。
次に、この手順のmultiprocessing.pool.Pool
インスタンスを自分のデータに使用しようとしました。map
以下で失敗しました。
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
raise self._value
cPickle.PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed
cPickle
私はそれが原因であると推測しpathos
、はるかに高度な pickler を使用するライブラリを見つけましたdill
。ただし、失敗することもあります。
File "/local/lib/python2.7/site-packages/dill/dill.py", line 199, in load
obj = pik.load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
さて、このエラーは私がまったく理解していないものです。プールで機能する場合、プロシージャからの出力がないstdout
ため、何が起こっているのかを推測するのは困難です。私が知っている唯一のことはtest_reduce()
、マルチプロセッシングが使用されていない場合に正常に実行されることです。
では、これほど重くて複雑なものをどのように並行して実行するのでしょうか?