並列処理
前回、numpyのリストの要素の順番をずらす「roll」を紹介しました。
今回は並列処理のライブラリconcurrent.futuresで返り値を取得する方法を紹介します。
concurrent.futuresはこちらの記事で紹介していますが、並列処理(マルチスレッド、マルチプロセス)を行えるライブラリです。
今回、色々とやってみたのですが、どうしてもマルチプロセスのProcessPoolExecutorがうまくいかなかったため、ThreadPoolExecutorでの返り値の取得方法を紹介します。
それでは始めていきましょう。
返り値が取得できない?!
最初に
from concurrent.futures import ThreadPoolExecutor
x_list = range(5)
y_list = range(5, 10)
def calc(x, y):
sums = x + y
return sums
sums_list = []
with ThreadPoolExecutor(max_workers=4) as executor:
for x, y in zip(x_list, y_list):
sums = executor.submit(calc, x, y)
sums_list.append(sums)
print(sums_list)
数値のリストを二つ作り、それらから一つずつ要素を取得し、計算する関数(calc)内で足し合わせ、その結果をリストsums_listに格納し、最後に表示しています。
これを実行するとこのような結果が得られます。
[<Future at 0x10b9a4be0 state=finished returned int>, <Future at 0x10b9a4e80 state=finished
returned int>, <Future at 0x10b9a4b20 state=finished returned int>, <Future at 0x10b7f5db0
state=finished returned int>, <Future at 0x10b7f60e0 state=finished returned int>]
一応、結果が取得できているようですが、何がなんだか分かりません。
submiの場合は「.result()」で結果を取得
では返り値を取得するにはどうしたらいいでしょうか。
ThreadPoolExecutorのsubmitで実行した場合は、その返り値に「.result()」を付けてあげることで、その値を取得することができます。
from concurrent.futures import ThreadPoolExecutor
x_list = range(5)
y_list = range(5, 10)
def calc(x, y):
sums = x + y
return sums
sums_list = []
with ThreadPoolExecutor(max_workers=4) as executor:
for x, y in zip(x_list, y_list):
sums = executor.submit(calc, x, y).result()
sums_list.append(sums)
print(sums_list)
実行結果
[5, 7, 9, 11, 13]
返り値が複数の場合
返り値が複数であっても「.result()」を使うことで、いつもの「return」と同じく、複数の変数を準備することで取得可能です。
from concurrent.futures import ThreadPoolExecutor
x_list = range(5)
y_list = range(5, 10)
def calc(x, y):
sums = x + y
times = x * y
return sums, times
sums_list = []; times_list = []
with ThreadPoolExecutor(max_workers=4) as executor:
for x, y in zip(x_list, y_list):
sums, times = executor.submit(calc, x, y).result()
sums_list.append(sums)
times_list.append(times)
print(sums_list)
print(times_list)
実行結果
[5, 7, 9, 11, 13]
[0, 6, 14, 24, 36]
map関数も利用可能
また関数に受け渡す値のリストがある場合、map関数を使って一度に受け渡すことも可能です。
map関数に関してはこちらの記事で解説していますので、よかったらどうぞ。
気をつけるべきことはmap関数と同じく「list()」でリスト化することと、受け渡したリスト内の要素が一つずつ処理されるので返り値の取得に一工夫が必要な場合があることです。
ここでは返り値を一つにするために「return (sums, times)」というように返り値をタプルに格納しています。
from concurrent.futures import ThreadPoolExecutor
x_list = range(5)
y_list = range(5, 10)
def calc(x, y):
sums = x + y
times = x * y
return (sums, times)
sums_list = []; times_list = []
with ThreadPoolExecutor(max_workers=4) as executor:
result_list = executor.map(calc, x_list, y_list)
print(list(result_list))
実行結果
[(5, 0), (7, 6), (9, 14), (11, 24), (13, 36)]
次回はf文字列の際に「{}(波括弧、中括弧)」を使い方法を解説していきます。
ではでは今回はこんな感じで。
コメント