xiangze's sparse blog

機械学習、ベイズ統計、コンピュータビジョンと関連する数学について

Ubuntu でtensorflow-gpuを使えるようにするのにはまった→解決

表題のようにUbuntu16.04 でtensorflow-gpuを使おうとしてハマったのでその解決に至るまでの記録です。
個々の問題はググって出てきた情報を実施することで解決できるものです。
ここではそれをどんな順序で試行錯誤し実行していったかの流れを記します。

そもそもの問題

Ubuntu16.04, python2.7に

pip install tensorflow-gpu

としてtensorflow-gpuをインストールしたが

import tensorflow

としても

Couldn't open CUDA library libcuda.so.7

のエラーによりtensorflowが使えなかった。

対策1. cudaにあった環境変数の設定&Nvidia GPUドライバの再インストール

エラーメッセージをググった結果
TensorFlow on DockerでGPUを使えるようにする方法 | 株式会社カブク
にあるようにGPUドライバが適切にインストールされていないのが原因だと判断し、最新のドライバ(384.111)を
NVIDIAドライバダウンロード

からダウンロードし、以下の手順に沿ってインストールした。

  • Ctrl+Alt+F1を押しGUI停止させる。
  • sudo apt-get remove --purge nvidia*

として既存のドライバをアンインストール

  • service lightdm stop
  • sudo chmod +w NVIDIA-Linux-x86_64-384.111.run として実行権限を与えたのち実行
  • 出てくる質問は基本yesを選択する。
  • 再起動
  • nvidia-smi でインストールされたことを確認する。以下のような表示がでれば成功
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.111                Driver Version: 384.111                   |
|-------------------------------+----------------------+----------------------+
| 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 GTX 970     Off  | 00000000:04:00.0  On |                  N/A |
|  0%   19C    P0    44W / 163W |    228MiB /  4036MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1006      G   /usr/lib/xorg/Xorg                           168MiB |
|    0      1785      G   compiz                                        56MiB |
+-----------------------------------------------------------------------------+

同時にpython3.5をインストールし、そちらからtensorflowを使うことにした。

  • Nvidia GPU driver 384.111
  • cuda 8.0
  • cudnn
  • python 3.5
  • anaconda
  • tensorflow 1.4

をインストールした。手順は
Ubuntu 16.04 で GPU 対応版 TensorFlow をanaconda 環境でインストールした話 - ill-identified diary
に従った。
また以下の行を.bashrcに追加することでcudaのpathを環境変数に追加した。

export CUDA_HOME=/usr/local/cuda
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${CUDA_HOME}/lib64

nvidia-smiコマンドでドライバのインストールがされたことは確認できたのだが、

tf.Session()

とすると

failed call to cuinit curesult(-1)

というエラーが出てきてこれでもtensorflowはドライバを認識しないらしい。
ここで以下の情報からデュアルブートできるようにしているWindowsの(UEFI)セキュアブートが問題の可能性があると考え以下の対策を実行した*1
Ubuntu日本語フォーラム / Ubuntu16.04LTS nvidiaドライバーのインストール後 loginできない

対策2. Ubuntu16.04をクリーンインストール

起動用USBメモリとインストール用SSDを用意し、
Ubuntu Desktop 日本語 Remixのダウンロード | Ubuntu Japanese Team
からisoファイルをダウンロードし、dd コマンドでUSBにコピーする。
Linuxでddコマンド使ってisoイメージをUSBメモリに書き込む方法

sudo dd if=ubuntu-ja-16.04-desktop-amd64.iso of=/dev/sda bs=1048576

これは普通のコピーに比べて時間がかかる上に進捗は表示されない。オプションで指定したブロックサイズが小さいせいかもしれない。

“sda"は起動用USBメモリに対応するデバイス

sudo fdisk -l

コマンドで確認する。

