Posted at
KOIL CSCDay 11

TensorFlow を macOS 10.12 + CUDA 8.0 向けにセットアップする

More than 1 year has passed since last update.


概要

基本的な指針はTensorflowでOSXのGPUが対応されたよに従う。

2016年12月5日現在で、 Brew で CUDA を入れると、そのバージョンは 8.0 になるようだった。公式のDownload and Setupの手順ではうまくいかなかったので、この gist のこのコメントを参考にする。


セットアップ


Python 3.5 のインストール

Python は最近使っていなかったので、今回は 3.5 をインストールすることにする。 Mac ではデフォルトで Python 2.x が入っているので、 pyenv を使うのが良いらしい1

$ brew install pyenv

$ pyenv install 3.5.2
Downloading Python-3.5.2.tar.xz...
-> https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tar.xz
Installing Python-3.5.2...

BUILD FAILED (OS X 10.12 using python-build 20160602)

Inspect or clean up the working tree at /var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297
Results logged to /var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297.log

Last 10 log lines:
File "/private/var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297/Python-3.5.2/Lib/ensurepip/__main__.py", line 4, in <module>
ensurepip._main()
File "/private/var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297/Python-3.5.2/Lib/ensurepip/__init__.py", line 209, in _main
default_pip=args.default_pip,
File "/private/var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297/Python-3.5.2/Lib/ensurepip/__init__.py", line 116, in bootstrap
_run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
File "/private/var/folders/__/37mkgf2x4t70wt679szztc5m0000gn/T/python-build.20161205163930.24297/Python-3.5.2/Lib/ensurepip/__init__.py", line 40, in _run_pip
import pip
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1

zlib がないと言われたので、 xcode-select する2

$ xcode-select --install

$ pyenv install 3.5.2
$ pyenv global 3.5.2
$ python --version
Python 3.5.2

Python 3 は昔、 Pytho 2.x 向けに書かれたコードと互換性がないことを理由に触らないでいて、そのまま触れる機会がないままでいたけど、改めて調べてみたらそれほど大きな変更はなさそうだ3


CUDA, Bazel, cuDNN のインストール

CUDA と cuDNN は TensorFlow が直接必要としている。 Bazel は TensorFlow のビルドに必要になる。

$ brew cask install cuda

$ brew install bazel

cuDNN は NVIDIA Developer に登録しないとダウンロードできない。

NVIDIA cuDNN から "Download" をクリックしてアニメでも見ながら頭を使わずに NVIDIA の指示に従っていれば、気づいたときには利用規約に同意した上で cudnn-8.0-osx-x64-v5.1.tgz がダウンロードされているはずだ。

macOS 向けかつCUDA 8.0 向けのものをダウンロードすることに注意。困ったら、詳しい方法はTensorflowでOSXのGPUが対応されたよで紹介されている。

このアーカイブにはバイナリが入っているので、適切なディレクトリに移動しておく。

$ tar xvf cudnn-8.0-osx-x64-v5.1.tgz

