読者です 読者をやめる 読者になる 読者になる

Itsukaraの日記

最新IT技術を勉強・実践中。最近はDeep Learningに注力。

DRLでの格安なGCP Preemptible VM Instanceの利用方法

DRL(Deep Reinforcement Learning)の環境としてGoogle Cloud Platform(GCP)の無料枠($300まで and 2ヶ月まで無料)を使っていますが、当方のDRL環境に合ったマシン(4CPU+8GBメモリ)を通常通り使用すると$90/月掛かるため、$300では3台月強が上限となります。そこで、同じ構成でも格安($27/月)で使えるPreemptible VM Instanceを使うことにしました。これで10台月(5VMx2ヶ月で使う予定)まで使えます。

Preemptible VMは格安ですが、GCPのリソースが少なくなると勝手に停止される可能性があり、また、24時間で必ず停止されます。当方のDRL環境は、途中で止めても再開できるので、止まっているVMの検出・再起動を手動で行えば問題ありません。しかし、これは手間がかかるので、再起動を自動化しました。これにより、無料枠内で、3倍強のリソースが使えるようになりました。

今後、同じことを再実施する可能性もあるので、実施内容をメモに纏めました。

VMでのDRLプログラム起動・停止の自動化

  • VM作成画面で「管理、ディスク、...」をクリックし詳細表示

f:id:Itsukara:20161015184232p:plain

  • 詳細で、プリエンプティブをオンに設定(後での変更は不可)

f:id:Itsukara:20161015191310p:plain

f:id:Itsukara:20161015184705p:plain

#!/bin/bash
export run_dir=/home/itsukara21/async_deep_reinforce
export run_command=run-option-gym
export runset=montezuma-k-tes30-b0020-ff-fs2

# comment out this line after set up abobe lines
#exit

export PATH=".:/home/itsukara21/anaconda3/bin:$PATH"
cd /home/itsukara21/
echo "`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S` Start up!" >> start.log

cd $run_dir

export log=log.`hostname`.$runset
nohup $run_command $runset &>> $log &
(sleep 100; nohup report $log &>> report.log )&
(sleep 150; nohup run-avconv-and-rm nr-screen &>> avconv1.log )&
(sleep 300; nohup run-avconv-and-rm new-room-screen &>> avconv2.log )&
  • 当方の停止スクリプトの例(kill -2で学習データがsaveされる)
#!/bin/bash
#/home/itsukara21/shutdown-script

cd /home/itsukara21/

MY_COMMAND="python a3c.py"

echo "`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S` Shutting down!  Seeing if ${MY_COMMAND} is running." >> shutdown.log

# Find the process with command line $MY_COMMAND
PID="$(pgrep -f "$MY_COMMAND")"

if [[ "$?" -ne 0 ]]; then
  echo "`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S` ${MY_COMMAND} not running, shutting down immediately." >> shutdown.log
  exit 0
fi

echo "`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S` Sending SIGINT to $PID"
kill -2 "$PID"

# Portable waitpid equivalent
while kill -0 "$PID"; do
   sleep 1
done

echo "`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S` $PID is done, shutdown" >> shutdown.log

VM再起動の自動化

  • DeepLearning用のVMを監視するためのVMを作成(マシンAとする)
    • gcpの場合、マシンタイプとしてmicroを選べば$5弱/月で済む
    • Amazon EC2の場合、t2.microなら1年間無料で利用可(当方の選択)
  • マシンAにGoogle Cloud SDKをインストール
    • 下記サイトを参考にすれば直ぐにできる
      • http://www.task-notes.com/entry/20151019/1445223600
      • マシンAがHeadlessの場合、「ブラウザの使えないサーバーや仮想マシン内での認証方法」を参考にする
        • マシンAの画面に表示されたURLをローカルマシンのブラウザで開き認証すると、Google Cloud SDKアクセス許可画面が表示されるので、「許可」を押すと認証コードが表示される。これをマシンAで入力
      • プロジェクトIDは、1つしか表示されなければそれを使い、複数の場合はGCPコンソールの左上に表示されるプロジェクトIDを確認
      • 複数のzoneやregionを使う場合、これらに対する質問は、最後の選択肢「Do not set default zone等」の番号を入力
  • 止まっているVMを検出・再起動するスクリプトを作成し、マシンA上でnohupで走らせる
    • 当方が使っている素朴なクリプトは下記(host名やzoneは直打ち)
#!/bin/bash
hosts=(gcp001 gcp002 gcp003 gcp004 gcp005)
zones=(us-west1-a us-west1-b us-east1-a us-east1-b us-central1-a)
while true
do
  echo "*** check status of compute instances and start if not RUNNING ***"
  for (( i = 0; i < ${#hosts[@]]}; ++i ))
  do
    host=${hosts[$i]}
    zone=${zones[$i]}
    status=`gcloud compute instances describe $host --zone $zone | grep status`
    echo -n "[`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S`] $host $status"
    if [ "$status" = "status: RUNNING" ]; then
      echo " => OK"
    else
      echo " => NG => try to start it"
      gcloud compute instances start $host --zone $zone
      status=`gcloud compute instances describe $host --zone $zone | grep status`
      echo  "[`export TZ=JST-9;date +%Y/%m/%d-%H:%M:%S`] $host $status"
    fi
  done
  sleep 400
done

あとがき

上記により、計算リソースを格安で使えるので、GCP無料枠を最大限に活用することができそうです。これで、計算リソースに対する不安は少し解消されました。

ただ、Azureに比べるとGCPは遅いです。Azureでの学習速度は1.1M steps/hourぐらい出ていたのですが、GCPでは0.7M steps/hourぐらいしか出ません。CPU数やメモリ量は同じなので、単純にGCPの1CPUの性能が低いのだと思います。

ちなみに、自宅PC(3年ぐらい前の中堅PCで4コア+hyperthreading+GPU)では1.7M steps/hourぐらい出るので、自宅PCと比べると40%程度の性能ですね。遅い!