Oracle Cloud (OCI) で GPU の VM インスタンスを CentOS で使おう

# 1. 目的
Oracle Cloud Infrastructure(以降 OCI と表記します)では、GPU を搭載した VM やベアメタルのインスタンスを利用することが可能です。

OCI では GPU インスタンスを利用する際に必要な CUDA を事前インストールした以下 OS イメージを提供しております(2019/02/12 現在時点)。
- Ubuntu 16.04
- Oracle Linux 7.x
- Windows Server 2012 R2

残念ながら、上記以外の OS については CUDA をインストールするところから始める必要があります。

今回は CentOS 7 を利用した場合の CUDA のインストールから GPU の認識まで試してみたいと思います。

# 2. ゴール
- CentOS 7 に CUDA 10 をインストールする
- CUDA をインストールした CentOS のカスタムイメージ(OSテンプレートのようなもの)を作成する
- 作成したカスタムイメージからベアメタルの GPU インスタンスを作成してみる


# 3. 環境作成
## 3-1. リソースの確認
OCI ではデフォルトでは一部のインスタンスの種類しか作成することができません。
事前に自分のアカウントで GPU がどのリージョンのどのアベイラビリティドメイン(以降AD)作成できるか確認します。今回は Ashbrun リージョンで進めていきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/71bc33a6-1500-82ef-4d69-002583161d98.png)

Compute をクリックして展開します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/4cd87840-5559-e6c1-f314-1aa8e6cc354f.png)

us-ashburn の AD-1 に VM.GPU2.1 インスタンスのリソースが 1つあることが分かりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/f441380a-aa21-a1d5-4226-8e5fd4e631de.png)

## 3-2. ネットワーク作成
続いて、GPU インスタンスを配置するネットワークを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/af7dcd31-b0a3-e778-dacc-5634d34292e4.png)

既存のネットワークが一つありますが、今回は新たに作成しますので、 Create Virtual Cloud Network をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/e56ecbdb-03e0-702d-e7e7-16dfb066d3e9.png)

NAME を任意で入力し、CREATE VIRTUAL CLOUD NETWORK PLUS RELATED RESOURCES にチェックをします。
これをチェックすると自動的に Subnet を3つ作成し、Internet から SSH に必要なコンポーネントが自動で設定されます。今回は検証なので、こちらが非常にラクチンです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/791be7af-8023-480c-79ff-0985291964b2.png)

下にスクロールして、Create Virtual Cloud Network ボタンをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/e7e352af-59fa-d0e3-c8ce-16464c5c28fb.png)

作成できました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/cdd573ea-0331-b449-2e20-08521d409669.png)


## 3-3. GPU の VM インスタンス作成
今回目的の GPU の VM インスタンス作成をしていきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/7f93723f-2107-b730-152e-11381ec9809a.png)

Create Instance をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/d74cf418-5339-18ca-460d-42def7a628fa.png)

インスタンス名を任意で決めます。アベイラビリティドメインは先程確認した AD-1 を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/b23be409-9b60-ba59-2f1b-99a8e385f876.png)

今回のポイント、OS を選択します。デフォルトでは Oracle Linux が選択されますので、これを変更します。Change Image Source をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/0e39e633-a504-d4df-4850-fa39c9938d59.png)

リストが表示されるので CentOS 7 を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/3f4fb9a8-00de-a91d-2991-e9d1f3c4f069.png)

下にスクロールして、 Select Image をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/af4047d8-677e-a640-d99f-4ce49e1d1c08.png)

これで CentOS 7 に変わりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/6a60d0d3-c35b-11c1-e9b2-513419497ce2.png)

続いて Instance Type を選択します。 VM と Bare Metal が選べますが、今回は VM を選択します。
Instance Shape がデフォルトでは VM.Standard2.1 なので、Change Shape を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/740bf8f6-5ca2-c643-7e56-d7833d6ad825.png)

VM.GPU2.1 を選択して、Select Shape をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/1cd1db85-f228-286d-0910-583c693976cd.png)

