使用環境
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まで上げました。
…なんか、「無効な設定が見つかりました」って出てるけど、初期設定に戻しても出てくるから気にしない。
ついでに最大メモリも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と変わらないみたいです。
参考