LoginSignup
3
7

More than 3 years have passed since last update.

python multiprocessing の使い方(続) Pool編

Last updated at Posted at 2020-04-18

pythonでmultiprocessingの使い方を調査しています。
先ほど投稿した記事の調査の続き。別プロセスで動かしたい関数をProcess で一つ一つ起動するのでなく、まとめて実行してくれる関数Pool を利用します。

  • 並列処理で使用するコアの数(上限数)を指定できる。
  • 指定した処理を別コアで動かしてくれる。感じ。
  • 並列処理をしたい関数が同じで引数が違うだけの時、Pool を使って簡単に書ける。

を確認しました。

テストコード

  • CPUの数は cpu_count() で取得できる
  • Pool(num_cpu) で Pool のインスタンスを作り、`map(method, iterable_arg)

from multiprocessing import Pool, cpu_count
from time import sleep
from os import getpid, getppid
from numpy import exp, log

def f(args):
    print("[{}---{}] args {}".format(getpid(), getppid(), args))
    if isinstance(args, dict):
        y = args["x"]
    elif isinstance(args, int):
        y = args
    retValue =0.0
    try:
        sleep(1)
        for i in range(1000000):
            retValue = retValue/float(i+1) + log(exp(y * y + 1) - 0.1)
        print("here=", 100/0.0)
    except Exception as e:
        print("[{}---{}]  {}".format(getpid(), getppid(), e))
        raise e
    finally:
        print('[{}---{}] return: {}'.format(getpid(), getppid(), retValue))
        return(retValue)

if __name__ == "__main__":
    print("main pid={} cpu_count={}".format(getpid(), cpu_count()))
    p = Pool(6) # プロセス数を指定する
    try:
        result = p.map(f, [{"x":1}, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10])  # リストで引数を指定する
        print(result)
    except Exception as e:
        print("main", e)

実行結果

ちゃんとCPUを分けて使ってくれています。8コアのPCですが、Pool(10) としてもエラーは出ません。8個すべてを使って全力で処理してくれているようです。

コメント 2020-04-18 163925.jpg

他に気が付いたこと。基礎知識が無いので実験的に学んでいます。汗;

  • プロセスIDは再利用されている。(ので、関数の実行のunique な識別には利用できませんね。)
  • 発生したException は親プロセスではキャッチされない。(そりゃそうか)
  • mapで実行させる関数の引数は、型が違ってもOK。map はIterable なもので、実行させる関数できちんと処理をしていれば。

またCPU数については、ドキュメントには
multiprocessing.cpu_count() については、APIの説明で

This number is not equivalent to the number of CPUs the current process can use. The number of usable CPUs can be obtained with len(os.sched_getaffinity(0))

と書かれていましたが、私が実行したときは、os.sched_getaffinity(0)はいつも {0, 1, 2, 3, 4, 5, 6, 7} でした。CPUの割り当て方とか何か実装方法があるのかな。

参考にさせていただいた情報

来週、何とかなるといいな。
(2020/04/18)

追記(2020/04/18 17:40)
- よく読むと、Pool を使うときはwith Pool(processes=4) as pool: としたほうが良いみたい。with を抜けるときにPool のprocessが close されるみたい。

3
7
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
3
7