NVidia Optimusを搭載したノートPCでUbuntu14.04＋CUDA7.0を動かしてみた


こんにちは～

機械学習の勉強のため、Tensor flowを触りたいということで、二台目のノートPCにubuntuを入れました！

なぜubuntuかといえば Tensor flowのGPU機能がlinuxしか対応していないからです。。。(2016年4月時点)

Chainerを触ったことがありますが、GPUあるなしで性能に雲泥の差がでるのは間違いないので、本気でGPU対応するように挑戦してきました。

現状、Tensor flowはCUDA 7.0が必要です

色々調べてみたら、CUDA 7.0をインストールする記事は結構ありましたが、NVidia Optimusを搭載したPCでCUDAを入れる方法はありませんでした。

なので、色々記事を参考にして、どうにかCUDAをいれました。。

ここまでの道のりがものすごく大変でしたので、今後のために備忘録として紹介します！

環境は次のとおりです

* PC:  ASUS K55VD
* OS:  Ubuntu 14.04
* GPU: Geforce 610M(NVidia Optimus対応)

# bumblebeeインストール
NVidia OptimusでGPUを使用する場合は、ただ単にドライバのインストールしても動きません！

そこで、NVidia Optimus環境でもGPUを使うためのツールとして, bumblebeeがあります！

これをインストールしましょう！

```
# bumblebeeのリポジトリ追加＋最新版へ更新
sudo add-apt-repository ppa:bumblebee/stable
sudo apt-get update

# bumblebee一式のインストール(公式ページでのubuntu14.04のインストール方法を参考)
sudo apt-get install bumblebee bumblebee-nvidia primus linux-headers-generic
```

# nvidia-352 nvidia-settingsインストール

CUDA7.0を入れるため、nvidiaのドライバは352以上が必要です。ここでインストールしましょう！

```
sudo apt-get install nvidia-352 nvidia-settings
```

# /etc/bumblebee/bumblebee.confでnvidia-352を設定

nvidia-352をbumblebeeで利用するようにしましょう！

```
sudo vim /etc/bumblebee/bumblebee.conf

# 次のように変更します

22行: Driver=nvidia
55行: KernelDriver=nvidia-352
58行: LibraryPath=/usr/lib/nvidia-352:/usr/lib32/nvidia-352
61行: XorgModulePath=/usr/lib/nvidia-352/xorg,/usr/lib/xorg/modules
```

# /etc/modprobe.d/bumblebee.confでnvidia-352をブラックリストに入れることでロードを抑制

nvidia-352をインストールした場合、bumblebeeを起動する前にnvidia-352を有効になってしまいます。そうなると、bumblebeeが起動せず、Ubuntuが正しく起動しません（原因がわかるまで、UbuntuのGUI起動後真っ暗になっていて大変でした。。。）

そこで、/etc/modprobe.d/bumblebee.confでnvidia-352をブラックリストに入れることでロードを抑制させます！

```
sudo vim /etc/modprobe.d/bumblebee.conf

# 以下を追加
blacklist nvidia-352
blacklist nvidia-352-updates
blacklist nvidia-experimental-352
```

これで、Nvidiaの新しいドライバをbumblebee上で動かせるようになりました。

# CUDAのダウンロード

つぎはCUDAを入れていきます。

まずは、CUDAをダウンロードします。debパッケージでもインストールできますが、細かいオプションが利かないため、runパッケージをダウンロードします！

下記ページからubuntu14.04のrunパッケージを選択してダウンロードするか、

https://developer.nvidia.com/cuda-toolkit-70

あるいは直接落とします。

```
wget http://developer.download.nvidia.com/compute/cuda/7_0/Prod/local_installers/cuda_7.0.28_linux.run
```

落としたら、ホームディレクトリ（~/）へ移動させます

# CUDAのインストール

何も考えずにインストールすると、OpenGLライブラリもインストールされます。このライブラリがインストールすることによって、Ubuntuがログインできなくなります！（アンインストールしても元に戻らなかったため、ここでUbuntuを再インストールするハメになりました。。。）

なので、OpenGLライブラリをいれずにインストールします！

```
./cuda_7.0.28_linux.run --no-opengl-libs
```

以下指示が出ますが、つぎのように選択します

```
# 当然accept
Do you accept the previously read EULA? (accept/decline/quit): accept

# 必要らしいので, y
Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 346.46? ((y)es/(n)o/(q)uit): y

# CUDA本体なので, y
Install the CUDA 7.0 Toolkit? ((y)es/(n)o/(q)uit): y

# CUDAの入れる場所を尋ねられます。ここはデフォルトのままなので、そのままENTER
Enter Toolkit Location [ default is /usr/local/cuda-7.0 ]:

# sudoで実行しない場合これがでます。sudoで実行させないとインストールできないので、 y
/usr/local/cuda-7.0 is not writable.
Do you wish to run the installation with 'sudo'? ((y)es/(n)o): y
Please enter your password:

# シンボリックリンクをはるか尋ねられますが、実効に必要なので y
Do you want to install a symbolic link at /usr/local/cuda? ((y)es/(n)o/(q)uit): y

# サンプルを入れるかどうか尋ねられますが、動作確認したいので y
Install the CUDA 7.0 Samples? ((y)es/(n)o/(q)uit): y

# サンプルの入れる場所はデフォルトにしときます
Enter CUDA Samples Location [ default is /home/faithnh ]: 
```

