読者です 読者をやめる 読者になる 読者になる

ill-identified diary

所属組織の業務や見解とは一切無関係なアフィリエイト付きメモ帳。所属とは関係ないけどここを見て所属先にも興味を持っていただけると喜びます。

Ubuntu 16.04 で GPU 対応版 TensorFlow をanaconda 環境でインストールした話

python anaconda Ubuntu TensorFlow

概要

巷では Ubuntu 14.04 と CUDA 7.5 の組み合わせが安定しているとのことだが, 仮想環境とか作るのがめんどくさいので Ubuntu 16.04 にインストールした. Linux に詳しい訳ではないので, あくまでこれは解決事例の1つであって正答でなく, 自己責任であることに注意. 環境・バージョン等は以下の通り.

2017/2/4追記: 最新版で再インストールしたのでバージョンの記述を変更した.なお現時点ではCUDAは7.0以上, cuDNNは3以上をサポートしているとDownload and Setup  |  TensorFlowに書かれている.

  • デスクトップ PC (AWS などにインストールする方法は探せば他に情報あるはずなのでそっち参照)

  • グラフィックボード: GTX 970

  • OS: Ubuntu 16.04 (64 bit) -> デスクトップ環境は Xubuntu 推奨

  • nVidia ドライバ: 375.26

  • CUDA : 8.0 (8.0RC ではない)

  • cuDNN: 5.1

  • tensorflow: 0.10.0rc0

  • anaconda 1.4.0

2016/12/02 追記: nvidia のドライバと unity がやたらと相性が悪く, ログイン画面ループをはじめとする不具合が頻繁に発生するようになった. そのため unity と ubuntu-desktop をアンインストールして xubuntu を使うことにした. 一部勝手が違うところがあるが, こちらも割と使いやすい. スタートメニューやタスクバーといった Windows っぽいデザインで問題なければ xubuntu にしたほうが良い. xubuntu ではスタートメニューに対応するものは whisker menu というのだが, デフォルトでは superキー (winキー) がショートカットになっていない. メニューのショートカットキーを変更したい場合, whisker メニューを開いて「設定マネージャ」->「キーボード」->「アプリケーションショートカットキー」の「xfce4-popup-whiskermenu」を変更するとよい.

2017/1/17 追記: なお, CUDA および cuDNN は最近 (?) 登場した R での深層学習の実装パッケージである MxNet にも使いまわせる. もちろん要求されるバージョンが違う可能性はあるが.

nVIDIA ドライバインストール

まず, nVIDIA ドライバのインストール. graphics-driversリポジトリからインストールできるもの (= 「追加のドライバ」で表示されるリストにあるもの) は起動時に読み込みに失敗するので Xorg.0.log を見ながらググっていろいろ修正してみたがうまく動作させられなかった.

そこで NVIDIAドライバダウンロード から最新版ドライバの .run ファイルをダウンロードする. さらに, Ubuntu14.04にcuda 7.5をインストール - Qiita の「デフォルトのグラフィックドライバを停止」に書いてある通りのことを実行した (これが必須かは要検証). ALT+CTRL+F1 で仮想コンソールを立ち上げ, ログインする (この画面では日本語が文字化けするので注意). ディスプレイマネージャが動いたままだとドライバのインストール時にエラーが出るため,

sudo service lightdm stop

で切る (gdm, kdm などを使っている場合は適宜変える). さらに念の為, 既にある nVIDIA のドライバ関係のものはアンインストールしてから最新版のドライバをインストールする.

sudo apt-get purge nvidia*
sudo sh Nvidia-Linux_x86_64-[ここにバージョン].run

対話的にいくつか質問されるが適当に答えておく. インストールが終わったら reboot (sudo service lightdm restart だけでもいい?) して再度ログイン. ターミナルで

nvidia-smi

と入力してドライバの状態を確認する*1.

CUDA & cuDNN インストール

次に GPU に対応させるため CUDA と cuDNN が必要となる. この2つはダウンロードするには nVIDIA developer に登録が必要である. CUDA Toolkit | NVIDIA Developer からダウンロードする. 7.5 であれば何も手続きがいらないが, 8.0RC はアカウント登録を促される. 今回はとりあえず 7.5 をダウンロードすればいいが, この後の cuDNN のダウンロード時にはどちらにせよ登録が必要である. 現時点ではメールアドレス, パスワード, アンケート的な使用目的くらいしか訊かれない*2. 全て埋める必要があるが, かなり雑に答えても大丈夫なようだ. すべて答えると確認用メールが届き, 本文にあるリンク先に飛べば承認される*3. あとはログインして OS やバージョンを選んでダウンロードすればよい. CUDA 7.5 は Ubuntu 15.04 までしか選択肢がないが, それを選んで問題ない. また, このバージョンは nvidia-352 のドライバに対応しており, .deb パッケージだと勝手に nvidia-352 を入れられ, 既にインストールしたドライバと競合するので [runfile (local)] を選んで .run の方をダウンロードした*4.以上灰色字部分は 8.0RC の話. CUDA 8.0のダウンロードに登録は不要.
CUDA 8.0 Downloads | NVIDIA Developer から以下の画像のようにOS等を指定してダウンロードする.
f:id:ill-identified:20170204103758p:plain
ただし, deb ファイルの場合は勝手にグラフィックドライバもインストールしようとするので runfile の方をダウンロードすることをおすすめする. ドライバの時と同様, 仮想コンソールでログインしてディスプレイマネージャを切ってから,

