Ubuntu 18.04にGeForceを積んで遊んでみる（1：リモートでCUDAとOpenGLが使えるようにする）

自分用の実験環境構築のメモだけど、誰かの参考になればいいね。

# OSのインストール、基本的な設定
何はともあれUbuntuをインストールする。WindowsPCからインストール環境を用意する手段としては、

* isoファイルを拾ってくる → Win32DiskImagerでUSBメモリに書き込む → ぶっさして起動

が一番手っ取り早いか？
Ubuntuのインストールはあまり悩むことがなくて楽である。以下、インストール方法の選択で「通常のインストール」を選んだ前提で話を進める。

インストール後に行った基本的な作業のメモ：

* インストール後、```sudo apt-get update```と```sudo apt-get upgrade```をしておく。
* sshアクセスできた方が便利（コピペ操作とかが楽）なので```sudo apt-get install openssh-server```しておく。
* sshログインして、公開鍵認証環境を構築し、パスワードログインを却下しておく。（お約束過ぎるので詳細省略）
* （自分の作業のしやすさの都合で）ディレクトリ名を英語に変更：```LANG=C xdg-user-dirs-update --force```
* インストール直後のUbuntuはgccすら入っていない状態。あらかじめいくつかインストールしておくと良い。
 * CUDAドライバの導入に必要：```gcc make```
 * OpenGLで遊ぶのに使う：```libgles2-mesa freeglut3-dev```
 * 数値計算で遊ぶ予定なので：```libopenblas-dev```
 * 「必要」かどうかは知らないが：```lightdm```
 * IPアドレスの確認に便利なifconfigは```net-tools```に入っている

# CUDA導入
本家からインストーラ一式を拾ってくる。今回使ったのは```cuda_10.0.130_410.48_linux.run```。
```sudo systemctl set-default  multi-user.target```でGUIを止めてから、上記runファイルをsudo実行……と思ったのだが、うっかり忘れてGUI起動したまま実行してもインストールできた。
基本的にGUIを止めてからやるべき。例によってOS起動後に```telinit 3```でCUIへ、```telinit 5```でGUIへの移行も可能。


```
===========
= Summary =
===========

Driver:   Installed
Toolkit:  Installed in /opt/cuda-10.0
Samples:  Installed in /home/hoge, but missing recommended libraries
```
※ライブラリが足りない旨のメッセージが出ているが、とりあえず放っておく。

念のためrebootし、起動後に```nvidia-smi```コマンドでGPU情報を取得できることを確認した。

```
$ nvidia-smi
Wed Jan 30 13:44:35 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.48                 Driver Version: 410.48                    |
|-------------------------------+----------------------+----------------------+
| 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 RTX 2080    Off  | 00000000:1C:00.0  On |                  N/A |
| 24%   36C    P8     6W / 215W |     61MiB /  7949MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0       942      G   /usr/lib/xorg/Xorg                            59MiB |
+-----------------------------------------------------------------------------+
```

ちなみに、kernelなどを更新すると、nvidia関係のモジュールが読み込まれなくなって各種GPU関連処理ができなくなる。CUDAインストールに使ったkernelを使うようにするか、再度インストーラを実行すると良い。

この時点でディスプレイ設定などを行うNVIDIA X Server Settingsが利用可能になる。（デスクトップのアプリ一覧から起動できる。）ここで「OpenGL Settings」の「Sync to VBlank」をオフにしてディスプレイリフレッシュレートとの同期を切っておかないと、ベンチマーク系アプリでFPSがリフレッシュレートまでしか上がらないという問題に躓くので変更しておくと良い。


