0

とにscheduler.py基づく並列タスクランナーである3 つのスクリプトがあります。2 番目のスクリプトは、いくつかのクラスと関数を含むスクリプトであり、最後に、から並列化クラスを作成し、それを のクラスに渡し、全体を実行します。multiprocessing.Processmultiprocessing.Pipesimulation.pyxscheduler.pyscheduler.pysimulation.pyx

ターゲットの並列関数がすべての最上位にある場合は正常に動作しますが、クラス関数でsimulation.pyx使用しようとするとすぐに酸洗エラーが発生します。scheduler.pysimulation.pyx

コードは数千行に及ぶため、概念的なコードのみを示します。

small_main_script.py:

import simulation
import scheduler


if __name__ == '__main__':

    main = simulation.Main()
    scheduler = scheduler.parallel()
    main.simulate(scheduler)


simulation.pyx:

import scheduler

cdef do_something_with_job(job):
...

cdef class Main:
    cdef public ...
    ...

    def __init__(self):
    ...

    def some_function(self,job):
        ...
        do_something_with_job(job)
        ...

    def simulate(self, scheduler):

        for job in job_list:
            scheduler.add_jobs(job)

        scheduler.target_function = self.some_function

        scheduler.run_in_parallel()

問題は、次のような役に立たないダミー関数を使用すると

def sleep(job):
    time.sleep(2)

最上位、つまりクラスの外側に配置すると、並列化は正常に機能しますが、クラス内に配置するとすぐにMain酸洗エラーが発生します。クラスでも定義されている実際のターゲット関数を使用し、Mainそれを最上位に移動したくない場合、同じエラーが発生します。sleep(self,job)クラス内でダミー関数を使用すると、次のようになりますMain。クラスの外にあるときは正常に動作します。

PicklingError: Can't pickle <built-in method sleep of simulation.Main
object at 0x0D4A3C00>: it's not found as __main__.sleep

In [2]: Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main self = load(from_parent)
  File "C:\Python27\lib\pickle.py", line 1384, in load return Unpickler(file).load()
  File "C:\Python27\lib\pickle.py", line 864, in load dispatch[key](self)
  File "C:\Python27\lib\pickle.py", line 886, in load_eof

    raise EOFError
EOFError

私はPython 2.7を使用しています

アップデート

問題をさらに切り分けることができました。サードパーティのパッケージpathos multiprocessingを使用すると、クラス関数をピクルすることができます。問題は、クラス インスタンスである関数引数を使用するとエラーが発生することです。

4

1 に答える 1

1

Python マルチプロセッシングプログラミング ガイドラインから:

ピクル可能性: プロキシのメソッドへの引数がピクル可能であることを確認します。

トップレベルの関数だけがpicklableです。

非トップレベル関数 (クラス/インスタンス メソッド、ネストされた関数など) をピクルするのが難しい理由は、子プロセスで移植可能な方法でそれらを検索するのが難しいためです。実行するインスタンス メソッドを送信しているプロセスは、メソッド自体を所有するオブジェクトについて何も知らない可能性があります。

プログラミングガイドラインが示唆するように:

ただし、通常、パイプまたはキューを使用して共有オブジェクトを他のプロセスに送信することは避けるべきです。代わりに、他の場所で作成された共有リソースへのアクセスを必要とするプロセスが先祖プロセスから共有リソースを継承できるように、プログラムを調整する必要があります。

つまり、メソッドを対象のキーワードに渡すプロセスを作成します。

Pathos ライブラリは pickle プロトコルを拡張し、標準プロトコルがサポートするよりも多くの型をシリアル化できるようにします。

一般に、OOP とマルチプロセッシングを混在させることは推奨されません。これはそれらの1つです。

于 2016-11-16T21:40:11.520 に答える