Slide 1

Slide 1 text

Python Parrotと学ぶ Pythonの並列実行 田城幸太

Slide 2

Slide 2 text

今回の内容  Pythonで使える並列実行ライブラリを紹介  threading(スレッドベースの並列実行)  multiprocessing(プロセスベースの並列実行)

Slide 3

Slide 3 text

並列実行って?  その名の通り、複数のコードを同時実行すること。  逐次処理により、1つずつ処理が実行されるが、 それでは1度に1つの処理しか行えない。  コアも1つしか使えない!  使用場面  マルチコアCPUのリソースを有効に使う。(multiprocessing)  I/Oバウンドの間に別な処理を実行する。(threading)

Slide 4

Slide 4 text

使い方  threading.Threadか、multiprocessing.Processクラスを使う。  コンストラクタ引数(すべてキーワード付き引数)  group:常にNoneにする。将来 ThreadGroup クラスが実装されたときの拡張用に予約され ている。  target: やらせたい処理をcallableオブジェクト(関数など)で渡す  args,kwargs:↑に渡したい引数を指定する。  args:キーワードなし引数のタプル  kwargs:キーワード付き引数の辞書型  daemon:デーモンスレッドであるかを指定する。  デーモンスレッド以外のスレッドがすべて終了すると、Pythonプログラム全体が終了する。  Noneにすると、現在のスレッドとおなじになる。

Slide 5

Slide 5 text

使い方2  メソッド  start()  スレッド・プロセスの活動を開始するメソッド。  join()  スレッド・プロセスが終わるまで待機するメソッド。  自分自身のスレッド・プロセスに対してこのメソッドを呼ぶとデッドロックを起こすため エラーになる。 (もしこれが許されれば永遠に待つことになる)  まだ開始していない場合も同様。

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

CPUバウンドの場合  逐次実行  4.848s  threading  5.039s  multiprocessing  1.521s

Slide 11

Slide 11 text

IOバウンドの場合  逐次実行  1.454s  threading  0.558s  multiprocessing  0.574s

Slide 12

Slide 12 text

スレッドとプロセス

Slide 13

Slide 13 text

GIL(グローバルインタプリタロック)  複数スレッドがあっても、同一インタプリタプロセス内では1度に1つのス レッドしかバイトコードを実行できない仕組み。  オブジェクトモデルが同時アクセスに対して暗黙的に安全になる。  おおざっぱに言うなら、threadingモジュールだと1つのコアしか使えない  ただし、標準あるいは外部のいくつかの拡張モジュールは、圧縮やハッシュ計 算などの計算の重い処理をするときに GIL を解除するように設計されている。  Zlibや、hashlibなどがこれに該当。  また、I/O 処理をする場合 GIL は常に解除される。(別スレッドに処理を移せ る)

Slide 14

Slide 14 text

同期プリミティブ  Lock  ロックとアンロック状態があり、デフォルトはアンロック。  一般に、同時アクセスのできないリソースを利用する場合に使う  acquire()  アンロック状態ならロック状態にして即座に処理を戻す(ロックの獲得)  ロック状態なら、アンロック状態になるまで待つ。  release()  ロックをアンロックする。  acquire関数でロックを獲得しようとしているスレッドがあれば、 どれか1つがロックを獲得できる。

Slide 15

Slide 15 text

同期プリミティブ  Semaphore  内部カウンタがあり、インスタンス作成時に初期値を決める  主に、同時に使える数に制限のあるリソースに対して使用する  acquire  内部カウンタが0よりも大きければ、内部カウンタを1つ下げてすぐに処理を返す  内部カウンタが0ならreleaseによって内部カウンタが1以上になるまで待つ  release(n=1)  セマフォを解放して、内部カウンタをn増加させる。

Slide 16

Slide 16 text

同期プリミティブ  Event  真と偽のフラグがあり、デフォルトは偽  主に、事前処理があってその処理を待ってからでないと処理できないスレッドに対 して使う  set()  フラグを真にして、waitメソッドでブロックされているすべてのスレッドを起こす。  wait()  フラグが真なら直ちに処理が戻る  フラグが偽なら真になるまで(setが呼ばれるまで)待ってから戻る  clear(): フラグを偽に戻す  is_set(): フラグの確認

Slide 17

Slide 17 text

同期プリミティブ(with文)  with文を使うことで、withスイート内で例外が起きた場合でも、 ロックを解放してくれる。  これによりロックの解放忘れを防げる!

Slide 18

Slide 18 text

おわりに  Pythonに限らず、並列実行は難しい。  Pythonで並列実行とかってあまり使わないイメージ?  asyncioは比較的使うかも。  Pythonで並列実行やるときの皆様の参考になれば良いです。