VM.GPU2.1 に変更されました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/06f6c20f-c997-2b96-98be-83fad61dddf7.png)


続いて、OS に SSH するための SSH Key をファイルから選択するか、コピペするかを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/72af765e-e6cb-6bf1-14c4-5d9341d14975.png)

最後に一番下の Create をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/275e23eb-c8f3-3700-aefc-8e9d429a9096.png)

インスタンスが作成されました。まだ、Provisioning 中です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/894583c0-58c2-6ada-f97d-a77ebeded024.png)

2分ほどで RUNNING となります。この状態になったら OS の起動が開始されます。
Public IP Address も割り当てられました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/f64a0e3d-9405-cb83-5865-8a3b9ceb5988.png)


## 3-4. SSH 接続
登録した SSH キーと確認した Public IP で接続します。

```
$ ssh opc@xxx.yyy.zzz.251
```

Kernel ver や OS リリースを確認してみます。

```
$ uname -a
Linux instance-20190212-1029 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
```

また H/W 的に GPU が認識されていることも確認しておきます。

```
$ lspci |grep -i nvidia
00:04.0 3D controller: NVIDIA Corporation GP100GL [Tesla P100 SXM2 16GB] (rev a1)
```

ちなみに、当然ですが CUDA はインストールされていないので、デバイスは見えません。

```
$ ls /dev/nvidia*
ls: cannot access /dev/nvidia*: No such file or directory
```

## 3-5. CUDA インストール
### 3-5-1. 必要なパッケージのインストール

以下は任意ですが、OS をアップデートしておきます。

```
$ sudo yum update
$ sudo reboot
```

続いて CUDA のインストールに必要なパッケージをインストールしていきます。

```
$ sudo yum install -y kernel-devel-`uname -r` kernel-headers-`uname -r` dkms
$ sudo yum groupinstall -y "Development Tools"
```

ここで注意ですが、現在の Kernel と同じ ver の kernel-devel と kernel-headers をインストールします。これはずれていると CUDA のインストール中に CUDA の Kernel Module が作成されません。
ちなみに、`sudo yum update` を実行していれば `$ sudo yum install -y kernel-devel kernel-headers dkms` で OK です。

### 3-5-2. CUDA のインストール

CUDA Repo をインストールします。

```
$ sudo yum install -y https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-10.0.130-1.x86_64.rpm
```

上記の URL は以下の URL から対象の環境を選択することで確認できます。
https://developer.nvidia.com/cuda-downloads

こんな感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/041c93b2-4b32-f091-4b36-c5410319e322.png)

これで CUDA の YUM リポジトリが追加されたので、CUDA のインストールができます。

```
$ sudo yum install -y cuda
```

モジュールのビルドなども実行されるので多少時間がかかります。
終了したら /usr/local 配下に cuda があることを確認します。

```
[opc@instance-20190212-1029 ~]$ ls /usr/local
bin  cuda  cuda-10.0  etc  games  include  lib  lib64  libexec  sbin  share  src
```

Reboot をします。

```
[opc@instance-20190212-1029 ~]$ sudo reboot
```

Reboot してきたら、/dev/nvidia* を確認します。

```
$ ls /dev/nvidia*
/dev/nvidia0  /dev/nvidiactl  /dev/nvidia-modeset
```
無事にデバイスが認識されています。

nvidia-smi も確認します。

```
$ nvidia-smi
Tue Feb 12 07:10:55 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.79       Driver Version: 410.79       CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000000:00:04.0 Off |                    0 |
| N/A   37C    P0    26W / 300W |      0MiB / 16280MiB |      4%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```
こちらも表示されましたので、無事に CUDA がインストールできました！

# 4. Custom Image について
Custom Image を利用すると、既存の OS ディスク(正式には Boot Volumeと呼ぶ)のイメージを作成し、それを元に同じ環境のインスタンスを作成することができます。
ただし、いくつか制限があるのでご注意ください。
- Boot Volume の最大サイズが 300GB 以内
- Custom Instance はデフォルトでは25個まで作成可能 → 増やせます

