LXDによるGPUの利用

# 初めに

NVIDIAのA100みたいな高価なGPUを搭載するマシンというのは普通共用のマシンなので、管理者権限を雑に行使してしまうと当然魔境が出来上がる。そこで、利用者それぞれの環境をコンテナで隔離したい、という欲求が出てくることになる。
この記事では、LXDでCUDAを使うための手順をまとめる。基本的には[この記事](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0532?page=3)通りである。

# 環境

ここで触れる手順は、Ubuntu 20.04、LXD 4.0、nvidia-driver-465,CUDA 11.0〜11.3でテストされている。
LXDの初期設定(`lxd init`が終わるまでの手順など)は説明しない。sudoを使わずに済ますためにはlxdグループにユーザを追加する必要が在ることに注意。

# 手順



## ホストマシンへのdriverのインストール

ここで説明する方法では、GPUのドライバ(正確にはドライバを叩くlibraryと思われるが)はコンテナ側と共有されるので、ホスト側でインストールする必要が在る。
`sudo apt search nvidia-driver-*`で最新のドライバが何かをチェックし、それをインストールする。使用できるCUDAのバージョンはドライバのバージョンで制限されるし、場合によっては特定のバージョンだとバグるとかが在るかも知れないのでどれをいれたかというのは気にしたほうが良いだろう。
この記事を書いた時点では最新は465だったので、`sudo apt install nvidia-driver-465`をした。

## libnvidia-containerのインストール

LXDでGPUをコンテナ(dockerも同様である)が使えるようにする(パススルー)には[libnvidia-container](https://github.com/NVIDIA/libnvidia-container)をインストールする必要がある。インストール方法はNVIDIAのレポジトリを追加してインストールする方式をとる。[ここ](https://nvidia.github.io/libnvidia-container/)にやり方が書いてあるので、これに従ってほしい。ここに転記しても古くなったら意味がないので。
インストールしたら`nvidia-container-cli list`でLXDのコンテナ上に展開されるファイルのリストが見れるので動作確認ついでに見てみるとよいだろう。

## LXDでのコンテナの立ち上げ

ここではcuda-devという名前のコンテナを作ることとしよう。つまり、別の名前が良い場合はcuda-devという文字列は置換すること。
まずは普通に`lxc launch ubuntu:20.04 cuda-dev`でコンテナを立ち上げる。この記事の時点のLTSは20.04なので20.04としている。
次にコンテナに接続するGPUを登録するために`lxc config device add cuda-dev A100 gpu`を実行する。A100という文字列はmygpuとか何か一意な文字列なら何でもいい。このコマンドだとホストに接続されているすべてのGPUがコンテナも見えるので、制限したい場合は`id=0`(0は`nvidia-smi`で見えるidを入れればいい)のようにすればよいはずである。(全部見えても困ったことがないのでやったことがない)
次に[libnvidia-container](https://github.com/NVIDIA/libnvidia-container)を有効化するために`lxc config set cuda-dev nvidia.runtime true`を実行する。設定変更の反映にはコンテナの再起動が必要なので`lxc restart cuda-dev`も実行する。
正しく有効化出来たかを確認するには`lxc exec cuda-dev nvidia-smi`を実行すれば良い。`nvidia-smi`もコンテナ内に展開されているため、正しく有効化できていればホスト側のGPUが見えるはずである。

## CUDAのインストール

libnvidia-containerで展開されたファイルは当然コンテナ側のパッケージマネージャの管理下にないので、`apt install cuda`とかでcudaを雑に入れると衝突してしまう。なので、[公式](https://developer.nvidia.com/cuda-downloads)の提供するインストール手段でパッケージマネージャに頼らずにインストールする必要が在る。
[公式](https://developer.nvidia.com/cuda-downloads)で適切にポチポチするとrunfile (local)という選択肢が出てくるので、それのインストール手順をコンテナ上で実行する。LXD一般の話だが、`lxc exec cuda-dev -- bash`だとrootユーザーでシェルに入ってしまうので、それがいやなら`lxc exec cuda-dev -- sudo --login --user ubuntu`とするとデフォルトで存在するユーザである`ubuntu`というユーザとしてログインできる。
CUDAをインストールするときに注意するべきことは**ドライバはインストールしない**ということである。ドライバは既にコンテナの中に展開されているので、インストールしようとすると衝突してしまう。逆に言えば、ドライバ無しでnvccとかのcuda用のものだけ入れるということができるのでrunfile (local)のインストール方法を選んでいる。
動作確認をしたければcudaのsampleとかをやればよいだろう。
このインストール方法ではインストール終了時に出てくるようにパスがデフォルトでは通っていないので、.bashrcとかに適切に記述を追加する必要が在る。ちなみにCUDAの異なるバージョン(11.1と11.3)とかを同時にインストールしても衝突しないので、パスを書き換えるだけで複数のCUDAバージョンを切り替えることができる。

# 実行コードをまとめたもの
古くなったら意味がないと言いつつ一応現時点の最新版をインストールする形でまとめておく。古くなるまでは意味が在るし......

```bash
sudo apt search nvidia-driver-*
sudo apt install nvidia-driver-465
DIST=$(. /etc/os-release; echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo apt-key add -
curl -s -L https://nvidia.github.io/libnvidia-container/$DIST/libnvidia-container.list | \
  sudo tee /etc/apt/sources.list.d/libnvidia-container.list
sudo apt-get update
sudo apt install libnvidia-container-tools
nvidia-container-cli list
lxc launch ubuntu:20.04 cuda-dev
lxc config device add cuda-dev A100 gpu
lxc config set cuda-dev nvidia.runtime true
lxc restart cuda-dev
lxc exec cuda-dev nvidia-smi
lxc exec cuda-dev -- sudo --login --user ubuntu
sudo apt update
sudo apt upgrade
wget https://developer.download.nvidia.com/compute/cuda/11.3.0/local_installers/cuda_11.3.0_465.19.01_linux.run
sudo bash cuda_11.3.0_465.19.01_linux.run
```

# 環境変数

こんなのを.bashrcに追加する。数字はバージョンによって変える。
```
PATH=/usr/local/cuda-11.3/bin:$PATH
LD_LIBRARY_PATH=/usr/local/cuda-11.3/lib64:$LD_LIBRARY_PATH
export CPATH=/usr/local/cuda-11.3/include
```

# 終わりに

準同型暗号の方は鋭意執筆中ということで.......()