問題なければこれでインストールできます！

最後にこの指示がでますので、

```
Please make sure that

 -   PATH includes /usr/local/cuda-7.0/bin

 -   LD_LIBRARY_PATH includes /usr/local/cuda-7.0/lib64, or, add /usr/local/cuda-7.0/lib64 to /etc/ld.so.conf and run ldconfig as root
```

~/.bashrc上に設定しときましょう！

```
vim ~/.bashrc

# 以下を追加

# for CUDA
export PATH=$PATH:/usr/local/cuda-7.0/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-7.0/lib64
```

そして、設定を反映させます。

```
source ~/.bashrc
```

# CUDAサンプルをビルド、実行

上記手順でインストールしたら、ホームディレクトリに配置されますので、サンプルにアクセスし、makeでビルドします。

makeするには、gccなどの環境が必要なので、開発環境一式をインストールしておきます

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

そのあと、makeしてビルドしていきます。ビルドは大変時間がかかります（ここで1時間ほどとられました）

```
cd ~/NVIDIA_CUDA-7.0_Samples
make
```

最後にFinished building CUDA samplesがでればOKです！


# 実行してみるものの、問題が・・・

マージソートのサンプルを実行してみます。

```
cd ~/NVIDIA_CUDA-7.0_Samples/bin/x86_64/linux/release
./mergeSort

./mergeSort Starting...
CUDA error at ../../common/inc/helper_cuda.h:1105 code=38(cudaErrorNoDevice) "cudaGetDeviceCount(&device_count)"
```

あらら、問題が。。。

色々調べたところ、bumblebeeでは、デフォルトGPUは有効になっていないため、GPUは認識しないようです。

GPUを有効にして実行させるためにはoptirunコマンドを挟んで実行しなければなりません。

使い方はこんな感じです。

```
optirun [オプション] アプリ実行コマンド
```

オプションはなしでも実行できるので実質こうなります。

```
optirun アプリ実行コマンド
```

それでは実行してみましょう。

```
optirun ./mergeSort
./mergeSort Starting...modprobe: FATAL: Module nvidia-uvm not found.
CUDA error at ../../common/inc/helper_cuda.h:1105 code=30(cudaErrorUnknown) "cudaGetDeviceCount(&device_count)"
```

今度は別の問題がでました、、、nvidia-uvmがないと怒られてます。

つぎは、nvidia-uvmを有効にして対処していきましょう。

# nvidia-uvmを有効化

CUDAを動かすにはnvidia-uvmが必要だが、bumblebeeで動作する場合、なぜか有効になっていないため、対処していきます。

まずはbumblebee.confをこのように修正していきます。nvidia-352-uvmをnvidia-uvmとして利用できるようにします。

```
sudo vim /etc/modprobe.d/bumblebee.conf

alias nvidia-uvm nvidia-352-uvm
```

設定を反映させ、nvidia-uvmを有効にしていきます！

```
sudo updatedb
sudo optirun modprobe nvidia_uvm
```

# 再度実行

再度マージソートのサンプルを実行してみます。


```
optirun ./mergeSort
./mergeSort Starting...modprobe: FATAL: Module nvidia-uvm not found.
CUDA error at ../../common/inc/helper_cuda.h:1105 code=30(cudaErrorUnknown) "cudaGetDeviceCount(&device_count)"
```

うーん、まだ動かないな。。。

あ、よく考えたらnvidia_uvmではsudoで実行してたので、sudo入れたら動くのでは。。。。

と思い、sudo を入れてみました。

```
cd ~/NVIDIA_CUDA-7.0_Samples/bin/x86_64/linux/release
sudo optirun ./mergeSort 
 
./mergeSort Starting...

GPU Device 0: "GeForce 610M" with compute capability 2.1

Allocating and initializing host arrays...

Allocating and initializing CUDA arrays...

Initializing GPU merge sort...
Running GPU merge sort...
Time: 1037.418945 ms
Reading back GPU merge sort results...
Inspecting the results...
...inspecting keys array: OK
...inspecting keys and values array: OK
...stability property: stable!
Shutting down...
```

う、うごいた～！

なぜsudo入れないといけないのかがよく分かりませんが、これで動きました！（後で理由を調べたいと思います）

# 終わりに
CUDAを入れるだけでものすごい労力がかかってしまったため、残念ながらcuDDN以降は紹介できませんでした

が、Tensor flowが無事に入れた暁に紹介していきたいと思います！

# 参考記事

http://ry0.github.io/blog/2015/08/12/ubuntu-nvidia-cuda-7.0/
http://ubuntuforums.org/showthread.php?t=2262882&page=7
http://www.linuxveda.com/2015/07/16/how-to-install-drivers-for-nvidia-optimus-cards/
https://ask.fedoraproject.org/en/question/77633/install-nvidia-driver-for-cuda-without-turn-it-on-for-xwindows/