sudo sh cuda_[ここにバージョン]_linux.run --override

でグラフィックドライバの時と同様に対話形式でインストールが進む. 基本的に accept とか yes とか連打し, パスを訊かれても空白で返事するとかで良いが, ドライバを既にインストールしているため, nvidia-352 をインストールするか(バージョン番号は違う場合がある), という質問には確実に no と言っておく. さらに, サンプルをインストールするかという質問もあるが, 動作確認がしたい場合は yes にしておく. また, CUDA には gcc が必要なのだが, 現時点での最新版 5.4.0 はサポートしていないバージョンだとしてインストールが中断されてしまう. このエラーを無視するために --override オプションを付けている. 8.0 は gcc-5.4 に対応したらしいので灰色字部分は不要. なお, ここでcuda-toolkit も同時にインストールされる. インストールが終わったら, ディスプレイを sudo service lightdm restart で戻す. 以降の操作もほぼ全て端末でできる操作なので, めんどくさかったら戻さず続けてもよい. 次に ~/.bashrc の末尾に以下の記述を追加する.

export CUDA_HOME=/usr/local/cuda-7.5
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${CUDA_HOME}/lib64
export PATH=$PATH:${CUDA_HOME}/bin

ここまでの話は, 結局 http://devtalk.nvidia.com/default/topic/938988/-solved-cuda-8-0-on-ubuntu-16-04-gpu-not-available/ で紹介されているのとほぼ同じである.

実際には, インストーラ/usr/local/cudaにもシンボリックリンクを作成するので, 将来バージョンアップする際の手間を考えると1行目のパス指定はこちらにしたほうが少しだけ楽かもしれない.

--- 2017/2/4 追記: 以下の作業は 8.0 以降では不要. ---

さらに, 実際に CUDA を使用するにあたって gcc 5.3 以上では動かせないため, 古いバージョンのシンボリックリンクを貼る. ls /usr/bin/gcc-* で探したところ, 自分の場合は 4.9 が入っていたのでこれを使うことにした. Ubuntu 16.04 ならたいていは gcc-4.9gcc-5 が入っていると思う*5. なお, gcc-5 という名前があっても gcc-5 -v とすると実際はもっと新しいバージョンだったりするので注意.

sudo ln -s /usr/bin/gcc-4.9 /usr/local/cuda/bin/gcc
sudo ln -s /usr/bin/g++-4.9 /usr/local/cuda/bin/g++

とした ( 参考: CUDA incompatible with my gcc version - Stack Overflow). 別のバージョンを使う場合も数字の部分を変えるだけで適用できる.

--- 2017/2/4 追記: 以上の作業は 8.0 以降では不要. ---

CUDA のサンプルをダウンロードした場合は, 以下の方法でサンプルプログラムをコンパイルし動作確認する.

# 通常はホームディレクトリにある
cd NVIDIA_CUDA-8.0_Samples/
# 全プログラムをコンパイルするので時間がかかる
make
# 実行するプログラムは適当で良い. これはマンデルブロ集合を描くプログラムらしい.
./2_Graphics/Mandelbrot/Mandelbrot

cuDNNNVIDIA cuDNN | NVIDIA Developer から tar.gz 形式でダウンロードできる. cuDNN はダウンロード前にユーザー登録の必要がある.

tensorflow 0.10rc0 に対応して v5.1 を利用する: [Download cuDNN v5.1 (Jan 20, 2017), for CUDA 8.0] -> [cuDNN v5.1 Library for Linux] を選択する.

cuDNN は 解凍したファイルを適切な場所に置くだけでインストールできる. cuda のインストール先にファイルをコピーするのが通常だが, Ubuntu16.04LTSにCUDA7.5とcuDNNとCaffeをインストール - Qiita を参考にして, 解凍して出てきたCUDA以下のファイルはホームディレクト~/.cudnn/5.1/に置いて, cuda のディレクトリにシンボリックリンクを張るという方法を採用した. ただし, 参考元は caffe のインストール用なので, リンクを置く場所が少し違う:

