Pythonの並行処理(マルチプロセス、マルチスレッド)|サンプルコードで違いを理解する

Pythonの並行処理(マルチプロセス、マルチスレッド)|サンプルコードで違いを理解する 機械学習
Pythonの並行処理(マルチプロセス、マルチスレッド)|サンプルコードで違いを理解する
スポンサーリンク

並行処理を実行させることで、複数の処理を同時に進めることができます。

この記事ではPythonを使った並行処理について説明していきます。

対象読者
  • Pythonで並列処理を実行したい
  • 並行処理の種類がわからない
  • Pythonの並列処理を実行したい

Pythonの並行処理は2つ(マルチプロセス・マルチスレッド)あります。
それぞれどういった特徴があるのか説明します。

次にサンプルコードを実行してそれぞれの並行処理の違いを検証しています。
実装方法も紹介しているので参考にしてください。

並行処理の種類

並行処理の種類

普通にプログラムを実行すると上から順番に実行されます(逐次処理)。
そのため、処理が終わるまで次の処理を実行するのを待たなければいけません

そこで有効なのが「並行処理」です。

並行処理を実行すると、同時に複数の処理を行うことができます。

Pythonには以下の並行処理があります。

  • マルチプロセス
  • マルチスレッド

それぞれについて簡単に説明します。

マルチプロセスについて

並行処理ごとにプロセスを割り当てて実行していく方法です。

プロセスとは「OSがメモリを管理して動くプログラム」のことです。
OSがメモリデータを管理してくれるので、不整合が起こる可能性が低いことが強みです。

たとえばExcelとPowerPointを開いていたら、それぞれで1つずつのプロセスが動くことになります。
アプリ、プログラムを実行している間にそれぞれ動く単位だと思ってください。

マルチプロセスで実行すると、Pythonの処理の中でプロセスを切り分けて、同時に実行することができます!

マルチスレッド

同じプロセス内で並行処理させる方法です。

同じプロセスを使うためメモリの同じ場所にアクセスして、不整合が起こる場合があります
そのためメモリデータを自分で管理しなければいけません。

よくWebサービスなどでユーザが操作している裏で実行させる時など利用されます。

実行して比較する

実行して比較する

以下のパターンで実行して違いを確認していきます。
実装方法(引数の指定方法など)の参考になるので、利用してください。

確認内容
  • 普通に実行(逐次処理)
  • マルチプロセス
  • マルチスレッド

「実行時間」「プロセス」について違いを確認してください。

普通に実行(逐次処理)

5秒停止する3つの関数を実行していき、トータルで処理にかかった時間を計算します。

import time

def test1(word):
  print('test1:start')
  print(word)
  time.sleep(5)
  print('test1:end')
  print('----------------')

def test2(word):
  print('test2:start')
  print(word)
  time.sleep(5)
  print('test2:end')
  print('----------------')

def test3(word):
  print('test3:start')
  print(word)
  time.sleep(5)
  print('test3:end')
  print('----------------')


start = time.time()

test1('test1を実行',)
test2('test2を実行',)
test3('test3を実行',)

end = time.time()


print('%.3f seconds' % (end - start))

出力結果はこのようになります。

test1:start
test1を実行
test1:end
----------------
test2:start
test2を実行
test2:end
----------------
test3:start
test3を実行
test3:end
----------------
15.015 seconds

順番に実行されていることがわかります。
5秒待機する関数を3つ実行しているので約15秒かかりました。

マルチプロセスで実行

同じ内容をマルチプロセスを利用して実行していきます。

import multiprocessing
import time

def test1(word):
  print('test:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test1】PID:' + str(p.pid))
  print('test:end')
  print('----------------')

def test2(word):
  print('test2:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test2】PID:' + str(p.pid))
  print('test2:end')
  print('----------------')

def test3(word):
  print('test3:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test3】PID:' + str(p.pid))
  print('test3:end')
  print('----------------')


start = time.time()

p = multiprocessing.current_process()
print('PID:' + str(p.pid))
print('----------------')