## 4-1. Custom Image の作成
注意として、Custom Image の作成を実行するとインスタンスは自動的にシャットダウンされます。必ず停止できる状況で実行してください。またインスタンスが停止している分には当然影響ありません。

メニューから instance を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/cee45e1d-0301-e831-2185-c304d83a7b41.png)

インスタンスのリストから Custom Image を作成したいインスタンスの・・・にカーソルをあわせます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/c6f9ef55-62ea-906b-3c29-4c4915d0e9aa.png)

するとメニューが開くので、Create Custome Image を作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/ed4c51c7-34c0-b098-fc5f-5b0c51ee314b.png)

名前を任意で入力して、Create Custom Image をクリックしますが、クリックするとインスタンスが自動的にシャットダウンされますので、ご注意ください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/ac202700-4c69-fe8d-6da4-7bc42b8fd6d7.png)

作成が始まるとアイコンが緑からオレンジに変わります。今回対象の Boot Volume は 50GB でしたので数分で完了して緑に戻ります(Bootされます)。 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/72366d70-931a-3b59-79a3-b24b9c3edc84.png)

## 4-2. Custom Image の確認
作成した Custom Image を確認してみます。
メニューから以下のように Custom Image を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/fb2eb40e-6a8b-dde8-cc65-2966d9ea8f5a.png)

無事、作成されています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/da44bc0d-5ae6-8dda-ef24-133ce5a859bc.png)

ちなみに、詳細を確認すると、Compatible Shapes というのがあり、このイメージを利用できるインスタンスが表示されます。
元々汎用的なイメージなので色々な Shape が表示されています。ちなみに、私の環境では、GPU インスタンスとして、BM.GPU2.2 と VM.GPU3.1 が表示されています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/fc06f655-f9a2-2c91-1571-901d53a5becb.png)

## 4-3. 新たなインスタンスを Custom Image から作成
最後に、先程作成した Custom Image から新たなインスタンスを作成してみます。

作成した Custom Image の・・・にカーソルをあわせて、Create Instance を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/02591115-e07e-d552-941d-e240cf56387c.png)

すると、インスタンス作成の画面に飛びます。
先程、VM を作成したときと同じ要領で進めていきます。

OS イメージに自分が作成した Custom Image が選択されていることを確認し、今回は Bare Metal Instance を選択します。Shape として BM.GPU2.2 というものを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/1203299e-ffdf-28d3-448a-bd5a3ebc2489.png)

その他の項目は先程と同じように選択します。

以下のように作成されました。Image が Custom Instance の名前になっています。当然ですが、IP やホスト名(=インスタンス名)は新たなものが割り振られています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/108605/01d5ebaa-b6a6-d48b-2918-1bbc7620dd1f.png)

ログインして確認みます。
作成した BM.GPU2.2 はベアメタルインスタンスで GPU が2つ搭載されています。

```
$ ls /dev/nvidia*
/dev/nvidia0  /dev/nvidia1  /dev/nvidiactl  /dev/nvidia-modeset

[opc@instance-20190212-1637 ~]$ nvidia-smi
Tue Feb 12 07:51:15 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.79       Driver Version: 410.79       CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000000:5E:00.0 Off |                    0 |
| N/A   38C    P0    44W / 300W |      0MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000000:86:00.0 Off |                    0 |
| N/A   36C    P0    42W / 300W |      0MiB / 16280MiB |      5%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
[opc@instance-20190212-1637 ~]$
```
無事、P100 が2つ認識されています。

# 5. 最後に
OCI が提供している CUDA インストール済みイメージ(以下のOSのみ)では最初から上記のように CUDA が使えて便利です。
- Ubuntu 16.04
- Oracle Linux 7.x
- Windows Server 2012 R2

余談ですが、Oracle Linux は基本 RHEL クローンはなので、RHEL や CentOS をお使いであればあまり意識せずご利用頂けます。またサポート付きで、Oracle が検証済みの新しい Kernel や付加機能をご利用頂けます。
https://www.oracle.com/assets/oracle-linux-faq-027617-ja.pdf

以上、