なろう分析記録

『小説家になろう』をふくめ『ネット小説投稿サイト』を分析する。コード置き場,主にPython,javascript,たまに創作。

【Python】joblibを用いて簡単に『並列処理』を行う方法

今回はPythonのjoblibパッケージを用いて手軽に並列処理を行う方法をご紹介したいと思います。

f:id:karupoimou:20200305195926p:plain:w400
joblib


『Joblib』とは

Joblibパッケージはデータの外部保存や並列処理・並行処理などを簡単に行うために用いるパッケージです。
現在市販されているPCのCUPはマルチコア・マルチスレッドを機能を持つものが一般的となっていますが、デフォルトのPythonではそのうちの1スレッドしか処理に用いられないので、大抵の場合リソースを持て余すことになります。

そこでJoblibを用いた並列処理です。

並列処理を行うことでCUPのリソースをフル活用し、同時に複数の処理を走らせることが出来る様にできます。

Joblibのイメージ

joblibの処理の流れとしては『あるリスト』を『ある関数』に送り、最終的に「処理結果のリスト」を得るといった感じです。

f:id:karupoimou:20200305195926p:plain
イメージ

処理の内容によっては途中で早い・遅いと行ったことが生じますが、最終的にはリストの順番に沿った結果リストが返ってきます。

準備

pip

pip install joblib

並列処理のサンプルコード

import joblib

data_list = [1,2,3,20,100]

# 計算する関数
def process(num):
    big_num = num*10
    return big_num
    
# joblibによる並列処理
export_data_list = joblib.Parallel(n_jobs=-2, verbose=2)( [joblib.delayed(process)(num) for num in data_list] )

display(data_list)
display(export_data_list)

f:id:karupoimou:20200305201937p:plain:w400
結果

コードの説明

data_list = [1,2,3,20,100]

まず投入するリストを用意し

# 計算する関数
def process(num):
    big_num = num*10
    return big_num

次に処理の関数を作成

# joblibによる並列処理
export_data_list = joblib.Parallel(n_jobs=-2, verbose=2)( [joblib.delayed(process)(num) for num in data_list] )

最後にこの部分で並列処理を実行しています。

n_jobs=-2

この部分では使用するスレッド数を指定しています
ここをもし「-1」とすればシステムにおけるスレッドを全部使用する形となり、「-2」とすると1つ空きをあけた上で残りのスレッドを使用する形となります

verbose=2

これは途中経過の表示設定です。0~10まで設定可能であり、0の場合は無表示、1~10の場合は数字が大きくなるごとに表示の頻度が上がります。

[joblib.delayed(process)(num) for num in data_list]

ここで、「process」という関数に対して、data_listを投入しています。

最終的に出来上がった結果は「export_data_list」に収められます。

追記

joblibでグローバル変数を扱う方法

プロセス間で変数を共有したい場合、グローバル変数を使う方法が考えられますが、joblibのデフォルト設定ではその方法は使えません。

しかし、Paralleの設定に

require='sharedmem'

を足すことで、参照関数内のglobal変数を扱うことが出来るようになります

サンプルコード

import joblib
import sys

data_list = [1,2,3,20,100]
all_num = 2

# 計算する関数
def process(num):
    global all_num
    
    big_num = num*10
    all_num = all_num + num
    
    return big_num
    
# joblibによる並列処理
export_data_list = joblib.Parallel(n_jobs=-2, verbose=2, require='sharedmem')( [joblib.delayed(process)(num) for num in data_list] )
print(all_num)

[f:id:karupoimou:20200421161143p:plain:400]
結果

参考ページ

own-search-and-study.xyz
「n_jobs=」や「verbose=」といったjoblibの引数についてはこちらのページが参考になります

qiita.com

ohke.hateblo.jp