t1 = multiprocessing.Process(target=test1, args=('test1を実行',))

t2 = multiprocessing.Process(target=test2, args=('test2を実行',))

t3 = multiprocessing.Process(target=test3, args=('test3を実行',))

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

end = time.time()


print('%.3f seconds' % (end - start))

出力結果はこのようになりました。

PID:6360
----------------
test:start
test1を実行
test2:start
test2を実行
test3:start
test3を実行
【test1】PID:11763
test:end
----------------
【test2】PID:11764
test2:end
----------------
【test3】PID:11765
test3:end
----------------
5.068 seconds

約5秒で処理が完了しています。

PIDがプロセスを表しています。
実行された順番からみて同時に処理されていることがわかります。

また、PIDが違うことより、実行元から、各関数すべてのプロセスが違うことがわかります

マルチプロセスには「multiprocessing」の「Processクラス」を使用します。
start関数で”target”で指定した関数を実行します。
“target”で実行する関数を指定するのですが、()は書かないことに注意しましょう!

引数は”args”で指定します。

join関数を実行することでスレッドが終わるまで待つようになるので、最後まで実行したい場合に使用してください。
join関数を使用しない場合、並行処理のどれかが終わると同時にjoinしていないプロセスも終了します。

マルチスレッドで実行

次はマルチスレッドで実行します。
マルチプロセスとの違いを確認してください。

import threading
import multiprocessing
import time

def test1(word):
  print('test:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test1】PID:' + str(p.pid))
  print('test:end')
  print('----------------')

def test2(word):
  print('test2:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test2】PID:' + str(p.pid))
  print('test2:end')
  print('----------------')

def test3(word):
  print('test3:start')
  print(word)
  time.sleep(5)
  p = multiprocessing.current_process()
  print('【test3】PID:' + str(p.pid))
  print('test3:end')
  print('----------------')


start = time.time()

p = multiprocessing.current_process()
print('PID:' + str(p.pid))
print('----------------')

t1 = threading.Thread(target=test1, args=('test1を実行',))

t2 = threading.Thread(target=test2, args=('test2を実行',))

t3 = threading.Thread(target=test3, args=('test3を実行',))

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

end = time.time()


print('%.3f seconds' % (end - start))

このように出力されました。

PID:6360
----------------
test:start
test1を実行
test2:start
test3:starttest2を実行


test3を実行
【test1】PID:6360
test:end
----------------
【test2】PID:6360
【test3】PID:6360


test3:end
----------------
test2:end
----------------
5.006 seconds

マルチプロセスの場合と同様、約5秒で処理が完了しています。

PID(プロセス)が同じことがわかります。

「multiprocessing.Process」と「threading.Thread」は同じ処理で実行できるようになっています。

違いは「multiprocessing.Process」はPIDが取得できるが、「threading.Thread」は取得できない点です。
サンプルでは「multiprocessing」を読み込んでいますが、本来は必要ありません

最後に

並行処理を行うことでシステムとしてのスピードを格段にあげることができるケースがあります。

ケースに合わせて「マルチプロセス」と「マルチスレッド」を使い分けて、早く動くシステムを開発していきましょう!

Python初心者の方はPyQで中級者レベルまでスキルをつけることができます!

講座内容
  • Python文法:基礎から実務レベルまで
  • 設計方法:実務向き
  • ライブラリー利用
  • Web開発
  • API開発
  • スクレイピング
  • データ分析と必要な数学
  • 機械学習
  • 統計

Pythonについて多少スキルがある方は『Udemy 』を利用してスキルを高めていくことをオススメします。

こがた
こがた

ぼくもこれまでいろいろな講座を受けて学習してきました。

10万以上の講座があるので、自分の求めている内容のものが必ずあります!

普段はほとんどの講座が1万円以上するのですが、時々セールで1,000円代で購入することができます。
セールを見計って利用しましょう!

最後まで読んでくださり、ありがとうございました!!!

コメント

タイトルとURLをコピーしました