LoginSignup
32
25

More than 5 years have passed since last update.

Pythonのmultiprocessing.Poolが使いやすくなっていた件

Last updated at Posted at 2018-11-29

Pythonでのmultiprocessing

Python2.6から導入されたmultiprocessing.Poolを用いることで実現できます。

実行可能コア数の取得(指定)

Poolインスタンスの生成

マルチプロセス実行する関数の引数を用意

実行

use_multi.py
from multiprocessing import Pool
import multiprocessing as multi


def calc(n): # マルチプロセス実行したい関数
    return n * n


def main():
    n_cores = multi.cpu_count()  # 実行可能コア数の取得
    p = Pool(n_cores)
    args = list(range(10))  # fugaに与える引数のリスト
    res = p.map(calc, args)  # マルチプロセスの実行 
    print(res)  # 各プロセスで実行した関数の戻り値がリストで返ってくる


if __name__ == "__main__":
    main()
$ python use_multi.py
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

便利だけど痛い制約があった

マルチプロセス実行する関数が

  • クラスのインスタンスメソッド
  • 匿名関数
  • 関数中で定義した関数

の場合にはpickle関連のエラーが出て使用できませんでした。

use_multi.py
from multiprocessing import Pool
import multiprocessing as multi


class Calc:

    def square(self, n):
        return n * n

    def calc_square_usemulti(self, args):
        n_cores = multi.cpu_count()
        p = Pool(n_cores)
        res = p.map(self.square, args)
        print(res)


def main():
    calc = Calc()
    args = list(range(10))
    calc.calc_square_usemulti(args)


if __name__ == "__main__":
    main()
3.2以前
$ python use_multi.py
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

Python 3.3.7から対応された模様

どうやらmethodがpickle可能になったらしく、インスタンスメソッドでも問題なく利用できるようになりました。オブジェクト指向プログラミング等にも使用できるのは大変嬉しいですね。

3.3以降
$ python use_multi.py
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

終わりに

最初、昔はインスタンスメソッド等をmultiprocessing.Poolで使うとエラーが出るということを知らずに使っていたんですよね。ある日、別なエラーで色々調べているうちにインスタンスメソッド等は使えないという記事ばかり出てきて、なんで自分は使えているんだろう?と疑問に思って調べてみて発覚しました。ネットには対応した等の記事がなかったので一応まとめました。

32
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
25