株式会社ACCESS Advent Calendar 2018の20日目の投稿です。
会社のAdvent Calendarですが、完全にネタです。
Google Colaboratory 上でVNCサーバを動かしたい!?
Google Colaboratory 良いですよね(以下略。詳しくはこちら
Google Colaboratory で、強化学習をしようとして障害になるのが、画面を出せないという事です。
せっかくゲーム等を解いているのに、プレイ画面が見れないようでは意味がありません。
そこで、ChainerRL を Colaboratory で動かす
では、画面の画像をアニメーションに変換して、Notebook上に表示していました。
動作の様子はこちらからも確認できます。
ですが、これではリアルタイムに見ているわけではないので、面白くありません。いや、リアルタイムで見る意味なんてないんですが、とにかく面白くありません。
なので、Colaboratory上で、VNC Serverを立てて動作させられないか、と思ったので、色々やってみました。
と思って調べていたら、 https://github.com/KiranArun/Reinforcement_Learning-101-demo でまさにそういうことをやっている人がいた!
ので、この記事は、上記レポジトリでやっている内容を解説しているだけです。
上記レポジトリにもNotebookがありますが、もう少しシンプルにした以下のNotebookで動作を確認しました。
こんな感じで動作しています。
インストール
細かいaptやpipでインストールしているもの意外に、以下を入れています。
-
apt
- xvfb <== 仮想フレームバッファー。OpenGLを動かすのに必要
- freeglut3-dev <== OpenGLを動かすのに必要
- その他いろいろ
-
VNC
- TurboVNC : VNC server
- NoVNC : ブラウザでVNCを見れるビューワ
- websockify : WebSocket を使って、TCPへブリッジするライブラリ。NoVNCの一部みたいなもの
-
Ngrok
- ローカルに立てたサーバー中継してくれるサービス
VNCのインストールは大変だったのでサボって上記リポジトリにあるスクリプトを使っています。
VNCサーバーを起動
ここはどうも謎があります。
最初の
!kill $(ps ax | grep websockify | grep -v grep | awk '{ print $1 }') >/dev/null
!pkill ngrok
!pkill vncserver
!pkill Xvnc
!pkill Xvfb
!pkill x11vnc
は念のため、関連するプロセスをKillしておきます。
以下では、VNCサーバーを起動し、ngrokを起動し、ウインドウシステム(openbox)を起動しています。
! timeout 5 /opt/websockify/run 5901 --web=/opt/noVNC --wrap-mode=ignore -- /opt/TurboVNC/bin/vncserver :1 -securitytypes otp -otp -noxstartup 2>/dev/null
get_ipython().system_raw('python /opt/websockify/run 5901 --web=/opt/noVNC --wrap-mode=ignore -- /opt/TurboVNC/bin/vncserver :1 -securitytypes otp -otp -noxstartup > /content/.vnc/stdout 2>&1 &')
get_ipython().system_raw('/opt/ngrok http -config=/content/config.yml 5901 &')
! sleep 1
get_ipython().system_raw('DISPLAY=:1 openbox &')
なぜか、VNCサーバーを2回起動しているのは、、謎です。ですが、こうしないとうまく動作しませんでした。
get_ipython().system_raw()
を使っているのは、バックグラウンドで動作させるためです。(通常の、!
はバックグラウンドで動作できない)
ブラウザでアクセス
そして、ブラウザでnoVNCにアクセスします。/content/.vnc/stdout にワンタイムパスワードが出力されているのでそれを使います。また、http://localhost:4045/api/tunnels を見ると、NgrokのPublic URLが見れるので、それにアクセスします。
!grep "one-time password:" /content/.vnc/stdout
import requests
import json
r = requests.get("http://localhost:4045/api/tunnels", headers={"content-type": "application/json"})
print(r.json()['tunnels'][0]['public_url'])
OpenGLを使うためXvfbを起動
ここまでの所で、VNCサーバーは起動しているのですが、Open AI Gymを動かすことはできません。
というのも、Open AI Gymの多くの環境が、OpenGLを使っているためです。
OpenGLを動かすのは骨なので、、Xvfbで仮想ディスプレイを作成し、さらにそこにVNCサーバーを起動します。
そして、VNC Viewerを起動し、そのXvfbの画面を表示しています。
get_ipython().system_raw('/usr/bin/Xvfb :99 -screen 0 768x1024x24 &')
!sleep 1
get_ipython().system_raw('/usr/bin/x11vnc -rfbport 5902 -forever -display :99 &')
!sleep 1
get_ipython().system_raw('DISPLAY=:1 /usr/bin/vncviewer localhost:5902 &')
!sleep 1
get_ipython().system_raw('DISPLAY=:99 xterm &')
うーん、これ、最初から、Xvfb のサーバーをnoVncでラップして、Ngrokで公開すればこの入れ子要らないような。。と思うのですが、試していないです。
ChainerRLを動かしてみる
以降のセルは、ChainerRLを動作させるためのものです。
まとめ
上記で、Colaboratory上でVNCサーバーを動かすことができました。
が、、全然お手軽じゃないですし、特に意味が無い気がしています。。
明日は、@Yam3939 さんです!