3

奇妙な問題に遭遇しました。私が知る限り、データを変数に代入するという実際の行為は、私のプログラムに大きな遅延を引き起こしています。インスタンス変数に割り当てたいデータを実際に構築するのにかかる時間を測定したところ、平均で約 0.7 秒でした。self.data = data大規模な遅延が発生するのは、割り当てようとしたときだけです(たとえば)。

編集:

上記の仮定は正しくありませんでした。変数の割り当て中にハングしていませんでした。への呼び出しの前後にタイマーを追加しましたbuild_dataが、時間はごくわずかです。

__init__遅延は、終了しrunて呼び出される間に何らかの形で発生します。

更新されたクラス

これがクラスのコードです。__init__の最後に開始し、 の最初の呼び出しで停止するタイマーを追加しましたrun()。2 つの間に 50 秒の遅延があります。

class Worker(multiprocessing.Process):
    def __init__(self, queue, image): 
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.data = self.build_data(image)
            self.start_time = time.time()

    def run(self): 
        print 'I finally reached the run statement!'
        print "Time taken:", time.time() - self.start_time
        print "Exiting {}".format(self.name)

そしてbuild_data機能。

        def build_data(self, im): 
            start_time = time.time()
            size, data = im.size, list(im.getdata())
            data = [data[x:size[0] + x] for x in range(0, len(data), size[0])]
            print 'Process time:', time.time() - start_time
            return data

誰がこれを引き起こしているのか知っていますか?

ワーカープールのコード:

if __name__ == '__main__':
    im = ImageGrab.grab()
    queue = multiprocessing.Queue()
    workers = [] 
    for i in range(1): 
        w = Worker(queue, im)
        w.start()
        workers.append(w)


    print 'waiting for workers to join'
    for i in workers: i.join()

部分的な解決策:

Toreks の提案で、 にmultiprocessing渡されるすべての引数が pickle 化可能であると述べているのプログラミング ガイドラインに目を通しました__init__。内部に関する私の理解は非常に曖昧ですが、コードの遅延は、巨大なネストされたリスト構造が渡されたときにピクル/アンピクルされていたことだと思います__init__(ただし、その事実は完全に間違っている可能性があります)。

からデータを移動し、__init__後で割り当てることで、問題は完全に解消されました。もう遅延はありません。

作業コード:

class Worker(DataStore):
    data = None
    def __init__(self, queue, image): 
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.img = image
        self.start_time = time.time() 


    def run(self):
        self.assign_data(self.img)
        print 'I finally reached the run statement!'
        print "Time taken:", time.time() - self.start_time
        print "Exiting {}".format(self.name)


    @classmethod
    def assign_data(cls, im): 
        size, data = im.size, list(im.getdata())
        cls.data = [
            data[x:size[0] + x] for x in range(0, len(data), size[0])
        ]
    

dataそのため、変数をクラス スコープに移動build_dataし、@classmethod. すべてがスムーズに動作するようになりました。

4

0 に答える 0