クラスの内部で並列処理を利用したメソッドを利用する
やりたいこと
pythonクラスで、並列処理を利用したメソッドを実装したい。
つまり、classの中で、multiprocessing.Pool
を利用したい。
しかし、普通のやり方ではできない。そこで、ちょっとした工夫が必要になる。
※ ただし、multiprocessing.Process
ならメソッドで使える。ただし、 multiprocessing.Process
はプロセスの管理とか面倒なのだ
解決法
通常、クラスの中で、multiprocessing.Pool
を利用したメソッドを書き、別のメソッドを並列処理させようとすると、エラーがでる。
PicklingError: Can't pickle : attribute lookup __builtin__.instancemethod failed
つまり、「引数が展開できへんで〜」と言っている。これはmultiprocessing.Pool
の仕様なのだ。
じゃあ、どうするか、っていうと、クラスの外部に引数を展開して、目的のクラスメソッドを呼び出して、値を返す関数を定義することになる。
動かないコード
from multiprocessing import Pool import time class C: def f(self, name): 並列処理をしたいメソッド def run(self): pool = Pool(processes=2) pool.map(self.f, [1, 2, 3, 4]) if __name__ == '__main__': c = C() c.run()
ここで、self.f
をcallせずに、「メソッドfをクラスメソッドとして呼び出す関数」を作成する
from multiprocessing import Pool import time def unwrap_self_f(arg, **kwarg): # メソッドfをクラスメソッドとして呼び出す関数 return C.f(*arg, **kwarg) from multiprocessing import Pool import time class C: def f(self, name): 並列処理をしたいメソッド def run(self): pool = Pool(processes=2) pool.map(unwrap_self_f, [1, 2, 3, 4]) if __name__ == '__main__': c = C() c.run()
こうすると、動いてくれる。
ちなみに、この内容はここ の英訳みたいなもんです。