久しぶりの更新です.ここんとこ,忙しかったり風邪引いたり マンボウが絶滅危惧種に指定 されたりでへろへろやったもので.そんなわけで,11月はじめにやってた話を忘れんうちにメモ.
大量の画像をデータとした Deep Learning をやろうとすると,学習データ全部をメモリに置いとくわけにいかへんので,ディスクからの読み込み → 前処理 → 学習というステップをミニバッチ単位とかで繰り返すことになります.そうすると,ディスクからの読み込みに時間がかかるせいで,読み込み+前処理と学習のそれぞれにかかる時間が同じくらい,せっかくGPU使って学習してんのにGPUは半分くらい遊んでる状態,っていう悲しいことになりかねません.
というわけで,読み込み+前処理と学習を並列化しましょう.この条件やと,読み込み+前処理と学習をそれぞれ別のスレッドにするのがよさげです.少し調べてみたら,こんな記事がありました:
それから,こちらは Python のマニュアル:
- 16.2. threading — 高水準のスレッドインタフェース — Python 2.7ja1 documentation
- 8.10. queue — 同期キュークラス — Python 2.7ja1 documentation
これらを参考に自分でもプログラムを書いてみました.画像の読み込みうんぬんは後で考えることにして,とりあえずマルチスレッドの動作確認用に作ったプログラムがこちら:
'sub'が読み込み+前処理を,'main'が学習を担当するって想定.'sub' のスレッドから'main'のスレッドへデータを渡すのにキューを使って,'sub'の方の処理が速かったり遅かったりしてもある程度(qsize分)は吸収できるようにしてみました.このプログラムでは,main_st < sub_st だと 'sub' の方が律速段階になり,main_st > sub_st だと逆に 'main' の方が律速になります.
main_st = 0.2, sub_st = 2 だとこんなん.
sub: 0 sub: main: 01 sub: 2 main: 1 sub: 3 main: 2 sub: 4main: 3 sub: 5 main: 4 sub: 6main: 5 sub: 7 main: 6 sub:main: 8 7 sub: 9 main: 8 main: 9 # elapsed time: 20.2274708748 [sec]
表示が重なってわかりにくいですが,subの方が遅いので,subがひとつエンキューするとすぐにmainがそれをデキューしてます.
main_st = 2, sub_st = 0.2 だとこんなん.
sub: 0 sub: 1 main: 0 sub: 2 sub: 3 sub: 4 main: 1 sub: 5 main: 2 sub: 6 main: 3 sub: 7 main: 4 sub: 8 main: 5 sub: 9 main: 6 main: 7 main: 8 main: 9 # elapsed time: 20.2381651402 [sec]
こちらはmainが遅いので,最初はキューが一杯になるまでsubの処理が進んで,後はmainがひとつデキューするたびにsubが一つエンキューすることになってます.
とりあえず今日はここまで.実際に画像を読み込むプログラムも作ったんですが,そっちの話はいずれまた.