Azure NシリーズでNVIDIA DIGITSをサクッと動かす

エヌビディアの佐々木です。

Microsoft Azureで「Nシリーズ」と呼ばれるGPU搭載仮想マシンのプレビューが始まりました。
昨年の9月末、弊社CEOジェンスン・ファンが語っていたこれです。

[NVIDIA の CEO Jen-Hsun Huang が Microsoft Azure クラウド向け GPU について語る](https://youtu.be/S2GFlYL7APA)

予定よりかなり遅れてしまったようですが、私もTesla K80を搭載したNC6及びNC12インスタンスを試せるようになり、これを使ってNVIDIA DIGITSをうごかしてみましたので簡単に報告します。

DIGITSを動かすまでの概略は以下の通り。

1. NシリーズのVMを作成
1. GPUのドライバをインストール
1. Docker, NVIDIA Dockerをインストール
1. DIGITSを起動して遊ぶ

特に難しいところはありません。というかとても簡単です。NVIDIA Dockerならね！

では、私が実際試した手順を書いていきます。

# NシリーズのVMを作成
[Azureポータル](https://portal.azure.com) でNC6インスタンスを作成しました。OSはUbuntu 16.04です。

NCインスタンス自体はWindows, Linuxの両OSに対応していますが、DIGITSはWindowsでは動作しませんから、Linux VMを作成する必要があります。
そして少なくとも現時点ではNシリーズのゲストOSとしてサポートされているLinuxはUbuntu 16.04のみのようです。(14.04ではGPUを認識できませんでした)

## DNS名の設定
SSHでのログインやWebブラウザでのアクセス時に、いちいちIPアドレスを指定するのもイマイチなので、DNS名を付与しておきました。
![image](https://qiita-image-store.s3.amazonaws.com/0/32712/0a3bb36c-cd59-27cc-6dc3-8e47699ca543.png)

## lspciで確認

VMが出来上がったら、ログインしてlspciしてみましょう。

```shell-session
$ lspci
0000:00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (rev 03)
<中略>
b0c7:00:00.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)**
```

Tesla K80がちゃんと認識されています。ちょっと面白いのは、K80を構成するGPUであるGK210が一つだけしかないことでしょうか。このNC6インスタンスというのは、K80を搭載するNC系列の中で一番小さい(=安い)インスタンスで、K80を「**半分だけ**」割り当てられているのです。

GK210を一つだけ搭載したGPUカードというのは製品化されていませんから、この
「**lspciしたらGK210が一つだけ出てくる**」
というのはかなり珍しい状態といえるでしょう。


# GPUのドライバをインストール
Nシリーズのプレビュー参加者にはマイクロソフトさんからGPUドライバのダウンロードURLが送られてくると思います。これをダウンロードしてインストールすればよいのですが、素の状態で実行するとccがないと怒られます。開発ツール一式をインストールしてからにしましょう。

```shell-session
sudo apt-get install build-essential
```

この後、 NVIDIA-Linux-x86_64-361.69-1009163-01.run を実行してGPUドライバをインストールしました。

# Docker, NVIDIA Dockerをインストール
DIGITSは普通にインストールしても良いのですが、今回はDockerのコンテナとして実行する方法を選びました。
そのためにDockerと、NVIDIAのプラグインであるNVIDIA Dockerをインストールする必要があって、これはコマンド一発という感じではないのですが、以下のスクリプトをsudoで実行すれば済むのでよろしければご利用ください。

```bash
#! /bin/sh

# Install Docker
apt-get update
apt-get install apt-transport-https ca-certificates
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" >> /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
apt-get install docker-engine
docker run hello-world

# Install nvidia-docker and nvidia-docker-plugin
wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0-rc.3/nvidia-docker_1.0.0.rc.3-1_amd64.deb
dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb

# Test nvidia-smi
nvidia-docker run --rm nvidia/cuda nvidia-smi

```

なお、これらのコマンドはDocker, NVIDIA Dockerそれぞれの公式手順から持ってきたものです。
- [Docker Installation on Ubuntu](https://docs.docker.com/engine/installation/linux/ubuntulinux/)
- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker)

最後に nvidia-smi がこんなのを出力していれば成功です。

```text
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 361.69                 Driver Version: 361.69                    |
|-------------------------------+----------------------+----------------------+
| 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 K80           Off  | A7AD:00:00.0     Off |                    0 |
| N/A   41C    P8    32W / 149W |      0MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

# DIGITSを起動して遊ぶ
[NVIDIA DIGITS](https://developer.nvidia.com/digits) は、簡単に言えばCaffeやTorchをラッピングするWebアプリケーションです。学習用データセットの管理やトレーニングの実施、トレーニング済みモデルを使った推論といった一連の操作をWebブラウザから行うことができます。

## DIGITSコンテナの起動
こんなコマンドで起動します。

```shell-session
sudo nvidia-docker run --name digits -d -p 8080:34448 nvidia/digits
```

これで、 Dockerホスト（=今回作成したNCシリーズインスタンス)の8080番ポートでDIGITSが動き始めました。しかし、まだこの状態では外部から接続できません。Azureの「ネットワークセキュリティグループ」の設定でこの8080番への着信接続を許可する必要があります。

## 受信セキュリティ規則の設定
Azureポータルで「仮想マシン」→「ネットワークインタフェース」→「ネットワークセキュリティグループ」と辿り、「受信セキュリティ規則」を追加します。
![image](https://qiita-image-store.s3.amazonaws.com/0/32712/3197c923-6813-c4f2-956a-0a300a590d48.png)



これでDIGITSが使えるはずです。Webブラウザで、仮想マシン作成時に設定したDNS名の8080番へアクセスしてみます。こんな画面が出てくるはず。
![image](https://qiita-image-store.s3.amazonaws.com/0/32712/f4828f59-f8a6-25a0-0d81-292bbb4dac80.png)

## Hello, Deep Learning World!
月並みすぎて恐縮ですが、まずは「ディープラーニング界のHello World」的なMNISTの手書き文字認識を試してみました。ここにわかりやすい手順があります →  [Getting Started](https://github.com/NVIDIA/DIGITS/blob/master/docs/GettingStarted.md) 
 
 基本的にはこの手順のとおりなのですが、今回の環境固有の事情をちょっと補足しておきます。

## 補足: コンテナへの対話的接続
最初にデータセットをダウンロードする部分だけは、ブラウザではなくDIGITSが動いているサーバーにログインして操作する必要があります。そして今回、DIGITSはDockerコンテナの中で動いていますので、コンテナに対話的に接続しなければなりません。（もちろんホストのディレクトリにデータをダウンロードして、それをコンテナと共有しても良いと思います。以下の操作はホストを汚さずコンテナの中にデータを置く例です）
 
先ほどのコマンドで起動したコンテナに接続するには、コンテナのIDを確認して、docker exec で bash を実行します。
 
```shell-session
ksasaki@sasavidia:~$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
c9795c98449f        nvidia/digits       "./digits-server"   33 minutes ago      Up 33 minutes       0.0.0.0:8080->34448/tcp   digits
ksasaki@sasavidia:~$ sudo docker exec -it c9795c98449f bash
root@c9795c98449f:/usr/share/digits#
```
あとは、ドキュメント通りです。/usr/share/digits/tools/download_data/main.py を実行してMNISTのデータをダウンロードします。私は /tmp/mnist にダウンロードしました。

```shell-session
root@c9795c98449f:/usr/share/digits# /usr/share/digits/tools/download_data/main.py mnist /tmp/mnist
Downloading url=http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz ...
＜中略＞
Reading images from /tmp/mnist/test-images.bin ...
Dataset directory is created successfully at '/tmp/mnist'
Done after 18.8425891399 seconds.
```

ぜひ、みなさんもDIGITSをお試しください。MNIST以外にもいろいろなチュートリアルが用意されていますよ。
例えば、
- [画像の分類](https://github.com/NVIDIA/DIGITS/tree/master/examples/segmentation)
- [物体検出](https://github.com/NVIDIA/DIGITS/tree/master/examples/object-detection)
- [テキスト分類](https://github.com/NVIDIA/DIGITS/tree/master/examples/text-classification)

[その他にもいろいろあります。](https://github.com/NVIDIA/DIGITS/tree/master/examples)

以上、Azure NシリーズでNVIDIA DockerによるDIGITS簡単実行を試したお話でした。

# 関連情報
- [NVIDIA TESLA K80 - HPC および機械学習用の世界最速 GPU アクセラレータ](http://www.nvidia.co.jp/object/tesla-k80-jp.html)
- [NVIDIA DIGITS](https://developer.nvidia.com/digits)
- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker)
- [CUDA Toolkit 8 RC Now Available](https://developer.nvidia.com/cuda-toolkit)
- [NVIDIA GRID 仮想 GPU テクノロジ](http://www.nvidia.co.jp/object/grid-technology-jp.html)
- [Docker Installation on Ubuntu](https://docs.docker.com/engine/installation/linux/ubuntulinux/)
- [Azure N シリーズのプレビュー版の提供を開始](https://blogs.technet.microsoft.com/jpitpro/2016/08/12/azure-n-%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%E3%81%AE%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E7%89%88%E3%81%AE%E6%8F%90%E4%BE%9B%E3%82%92%E9%96%8B%E5%A7%8B/)
- [ubuntu14.04でnvidia-dockerを動かす](http://qiita.com/mana-murakami/items/78cfc60c2205f9eba72c)
- [ubuntu14.04にnvidia-dockerをインストールする](http://qiita.com/mana-murakami/items/2ff0c3b3ecd4ce85c2cd)