$ sudo mv -v cuda/lib/libcudnn* /usr/local/cuda/lib
$ sudo mv -v cuda/include/cudnn.h /usr/local/cuda/include
$ sudo ln -s /usr/local/cuda/lib/libcudnn.5.dylib /usr/local/cuda/lib/libcudnn.5
$ cd /usr/local/lib
$ sudo ln -s libcuda.dylib libcuda.1.dylib
$ sudo ln -s ../cuda/lib/libcudart.8.0.dylib .
$ sudo ln -s /usr/local/cuda/lib/* /usr/local/lib

最後の3つの symlink は、もしかしたら今の TensorFlow のビルドシステムに問題があって必要なだけかもしれない。

1つ目(libcudnn.5)は、張らないと configure できない。

2つ目(libcuda.1.dylib)は、 Bazel が長時間いい感じに進んだあとで、最後にビルドエラーになる。

3つ目の symlink は張らなくてもビルドはできるが、 TensorFlow をインポートしたときに segmentation fault を得ることになる。そのときに張っても良い。

4つ目の symlink も張らなくてもビルドはできる。 El Capitan 以降、 DYLD_LIBRARY_PATH は System Itegrity Protection の加護により使えなくなったので、 CUDA 関係のライブラリはこの環境変数を使う代わりに、ロードパスにある場所から symlink しておく。


TensorFlow のインストール

ビルド対象のコードを得る。

$ git clone --recurse-submodules https://github.com/tensorflow/tensorflow

$ git pull --tags
$ git checkout 0.12.0-rc0

configure する。いくつか入力を求められるが、基本的にはデフォルトのままで良い。「GPU support を有効化するか?」という確認もあったはずだけど、この環境変数を渡した場合は、そこは自明だということなのか、入力は求められなかった。

自分の場合は「Python library path が複数見つかったがどれを使う?」という確認があったので、 pyenv を使って入れた 3.5 のパスを指定した。それ以外はデフォルトにした。

$ CUDA_TOOLKIT_PATH="/usr/local/cuda" CUDNN_INSTALL_PATH="/usr/local/cuda" TF_UNOFFICIAL_SETTING=1 TF_NEED_CUDA=1 TF_CUDA_COMPUTE_CAPABILITIES="3.0" TF_CUDNN_VERSION="5" TF_CUDA_VERSION="8.0" TF_CUDA_VERSION_TOOLKIT=8.0 ./configure

configure できたら、 bazel で pip パッケージをビルドして、 pip でインストールする。pyenv で入れても pip は sudo じゃないと permission error が出た。ここは rbenv と思想の違うところなのだろうか。

$ bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package

$ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
$ pip3 install --upgrade /tmp/tensorflow_pkg/tensorflow-0.12.0rc0-cp35-cp35m-macosx_10_6_x86_64.whl

直接指定しても良いと思う。

いくつか実行時に必要なパスがあるので、 .bash_profile に書いておく。

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64"

export CUDA_HOME=/usr/local/cuda

これで準備が整った。動作確認する。

$ python

Python 3.5.2 (default, Dec 5 2016, 16:46:59)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.8.0.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.5.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.8.0.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.1.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.8.0.dylib locally

CUDA 関係のライブラリがロードされている。とりあえずセットアップは完了したみたいだ。


動作確認


Hello World

公式の手順に従って動作確認する。

$ python

Python 3.5.2 (default, Dec 5 2016, 16:46:59)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
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.8.0.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.5.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.8.0.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.1.dylib locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.8.0.dylib locally
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
E tensorflow/stream_executor/cuda/cuda_driver.cc:509] failed call to cuInit: CUDA_ERROR_NOT_INITIALIZED
I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:158] retrieving CUDA diagnostic information for host: ingrid.local
I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:165] hostname: ingrid.local
I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:189] libcuda reported version is: Not found: was unable to find libcuda.so DSO loaded into this program
I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:193] kernel reported version is: Invalid argument: expected %d.%d or %d.%d.%d form for driver version; got ""
>>> print(sess.run(hello))
b'Hello, TensorFlow!'
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>

GPU を活用して生命、宇宙、そして万物についての究極の疑問の答えを計算することができた。


MNIST

tensorflow.models.image.mnist.convolutional を使って動作検証する。

$ python -m tensorflow.models.image.mnist.convolutional

(snip)
Minibatch loss: 1.598, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.9%
Test error: 0.8%

以前 CPU-only で試したときより早い…?


おまけ


import tensorflow すると、 ImportError: cannot import name 'pywrap_tensorflow' と言われる

TensorFlow のリポジトリがあるディレクトリで tensorflow をロードするとこういうエラーが出る。別のディレクトリに言って試せば良い4


import tensorflow すると、 segmentation fault 11 が起きる

libcuda.1.dylib という名前でロードしようとするので、そのための symlink を作っておく5


CPU-only TensorFlow のインストール

こっちはとても簡単。

$ pip3 install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.12.0rc0-py3-none-any.whl





  1. Mac環境へのPython3系インストール 



  2. MacでPython 3.5.0インストールに失敗したら 



  3. Python 2.7.x と 3.x の決定的な違いを例とともに 



  4. ImportError: cannot import name pywrap_tensorflow 


    You're running the script in the same directory as tensorflow. Move it out and you should be fine.




  5. Segmentation fault, import tensorflow, tensorflow 0.9, mac osx 


    Having the same problem, It appears that it fails when loading libcuda.dylib. Unfortunately, since #2878 it's now looking for libcuda.1.dylib instead.

    Creating a symlink or changing the name of libcuda.dylib to libcuda.1.dylib in /usr/local/cuda/lib seems to do the job.