Python ProcessPool Executor

Python学習【365日チャレンジ!】230日目のマスターU(@Udemy11)です。

あなたは、欲しいものリストを作っていますか?

欲しいものリストを作ることって結構重要で、欲しいものリストを作って、毎日そのリストを眺めながら、手に入れたときの自分の状態を想像していると、そのうち欲しいものを手に入れることができます。

少しスピリチュアルな話になりますが、人間の脳って、毎日繰り返し強烈にインプットしていると、その情報が無意識にすり込まれて、欲しいものを手に入れるまでの道のりを勝手に整理して、その行動を起こさせるんです。

欲しいものリストだけでなく、やりたいことリストも作って、すでにやりたいことを実現したかのように毎日具体的に想像を繰り返すことで、脳が無意識に実現までの交通整理をして、やりたいことの実現に向かった行動を選択するようになるんです。

重要なのは、具体的に強烈に継続して脳にすり込むことです。

ほんと【継続は力なり】という言葉は間違いないんですよね。

ということで、今日もPython学習を始めましょう。

昨日の復習

昨日は、スレッドでの並列処理を簡単にできるthreadPoolExecutorについて学習しました。

threadmultiprocessingを使って並列処理をするよりも簡単なコードにできるのがthreadPoolExecutorでした。

詳細については、昨日の記事をごらんください。

今日は、プロセスの並列処理を簡単にできるProcessPoolExecutorを学習します。

ProcessPoolExecutor

早速ProcessPoolExecutorを使った並列処理のコードを書いていきます。

import concurrent.futures
import logging

logging.basicConfig(
    level=logging.DEBUG, format='%(processName)s: %(message)s'
)

def worker(x, y):
    logging.debug('start')
    r = x + y
    logging.debug(r)
    logging.debug('end')
    return r

if __name__ == '__main__':
    with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor:
        f1 = executor.submit(worker, 2, 5)
        f2 = executor.submit(worker, 2, 5)
        logging.debug(f1.result())
        logging.debug(f2.result())

昨日のコードとほぼ同じですので、変更した部分だけ確認します。

まず5行目のロギングでthreadNameprocessNameに変更しています。

次に、10行目をx * yからx + yに変更しました。

最後に重要なところですが、16行目のThreadPoolExecutorProcessPoolExecutorに変更しています。

今回はロギングの出力と計算を掛け算から足し算に変更しましたが、スレッドとプロセスの変更だけなら基本的に、16行目の変更だけで、スレッドの並列処理からプロセスの並列処理に変更することができます。

実行結果

ForkProcess-1: start
ForkProcess-1: 7
ForkProcess-1: end
ForkProcess-2: start
ForkProcess-2: 7
ForkProcess-2: end
MainProcess: 7
MainProcess: 7

変更した計算とプロセス名が並列処理で出力されています。

map

スレッドと同様に、mapもプロセスに変更してみます。

import concurrent.futures
import logging

logging.basicConfig(
    level=logging.DEBUG, format='%(processName)s: %(message)s'
)

def worker(x, y):
    logging.debug('start')
    r = x + y
    logging.debug(r)
    logging.debug('end')
    return r

if __name__ == '__main__':
    with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor:
        args = [[2, 2], [5, 5]]
        r = executor.map(worker, *args)
        logging.debug(r)
        logging.debug([i for i in r])

こちらも変更点は同じで、昨日学習したスレッドのコードで、5行目はprocessName、10行目は足し算、16行目はProcessPoolExecutorに変更しています。

実行結果

MainProcess: <generator object _chain_from_iterable_of_lists at 0x7fd1140244d0>
ForkProcess-1: start
ForkProcess-1: 7
ForkProcess-1: end
ForkProcess-2: start
ForkProcess-2: 7
ForkProcess-2: end
MainProcess: [7, 7]

スレッド名からプロセス名の出力にしているので、MainProcessForkProcessに変更されて、計算も足し算になっているのがわかるかと思います。

今日は。。。

今日の学習は少しさぼってしまったような感じですが、基本的にスレッドと全く同じコードでプロセスの並列処理も扱えるのがPoolExecutorということですね。

酒井さんの講座は、今日までで並列化のセッションが終了です。

Udemy講師 酒井さん プログラミング Python

並列化で学習しなければならないことはもっとたくさんあるのだと思いますが、基本的なことを学習して、実践に入ったときにより深い内容を理解していったほうが効率がよいので、改めて今日まで学習してきた並列処理のセッションを見直してみてください。

明日からは新しいセッションの学習に進みたいと思います。

それでは明日もGood Python!