GPU
NVIDIA
python3
Keras
TensorFlow

Ubuntu18.04にCUDA9.0とcuDNN7.0.5を入れて、Tensorflow-gpuを動かす

まず簡潔に

Ubuntu18.04を前提として、Tensorflow-gpu環境構築で行うことは主に以下の5つです
・Nvidia driverの導入
・CUDAの導入
・cuDNNの導入
・Anacondaの導入
・Tensorflow-gpuの導入

これらの操作は以下に記載している参考リンクが非常に参考になります。
こちらの記事を参考に環境構築を行った後であることを、本記事では前提とします。

環境構築を行い、実際にコードを書いて何かしらの学習をスタートさせると、
「Tensorflow-gpuはcuDNN7.0向けに設計されているが、実際に環境にインストールされているのはcuDNN7.3ですよ」
とのエラーを受け、学習がスタートしないという問題がありました。

解決の結論としては、
「Tensorflow-gpuのバージョンごとに、cuDNNバージョンが指定されているので、正しいcuDNNを入れましょう」
ということです。

上記の内容を以下で詳しく書いていきます。

実施環境

Ubuntu 18.04.1 LTS
Celeron G3930
NVIDIA Geforce GTX1080
CUDA 9.0
cuDNN 7.0.5
Python 3.6.7
Tensorflow-gpu 1.5.0(1.6.0以上では、CPUによる動作制限があるようです)
Keras 2.2.4

参考リンク

環境構築の全体の流れがとても整理されている記事です
https://qiita.com/sho8e69/items/66c1662c49ac89a024be#ubuntu%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

このあたりのQ&Aを読むとかなりヒントがあります
https://groups.google.com/forum/m/#!topic/keras-users/kfzPSDvmhPo
https://stackoverflow.com/questions/37663064/cudnn-compile-configuration-in-tensorflow

今回、Tensorflow-gpu 1.5.0を入れている理由です
http://arakan-pgm-ai.hatenablog.com/entry/2018/06/21/090000

具体的なエラー

上記で紹介した、
「Tensorflow-gpuはcuDNN7.0向けに設計されているが、実際に環境にインストールされているのはcuDNN7.3ですよ」
とは具体的に一体どういうものなのか示します。

2018-11-06 18:00:04.565740: E
tensorflow/stream_executor/cuda/cuda_dnn.cc:378] Loaded runtime CuDNN library: 7300 (compatibility version 7300) but source was compiled with 7004 (compatibility version 7000).
If using a binary install, upgrade your CuDNN library to match.
If building from sources, make sure the library loaded at runtime matches a compatible version specified during compile configuration.
2018-11-06 18:00:04.566903: F 
tensorflow/core/kernels/conv_ops.cc:717] Check failed: stream->parent()->GetConvolveAlgorithms( conv_parameters.ShouldIncludeWinogradNonfusedAlgo<T>(), &algorithms) 
中止 (コアダンプ)

これです、このエラーの意味が、
「Tensorflow-gpuはcuDNN7.0向けに設計されているが、実際に環境にインストールされているのはcuDNN7.3ですよ」
となります。

解決

エラーの意味がわかったので、解決していきます。

Tensorflow-gpuが本当にcuDNN7.0向けに設計されているかどうかの確認は置いておいて、
ローカル環境にインストールされているcuDNNのバージョンを確認しましょう。
以下のコードをターミナルに入力します。

$ dpkg -l | grep cuda

出力は以下のようになりました。