sudo ln -s ~/.cudnn/5.1/include/cudnn.h /usr/local/cuda/include/cudnn.h 
sudo ln -s ~/.cudnn/5.1/lib64/libcudnn* /usr/local/cuda/lib64/
sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*

本体の置き場所が違うのは, 単にホームディレクトリがごちゃごちゃしているのが嫌なので隠しディレクトリにしたかっただけ.

TensorFlow インストール

最後に, tensorflow をインストールする. 公式の Download and Setup  |  TensorFlow を参考にする. 自分は普段は ancaonda を利用している*6 ので, それに従う. まず, tensorflow を動かす環境を conda で作成する.

conda create -n tensorflow python=3.5
source activate tensorflow

ちなみに, source activate tensorflow を実行して端末が閉じられる人は pyenv と競合しているだけなので activate をフルパスで書くと回避できる. 具体的には, 以下のページの解決策2を利用した.
qiita.com
端末の左に (tensorflow) と表示されるようになったら成功. 次にインストールだが, 現状は conda では GPU 対応版をインストールできないらしいので pip3 を使う (まだ tensorflow 環境から出てはならない).

export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.10.0rc0-cp35-cp35m-linux_x86_64.whl
pip install --ignore-installed --upgrade $TF_BINARY_URL

上記で指定した URL は OS, Python 本体バージョン, GPU の有無でそれぞれ違うのでよく確認する. 以上でインストール完了. python なり jupyter notebook なりで import tensorflow して使うことができる.
GPUを認識しているかどうかの最も簡単な確認をする. まずは python を起動する. ipython や jupyter だと初期設定ではログが表示されないので python を使った. 起動したらまずはimportする.

ILLIDENTIFIED: ~$ activate tensorflow
(tensorflow) ILLIDENTIFIED: ~$ python
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally

微妙に異なるかもしれないが, こんな感じの通知が出る. さらにセッションを確立する.

>>> a = tf.Session()
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties: 
name: GeForce GTX 970
major: 5 minor: 2 memoryClockRate (GHz) 1.2155
pciBusID 0000:01:00.0
Total memory: 3.93GiB
Free memory: 3.70GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 970, pci bus id: 0000:01:00.0)
>>> 

すると, GPU を認識したとの通知が出る. 環境設定が不適切で GPU を認識できていないと, 多くはここで何らかのエラーが発生する.
以下, tensorflowの機能をまるで活用しない動作確認プログラムを試してみる.

import tensorflow as tf
sess = tf.Session()

hello = tf.constant("Hello, TensorFlow!";)
print(sess.run(hello))

a = tf.constant(1)
b = tf.constant(1)
print(sess.run(a+b))

次に, GPU で演算ができているか確認. tensorflow をインポートした時点で successfully opened CUDA library ... のような CUDA ライブラリの読み込みに成功したというメッセージが表示されている上さらに, config= に以下のようなオプションを付けることでどのデバイスが割り当てられているかのログを表示させられる.

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
sess.run(a+b)

add: /job:localhost/replica:0/task:0/gpu:0
Const_1: /job:localhost/replica:0/task:0/gpu:0

のようなログが表示され, 1+1 というどうでもいい演算が gpu:0, つまりグラフィックボードでおこなわれたことが確認された. グラフィックボードを複数搭載していれば gpu:1, gpu:2, ... にも 1+1 を割り当てることができる.

参考文献

他にもいろいろ見た気がするが覚えていたものと最終的に活用できた情報だけ列挙.

  1. Ubuntu14.04にcuda 7.5をインストール - Qiita

  2. CUDA Toolkit Documentation

  3. Solved CUDA 8.0 on Ubuntu 16.04 - GPU not available

  4. CUDA incompatible with my gcc version - Stack Overflow

  5. Ubuntu16.04LTSにCUDA7.5とcuDNNとCaffeをインストール - Qiita

  6. Download and Setup  |  TensorFlow

*1:もし, そもそも Ubuntu がまともに操作できない, 画面が表示されないなどという事態になった場合は, おそらくドライバがうまくインストールされてないせいなので, やはり仮想コンソールに入って sudo apt-get purge nvidia* してやり直すことになる.

*2:ちなみに13歳未満は登録禁止.

*3:いくつかのサイトでは承認に数日かかるという記述があるが, 今回は即座に承認された.

*4:もし nvidia-352 を正常に動かせるならこれは気にしなくても良い

*5:適切なバージョンがない場合は古いバージョンをインストールする方法を適当にググって.

*6:python 環境構築について知りたい場合は データサイエンティストを目指す人のpython環境構築 2016 - Qiita を参照