インストール用USBをUSB3.0ではなく2.0の方にさす方が安定して起動できるらしい。また起動時にUHCIではなくUSBの方を選択したほうがいいらしい*2
Ubuntu16.04をクリーンインストールし、後からGPUのドライバをインストールしようとしても画面がうまく表示されない。これはGPUのドライバが入っていないからである意味当然でインストール時にnomodesetという状態でインストールしなければいけないらしい。

nomodeset

drivers - How to run Ubuntu with GTX970? - Ask Ubuntu
こちらの手順の通りに

  • OS起動直後にEnterを押し、言語選択画面に入る。
  • 好きな言語を選びEnterを押す
  • F6を押す
  • 出てきたメニューをからnomodesetを選びそこでEnterを押して印をつける
  • Escを押す
  • Install Ubuntuを選択しEnterを押す

としてインストールを開始する*3

あとは手順通りに…

上で書いたのと同様にNvidia driver, cuda, cudnn, python 3.5, anaconda, tensorflow 1.4
をインストールしていった。anacondaで仮想環境を作ってその上にpython3. , tensorflow-gpuを動かすようにする。

conda create -n tf python=3.5

で仮想環境を作成

 source activate tf

でそれをアクティベートできる。アクティベートした状態でpip,condaでライブラリをインストールする。
ただ仮想環境をアクティベートした状態で

source ~/.bashrc

とすると環境が元に戻ってしまうので

export CUDA_HOME=/usr/local/cuda
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${CUDA_HOME}/lib64

だけを実行する必要があった*4

jupyterで仮想環境を使う

このままではjupyterを起動しても仮想環境に入れたライブラリが使えないので、仮想環境(tf)で

conda install notebook ipykernel

としてjupyterをインストールし、
Jupyter上でkernel切り替えをしてもうまく機能しない場合の解決方法 - Qiita
のように

ipython kernel install --user --name tf --display-name tf

とするとJupyter内でkernelを選べるようになる。

結果

EdwardでのCNN VAEの1回のepochがcore i7では100s程度だったのがGeforce GTX970で19s程度になりかなり速くなった。より高性能なGPUも欲しくなってきた。

今回関係なかったこと

ドライバは別途インストールする必要があるが別々のバージョンのcuda, cuDNNをコンテナごとにインストールできるらしい。
Ubuntu 16.04 LTS で NVIDIA Docker を使ってみる - CUBE SUGAR CONTAINER
Chainerのテスト環境とDockerでのCUDAの利用
chainerも同様のcuda依存性があるらしく、Docker+自動テストを使えばバージョン変更にも手間が少なく対応できるそう。しかしドライバはホストとゲストで同じでないといけないらしく、また今回ハマったところはドライバやOSのインストール部分が大きかったので作業の削減にはならなさそう。

総括と感想

個々の手順はネット上に豊富な情報があり、ほとんど日本語の情報だけで解決できた。
当初はドライバ,cuda,cudnn,python,tensorflowの複数バージョンの組み合わせが膨大なことが辛いと思っていたが実際やってみると最もハマったのがLinux(Ubuntu)のインストールのところだった。ハードウェア(特にマザーボードGPU)に関わるので解決できないのではないかという不安が常にあった。

謝辞

リンクにある情報を書いてくださった皆さんありがとうございました。

*1:高速スタートアップを無効にすればWindows10も使えるようだがほとんど使っていないので諦めて使わないことにした

*2:何回かBIOS画面に入れなくなる時があったが原因不明。無線ではなく有線USBキーボードを使ったのがよかったのかもしれない。

*3:nomodesetに関しては本の虫: nomodesetとLinuxにおけるGPUドライバーの問題

*4:下記のjupyterの使用では不要っぽい

*5:Nvidia driverの起動が不安定で適切な解像度でログイン画面が表示されない。ログイン画面でパスワードを入力してもGUI(X)が立ち上がらなかったりすることがあるが、nouveauの方が安定しているということがあるかもしれない。