ii  cuda-command-line-tools-9-0                9.0.176-1                                   amd64        CUDA command-line tools
ii  cuda-core-9-0                              9.0.176-1                                   amd64        CUDA core tools
ii  cuda-cublas-9-0                            9.0.176-1                                   amd64        CUBLAS native runtime libraries
ii  cuda-cublas-dev-9-0                        9.0.176-1                                   amd64        CUBLAS native dev links, headers
ii  cuda-cudart-9-0                            9.0.176-1                                   amd64        CUDA Runtime native Libraries
ii  cuda-cudart-dev-9-0                        9.0.176-1                                   amd64        CUDA Runtime native dev links, headers
ii  cuda-cufft-9-0                             9.0.176-1                                   amd64        CUFFT native runtime libraries
ii  cuda-cufft-dev-9-0                         9.0.176-1                                   amd64        CUFFT native dev links, headers
ii  cuda-curand-9-0                            9.0.176-1                                   amd64        CURAND native runtime libraries
ii  cuda-curand-dev-9-0                        9.0.176-1                                   amd64        CURAND native dev links, headers
ii  cuda-cusolver-9-0                          9.0.176-1                                   amd64        CUDA solver native runtime libraries
ii  cuda-cusolver-dev-9-0                      9.0.176-1                                   amd64        CUDA solver native dev links, headers
ii  cuda-cusparse-9-0                          9.0.176-1                                   amd64        CUSPARSE native runtime libraries
ii  cuda-cusparse-dev-9-0                      9.0.176-1                                   amd64        CUSPARSE native dev links, headers
ii  cuda-documentation-9-0                     9.0.176-1                                   amd64        CUDA documentation
ii  cuda-driver-dev-9-0                        9.0.176-1                                   amd64        CUDA Driver native dev stub library
ii  cuda-libraries-dev-9-0                     9.0.176-1                                   amd64        CUDA Libraries 9.0 development meta-package
ii  cuda-license-9-0                           9.0.176-1                                   amd64        CUDA licenses
ii  cuda-misc-headers-9-0                      9.0.176-1                                   amd64        CUDA miscellaneous headers
ii  cuda-npp-9-0                               9.0.176-1                                   amd64        NPP native runtime libraries
ii  cuda-npp-dev-9-0                           9.0.176-1                                   amd64        NPP native dev links, headers
ii  cuda-nvgraph-9-0                           9.0.176-1                                   amd64        NVGRAPH native runtime libraries
ii  cuda-nvgraph-dev-9-0                       9.0.176-1                                   amd64        NVGRAPH native dev links, headers
ii  cuda-nvml-dev-9-0                          9.0.176-1                                   amd64        NVML native dev links, headers
ii  cuda-nvrtc-9-0                             9.0.176-1                                   amd64        NVRTC native runtime libraries
ii  cuda-nvrtc-dev-9-0                         9.0.176-1                                   amd64        NVRTC native dev links, headers
ii  cuda-repo-ubuntu1704-9-0-local             9.0.176-1                                   amd64        cuda repository configuration files
ii  cuda-samples-9-0                           9.0.176-1                                   amd64        CUDA example applications
ii  cuda-toolkit-9-0                           9.0.176-1                                   amd64        CUDA Toolkit 9.0 meta-package
ii  cuda-visual-tools-9-0                      9.0.176-1                                   amd64        CUDA visual tools
ii  libcudnn7                                  7.3.0.29-1+cuda9.0                          amd64        cuDNN runtime libraries
ii  libcudnn7-dev                              7.3.0.29-1+cuda9.0                          amd64        cuDNN development libraries and headers
ii  libcudnn7-doc                              7.3.0.29-1+cuda9.0                          amd64        cuDNN documents and samples

下3つにcuDNNのバージョンが記載されています。
libcudnn7、libcudnn7-dev、libcudnn7-docの3つです。
バージョンは7.3のようです。

エラーの意味は、
「Tensorflow-gpuはcuDNN7.0向けに設計されているが、実際に環境にインストールされているのはcuDNN7.3ですよ」
だったので、
「7.3を消して7.0を入れる」
ことを目指せばエラーが解消されそうです。

以下のコードで、cuDNN7.3を消しましょう

$ sudo apt-get --purge remove libcudnn7

この操作だけで、libcudnn7、libcudnn7-dev、libcudnn7-docの3つが消去されます。

次に、cuDNN7.0を入れていきます。
が、実際に入れるのはcuDNN7.0.5です。
cuDNNダウンロードリンクからダウンロードします。
Screenshot from 2018-11-07 10-57-19.png
「Download cuDNN v7.0.5 [Dec 5, 2017], for CUDA 9.0」を選択肢するとプルダウンが現れます。
Screenshot from 2018-11-07 11-01-01.png
「cuDNN v7.0.5 Runtime Library for Ubuntu16.04 (Deb)」、
「cuDNN v7.0.5 Developer Library for Ubuntu16.04 (Deb)」、
「cuDNN v7.0.5 Code Samples and User Guide for Ubuntu16.04 (Deb)」
の3つをダウンロードします。