# VirtualGL+TurboVNCでリモートOpenGL
## 導入
[VirtualGL on Ubuntu · aancel/admin Wiki · GitHub](https://github.com/aancel/admin/wiki/VirtualGL-on-Ubuntu)
上記を参考に、VirtualGL+TurboVNCをインストールする。
githubからvirtualgl_2.6.1_amd64.debを入手し、```sudo dpkg -i virtualgl_2.6.1_amd64.deb```。
```/opt/VirtualGL/bin/vglserver_config```を叩いてセットアップ。

```
$ sudo /opt/VirtualGL/bin/vglserver_config

1) Configure server for use with VirtualGL
2) Unconfigure server for use with VirtualGL
X) Exit

Choose:
1

Restrict 3D X server access to vglusers group (recommended)?
[Y/n]
y

Restrict framebuffer device access to vglusers group (recommended)?
[Y/n]
y

Disable XTEST extension (recommended)?
[Y/n]
y
... Creating vglusers group ...
... Creating /etc/opt/VirtualGL/ ...
... Granting read permission to /etc/opt/VirtualGL/ for vglusers group ...
... Creating /etc/modprobe.d/virtualgl.conf to set requested permissions for
    /dev/nvidia* ...
... Attempting to remove nvidia module from memory so device permissions
    will be reloaded ...
rmmod: ERROR: Module nvidia is in use by: nvidia_modeset
... Granting write permission to /dev/nvidia-modeset /dev/nvidia0 /dev/nvidiactl for vglusers group ...
... Granting write permission to /dev/dri/card0 for vglusers group ...
... /etc/X11/xorg.conf has been saved as /etc/X11/xorg.conf.orig.vgl ...
... Modifying /etc/X11/xorg.conf to enable DRI permissions
    for vglusers group ...
... /etc/gdm3/Init/Default has been saved as /etc/gdm3/Init/Default.orig.vgl ...
... Adding vglgenkey to /etc/gdm3/Init/Default script ...
... /etc/lightdm/lightdm.conf has been saved as /etc/lightdm/lightdm.conf.orig.vgl ...
... Adding greeter-setup-script=vglgenkey to /etc/lightdm/lightdm.conf ...

Done. You must restart the display manager for the changes to take effect.

IMPORTANT NOTE: Your system uses modprobe.d to set device permissions. You
must execute rmmod nvidia with the display manager stopped in order for the
new device permission settings to become effective.


1) Configure server for use with VirtualGL
2) Unconfigure server for use with VirtualGL
X) Exit

Choose:
x
```

nvidiaのmoduleが使用中でエラーが出ている、が、設定作業自体はできている？rmmodしても、ランレベルをmulti-userにして再起動してからrmmodしても、unloadできない。問題が起きないことを祈ってこのままスルー。

```
$ sudo rmmod nvidia
rmmod: ERROR: Module nvidia is in use by: nvidia_modeset
$ sudo rmmod nvidia_modeset
rmmod: ERROR: Module nvidia_modeset is in use by: nvidia_drm
$ sudo rmmod nvidia_modeset_drm
rmmod: ERROR: Module nvidia_modeset_drm is not currently loaded
```

インストール時のrecommendedでvglusersというグループに属しているユーザでないとVirtualGLが使えない設定になっているため、```sudo usermod -a -G vglusers username```などで追加する。（そもそも「そのような設定」にしない方が手っ取り早い気もする？）

さらにTurboVNCもインストール。```sudo dpkg -i ./Downloads/turbovnc_2.2.1_amd64.deb```
再起動して、vncserver起動。
パスワード文字列長が8に制限されている（何故……）のを忘れて長いのを打ってしまい、入れ直した。
なお、novaは実際のホスト名、usernameは本当は異なるユーザ名。

```
$ /opt/TurboVNC/bin/vncserver -depth 24

You will require a password to access your desktops.

Password:
Warning: password truncated to the length of 8.
Verify:
Passwords do not match. Please try again.

Password:
Verify:
Would you like to enter a view-only password (y/n)? n

Desktop 'TurboVNC: nova:1 (username)' started on display nova:1

Creating default startup script /home/username/.vnc/xstartup.turbovnc
Starting applications specified in /home/username/.vnc/xstartup.turbovnc
Log file is /home/username/.vnc/nova:1.log
```

生成されるlogファイルを覗くと

```
Listening for VNC connections on TCP port 5901
Listening for HTTP connections on TCP port 5801
```

といった行が見えるはずなので、WindowsにTurboVNCクライアントをインストールして当該ホストのポート5901に接続してみたら、ログインできた。
（カラープロファイルの認証とかが出てくるが、とりあえず何も気にせずパスワードを入れて認証した。）


## 動作確認
OpenGLのテストを行い状況を確認してみることにする。

VirutalGLに付属のglxsphere64（/opt/VirtualGL/bin/glxspheres64）はOpenGLレンダリングで描画を行いFPSを表示してくれる。

本体デスクトップ上の端末でコマンドを叩けばもちろん画面に映像が表示される。

ssh接続状態で同様に実行するには、```DISPLAY=:0 /opt/VirtualGL/bin/glxspheres64```とDISPLAY環境変数を指定すれば良い。起動元はsshだが、映像は直接接続されている画面になる。

VNCデスクトップ上の端末から実行すると、VNCデスクトップ上で動く。また、場所を問わず（VNCでもsshでも、それこそ本体デスクトップ上でも）```DISPLAY=:1 /opt/VirtualGL/bin/glxspheres64```とすると、VNCのデスクトップに表示される。実際にクライアントがVNC接続していなくても、サーバー側が立ち上がっていれば動く。ただし、```OpenGL Renderer: llvmpipe (LLVM 6.0, 128 bits)```と表示され、とても遅い。

VNC経由でGPUを叩く（GPUによるOpenGLレンダリング高速化をして、VNCデスクトップ上に表示する）には、```DISPLAY=:1 vglrun /opt/VirtualGL/bin/glxspheres64```とvglrun経由で動かせば良い。```OpenGL Renderer: GeForce RTX 2080/PCIe/SSE2```と表示され、かなりマシになる。だがやはり、「直接」と比べるとかなり遅い。改善策はあるのだろうか？


glmark2というOpenGLベンチマークも試してみたが（```sudo apt-get install glmark2```でインストール）glxsphere64と状況はとくに変わらず。vglrunを経由すればVNCデスクトップ上でも動かせるが、性能は今ひとつ。

# nvidia-dockerで遊ぶ
長くなってきたので別記事に書く。