6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Docker上のPython環境で並列処理してみたら、CPU数の設定で意外と手間取った

Last updated at Posted at 2018-11-18

使用環境

OS:Windows10 (Home Edition)
CPU数 : 4
メモリ容量:16GB

DockerにてUbuntu 18.04.1環境のコンテナを作成し、その上で実行した。

普通に実行

import numpy as np

def sum_from_one(N):
    sum = 0
    for i in range(1, N+1):
        sum += i

    return sum

if __name__ == "__main__":
    sum_list = []
    repeat_list = np.random.permutation(np.arange(1, 10001))
    for i in repeat_list:
        sum_list.append(sum_from_one(i))```

実行結果

%%timeit
    ...: %run nojoblib.py
2.27 s ± 15.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

joblibを使ってみる

<参考>
https://qiita.com/Yuhsak/items/1e8533343cf5458e2e08

from joblib import Parallel, delayed
import numpy as np

def sum_from_one(N):
    sum = 0
    for i in range(1, N+1):
        sum += i

    return sum

if __name__ == "__main__":

    repeat_list = np.random.permutation(np.arange(1, 10001))

    r = Parallel(n_jobs=-1)([delayed(sum_from_one)(i) for i in repeat_list])

実行結果

In [21]: %%timeit
    ...: %run joblib_test.py
2.13 s ± 13.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

… あれ?ほとんど変わらない???

タスクマネージャーを見ても、joblibありなしともにCPU使用率が最大でも25%程度。
むしろ、25%で頭打ちになっている感さえあったので、
https://linux.just4fun.biz/?%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/CPU%E3%82%B3%E3%82%A2%E6%95%B0%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B
を参考に認識コア数を調べてみたところ、

# cat /proc/cpuinfo | grep processor
processor       : 0

はい、本来4つあるうちの一つしか使われてませんでした。

どうやらDockerの設定の問題のようだったので、いったんdocker-machineを終了した後でこちらのサイト
https://qiita.com/niisan-tokyo/items/2d7d21aeb4e25f7a7bbe
を参考に、VirtualBoxマネージャーから設定を変更した。
上記ページではシステム>マザーボード>メインメモリで最大メモリ容量を調整していましたが、
今回はシステム>プロセッサー>プロセッサー数で最大使用コア数を4まで上げました。
スクリーンショット 2018-11-18 16.07.41.png
…なんか、「無効な設定が見つかりました」って出てるけど、初期設定に戻しても出てくるから気にしない。
ついでに最大メモリも10GBくらいまで増やしておく。

これでもう一回Docker Quickstart Terminalを立ち上げ、コンテナをもう一回起動して使用CPU数を確かめてみたところ、

# cat /proc/cpuinfo | grep processor
processor       : 0
processor       : 1
processor       : 2
processor       : 3

今度はちゃんと認識されてました。

改めて先ほどのプログラムを走らせます。
繰り返し回数が10000回程度だと並列化の効果が少しわかりにくかったので100000回にしました。
(ただし、計測のiterationは一回に)

# joblibなし
In [1]: %run -t nojoblib.py

IPython CPU timings (estimated):
  User   :     206.52 s.
  System :       1.38 s.
Wall time:     207.92 s.

# joblib使用
In [2]: %run -t joblib_test.py

IPython CPU timings (estimated):
  User   :       4.12 s.
  System :       0.04 s.
Wall time:      62.30 s.

無事実行時間が約1/3まで減りました。

1/4にならないのはI/O待ちとかその辺でしょうか?

multiprocessingモジュール

ついでに、multiprocessingモジュールも使ってみました。

from multiprocessing import Pool
import multiprocessing as multi
import numpy as np

def sum_from_one(N):
    sum = 0
    for i in range(1, N+1):
        sum += i

    return sum

if __name__ == "__main__":

    repeat_list = np.random.permutation(np.arange(1, 100001))

    p = Pool(multi.cpu_count())
    p.map(sum_from_one, repeat_list)
    p.close()
In [1]: %run -t multiprocess_test.py

IPython CPU timings (estimated):
  User   :       0.40 s.
  System :       0.16 s.
Wall time:      62.38 s.

実行時間はたいしてjoblibと変わらないみたいです。

参考

6
8
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
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?