ターミナル上で保存先のディレクトリに移動し、
以下のコマンドを実行すると、cuDNN7.0.5がインストールされます。

$ sudo dpkg -i libcudnn7_7.0.5.15-1+cuda9.0_amd64.deb
$ sudo dpkg -i libcudnn7-dev_7.0.5.15-1+cuda9.0_amd64.deb
$ sudo dpkg -i libcudnn7-doc_7.0.5.15-1+cuda9.0_amd64.deb

cuDNNのバージョンを確認してみましょう。
以下のコマンドで確認します。

$ dpkg -l | grep cuda

出力は以下です。cuDNN以外の部分は省略しました。

ii  libcudnn7                                  7.0.5.15-1+cuda9.0                          amd64        cuDNN runtime libraries
ii  libcudnn7-dev                              7.0.5.15-1+cuda9.0                          amd64        cuDNN development libraries and headers
ii  libcudnn7-doc                              7.0.5.15-1+cuda9.0                          amd64        cuDNN documents and samples

GPU動作の確認

ここまでで、問題だったエラー
「Tensorflow-gpuはcuDNN7.0向けに設計されているが、実際に環境にインストールされているのはcuDNN7.3ですよ」
が解決されているはずです。

実際にGPU動作を確認してみましょう。

pythonコンソールの起動

$ python

Tesorflowのインポート
GPU認識確認

>>> import tensorflow as tf
>>> tf.test.gpu_device_name()

以下が表示されるか確認してください。

'/device:GPU:0'

さあ、GPU動作を確認しましょう。
以下のコードが書かれたpythonファイルを作成し、実行してください。
引用:https://www.kaggle.com/getting-started/47096#post271139

GPU_performance_check.py
import tensorflow as tf
import timeit

# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True

with tf.device('/cpu:0'):
  random_image_cpu = tf.random_normal((100, 100, 100, 3))
  net_cpu = tf.layers.conv2d(random_image_cpu, 32, 7)
  net_cpu = tf.reduce_sum(net_cpu)

with tf.device('/gpu:0'):
  random_image_gpu = tf.random_normal((100, 100, 100, 3))
  net_gpu = tf.layers.conv2d(random_image_gpu, 32, 7)
  net_gpu = tf.reduce_sum(net_gpu)

sess = tf.Session(config=config)

# Test execution once to detect errors early.
try:
  sess.run(tf.global_variables_initializer())
except tf.errors.InvalidArgumentError:
  print(
      '\n\nThis error most likely means that this notebook is not '
      'configured to use a GPU.  Change this in Notebook Settings via the '
      'command palette (cmd/ctrl-shift-P) or the Edit menu.\n\n')
  raise

def cpu():
  sess.run(net_cpu)

def gpu():
  sess.run(net_gpu)

# Runs the op several times.
print('Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images '
      '(batch x height x width x channel). Sum of ten runs.')
print('CPU (s):')
cpu_time = timeit.timeit('cpu()', number=10, setup="from __main__ import cpu")
print(cpu_time)
print('GPU (s):')
gpu_time = timeit.timeit('gpu()', number=10, setup="from __main__ import gpu")
print(gpu_time)
print('GPU speedup over CPU: {}x'.format(int(cpu_time/gpu_time)))

sess.close()

以下のような結果が表示されれば、GPUが確かに動作しており、
CPUとGPUの処理時間の比較結果が見れます。

CPU (s):
8.017979502001253
GPU (s):
2.884423554998648
GPU speedup over CPU: 2x

まとめ

参考リンクを前提としてTensorflow-gpu環境構築を行った後、いざ学習してみようとしたら、
「Tensorflow-gpuが想定しているcuDNNのバージョンと、実際のcuDNNのバージョンが異なる」
ことに起因するエラーについて、解決策を示しました。

バージョンに関して、互換性・整合性をちゃんと確認しなければいけないなと思いました。

誰かのご参考になれば幸いです。