#流れ
僕:今まであまり変数の多くない学習を機械学習を試していたが,弊ラボには折角GPU4枚刺しマシンがあるので,tensorflow-gpuを使ってみよう.
僕:ついでに心新たにtensorflow2.0のkerasを使ってみよう.
僕:openaigymのtaxiでこんな感じに...
僕:さ~て学習は進んでいるかな???
PC:ターミナル「強制終了」
僕:え?
PC:強制終了!
決まって120学習ステップくらいで停止するのであった.
#環境
OS:ubuntu18系
GPU:GTX1080x4枚
python:3.6.9(Anaconda)
cudnn:7.6.0
cudatoolkit:10.0.130
以下使用したニューラルネットワーク構成
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 1, 10) 5000
_________________________________________________________________
reshape (Reshape) (None, 10) 0
_________________________________________________________________
dense (Dense) (None, 50) 550
_________________________________________________________________
dense_1 (Dense) (None, 50) 2550
_________________________________________________________________
dense_2 (Dense) (None, 6) 306
=================================================================
Total params: 8,406
Trainable params: 8,406
Non-trainable params: 0
_________________________________________________________________
#結論から言うと・・・
強制終了前にネットワークを適宜保存.
繰り返しプログラム回して学習という力業.
とりあえずこれでなんとかなる.
#解決するまでに試したこと(こっちの方が為になった)
##linuxのログを確認
tensorflowがエラーを吐いてくれているならターミナル上にメッセ―ジで問題を伝えてくれるが,今回の場合は唐突に
強制終了
の文字が表れた.
こういう時はやはりまずはlogを確認する.
sudo cat /var/log/syslog
Oct 27 18:27:41 hoge kernel: [1056250.835731] Out of memory: Kill process 1034 (python) score 949 or sacrifice child
Oct 27 18:27:41 hoge kernel: [1056250.835735] Killed process 1034 (python) total-vm:133873604kB, anon-rss:47517436kB, file-rss:440992kB
Out of memory: Kill processおせっかいにもメモリを心配してプロセスを強制終了をしてくれたこいつのことをoom killerなんて巷では言うらしい.
僕:そんなにメモリー必要なネットワークじゃないと思うんだけど・・・
##GPU使用状況確認&メモリ確認
nvidia-smi #GPUの使用状況が分かる
free #メモリの使用状況が分かる
top #他ユーザー含めてプロセスの確認
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.67 Driver Version: 418.67 CUDA Version: 10.1 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 108... Off | 00000000:05:00.0 On | N/A |
| 47% 78C P2 72W / 250W | 625MiB / 11178MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 1 GeForce GTX 108... Off | 00000000:06:00.0 Off | N/A |
| 39% 71C P2 59W / 250W | 149MiB / 11178MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 2 GeForce GTX 108... Off | 00000000:09:00.0 Off | N/A |
| 35% 67C P2 58W / 250W | 149MiB / 11178MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 3 GeForce GTX 108... Off | 00000000:0A:00.0 Off | N/A |
| 29% 62C P2 56W / 250W | 149MiB / 11178MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 1808 G /usr/bin/X 168MiB |
| 0 2567 G compiz 171MiB |
| 0 15131 C python 273MiB |
| 1 15131 C python 137MiB |
| 2 15131 C python 137MiB |
| 3 15131 C python 137MiB |
+-----------------------------------------------------------------------------+
nvidia-smiを実行すると上記のような出力がある.
注目すべきはMemory-Usage
今回載せているのはメモリ確保の設定変更後の学習中の様子なのでGPUは一枚だけかつ600MiB程度で学習が行えている.
oom killerが動作時はこれが10000MiB近い値が出てしまっていた.
それでもステップ序盤は止まらなかった・・・どうするとkillされるのか.
freeの出力を観察しているとなんとなくそれが分かった.
total used free shared buffers cached
Mem: 49374704 43332596 6042108 37000 67152 808784
-/+ buffers/cache: 42456660 6918044
Swap: 7999484 1564196 6435288
こちらがfreeの出力.これも修正後(問題発生時を再現するのがめんどくさかった).
oom killerが発動するまでになにが起きていたのかというと
ステップが進むたびにusedが爆上がり,そしてとあるタイミングでSwapが0に落ちる.
僕:で??
Swapメモリについてやlinuxのメモリ確保の仕組みバッファキャッシュ確保の仕組みについてggりましたが,今回どういう流れでoom killerが働いたのかまではわかりませんでした...
読者:いや,結局そこわからんのかい!
僕:またわかったら追記します...
##ところで実際ニューラルネットワーク作るのに必要なメモリってどれくらいなの?
[https://nori-life-log.com/nn%E3%81%AE%E5%AD%A6%E7%BF%92%E3%81%A7%E5%BF%85%E8%A6%81%E3%81%AAgpu%E3%83%A1%E3%83%A2%E3%83%AA%E3%82%92%E7%AE%97%E5%87%BA%E3%81%99%E3%82%8B]
こちらのブログで紹介されている式より
必要メモリ量(byte)
=(ニューロンの数 × Batch Size + パラメータ数) × 2 (data & grad) × 4(byte)
これを僕のネットワークで計算すると...約95000Byte
強化学習でtarget networkとreplay memory採用してても知れてる.
そう,ここで気づく.
僕:いや,GPU占有しすぎじゃね??
##tensorflowのGPU確保設定の変更
gpu_devices = tf.config.experimental.list_physical_devices('GPU')
if len(gpu_devices) > 0:
for i in range(len(gpu_devices)):
tf.config.experimental.set_memory_growth(gpu_devices[i], True)
print('memory growth:', tf.config.experimental.get_memory_growth(gpu_devices[i]))
memory_growthをTrueにすると解決した.
これがFalseだとGPUの使用可能スペースをフルで確保してしまい,oomkillerを呼び出す羽目になる.
tensorflow2.0ではGPU1枚ずつこれを設定できるので,for文で全てのGPUについて設定しておいた.
#まとめ
oom killerによって学習プロセスを途中で強制終了されるのは強化学習の性質上仕方ないか?途中でモデルをクリアしてメモリ解放なんてことを画像処理系モデルでは推奨されているが強化学習では環境であったりエージェントであったりをクリアすることはできないので難しそう.
実際にメモリの必要量を推定してみたり,linuxのメモリシステムについて再度いろいろ調べて勉強になりました.(実はtensorflowのmulti_gpu_modelとかも試したけどまるで見当違いだったので省略しました)
本当は実装に関する記事を書きたかったのでそれはまた今度書きます.