おはようございます,こんにちは,こんばんは.
機械学習まわりのプログラミングでは並列処理が書けるとかなり効率よく計算を回せます.そこでPythonでの並列処理プログラミングと,そもそも並列処理とは何なのかを勉強してみました.
まずOSにはマルチタスクという機能があります.そしてこのマルチタスク機能を用いて,ブラウザでものを調べながらエディタでコードを書くといったことを実現しています.
マルチタスク機能ではOSに対していくつかのプロセスが入力され,それをOSが各CPUに割り当てていきます.CPUは同時に1つのプロセスしか実行できないので,CPU数以上のプロセスがOSに入力された時は,その割り当て方を細かく切り替えることで全てのプロセスがほぼ常に実行されているようにします.
プログラムを並列に動かすには,子プロセスを複数立ち上げる,スレッドを複数立ち上げるという2通りの方法があります.1つのプロセスには複数のスレッドが存在し,スレッドはCPUでプロセスが実際に実行される単位でもあります.
メモリ(RAM)におけるプロセスは,テキストセグメントとデータセグメントという2つのセグメントに分けられます.テキストセグメントはプログラムの命令列を保持し,データセグメントはプログラム中の各データを保持します.
子プロセスを新規作成すると,テキストセグメントは元のプロセスと同じ部分を参照し,データセグメントは元のプロセスのコピーを作ります.スレッドを新規作成すると,そのスレッドがプログラムのどの部分を実行しているかという情報のみを保持し,その他は元のプロセスと共有します.
マルチプロセスはメモリ領域の独立性が高く安全ですが切り替えにコストがかかります.マルチスレッドは切り替えに要するコストは小さいですが実行されるプログラムがスレッドセーフである必要があります.
Pythonではグローバルインタプリタロック(GIL)という機能によって,安全にthreadingを行うために,同時に実行できるスレッドが1つに制限されています.
また,Pythonではos.fork()でプロセスをフォークできます.
が,os.fork()で並列処理を実装することはあまりなく,実際にはmultiprocessingかJoblibを用いて実装することになると思います.multiprocessingは個人的に使い勝手がよくないと考えているので,Joblibを用いた並列化を行います.multiprocessingは関数の引数に制約がかかるのが苦手です.またJoblibではctrl+cで終了したプログラムの子プロセスまで終了してくれるのが良いですね◎
multiprocessingとJoblibに関してはすでにわかりやすい記事が出ていますので,そちらを参照してください.
Joblibでは以下のようなコードで並列処理を実装します.
import cv2
from joblib import Parallel, delayed
results = Parallel(n_jobs=-1, backend='threading')(delayed(cv2.imread)(image_path) for image_path in image_file_path)
n_jobs: 使用するCPUの数(multiprocessing時)もしくはスレッドプールの数を指定します.-1を指定することで使用可能な最大のCPU数もしくはスレッドプール数をしようしてくれます.
backend: どのように並列化するかを指定します.'multiprocessing' or 'threading' or 'loky'で,lokyが何かはよくわかりません.
戻り値は与えた関数の戻り値がlist型で帰ってきます.
では機械学習タスクあるある,画像の読み込みを実行してみましょう.データはKaggleのPetFinderコンペの訓練画像を用いました.今回の実験ではmultiprocessingとthreadingの両方を指定し,速度を比較してみました.以下がコードと表示された結果です.(手元のMacBookProでの実行結果)
[標準出力]
[baseline] done in 38.777 s
[Joblib threading] done in 17.031 s
[Joblib multiprocessing] done in 34.848 s
今回の画像読み込みではthreadingによる並列化がもっとも適しているようです.multiprocessingはデータセグメントのコピーの作成に時間を要したのでしょうか,普通に書いたコードからそこまで高速化されていません.単純にマルチプロセス化しただけでは早くならないため,随時タスクに適した形で並列化する必要がありそうです.
というわけで今回はPythonを用いた並列処理に関して学びました.
機械学習ではデータの読み込み・前処理・特徴量生成などあらゆる過程で並列化による恩恵を受けられるはずですので,是非とも並列化処理を導入しましょう.