Python
Mac
Keras
TensorFlow
egpu

Macで外付けGPU使用しTensorflow GPUをソースからコンパイル(1.4/1.5対応)

Mac版Tensorflowは1.2からGPU版が正式配布されていないのでソースからコンパイルしてみたという話。

注意

2018年6月、Bazel、tensorflow、cuda、NVIDIA DRIVERが色々と変更されて大幅に設定方法を変える必要がありそうですので、最新の環境ではこの方法でうまくいかない可能性があります。

環境

ハード

  • MacBook Pro (Retina, 13-inch, Early 2015)
  • eGFX Breakaway Box (eGPU Expansion System)
  • - (これ以外のハードも試してみたので、機会があれば記載)
  • NVIDIA GeForce 1060 (GEFORCE GTX1060 6G OC (MSI))
  • アップル Thunderbolt 3(USB-C) - Thunderbolt 2アダプタ MMEL2AM/A

ソフト

  • MacOS10.13.3

  • Nvidia Webドライバ

  • XcodeCommandLineTool 8.3.2

  • cuda 9 (9.1)

  • cudnn 7

  • HomeBrew

  • Bazel

  • Anaconda

SIPについて

SIPは最近のMacのシステム整合性保護というやつで、野良ドライバの排除等の機能を担っており、Command + Rを押しながらシステムを起動した状態でコマンドプロンプトでcsrutilから記入する方式で変更可能です。(具体的な方法は後述)

eGPUを認識させる

基本的にはこちらの引用元そのまま
https://egpu.io/forums/mac-setup/wip-nvidia-egpu-support-for-high-sierra/

以前にeGPUにトライした人は

SierraでeGPUのためにInfo.plistを変更していたら元に戻します。(何もしていない人は気にしなくていいです)

GPUドライバ

SIPを有効にしたままWebドライバをインストールします。NVIDIAのwebサイトから最新のWebドライバをダウンロードしてインストール

http://www.nvidia.co.jp/Download/index.aspx?lang=jp
このURLから下記画像のように検索すると最新ドライバをダウンロードするページに移動します。
QuadroとありますがMac版はGeforceの個別のドライバは無いので、この条件で検索して問題ありません。

スクリーンショット 2018-01-29 13.22.15.png

CUDAドライバ

NVIDIAのwebサイト上にあるCUDAドライバインストーラを使ってインストール

オフィシャルの説明
http://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html

SIP

先述のSIPを変更するためcommand + Rを押しながらシステムを起動。リカバリモードからの起動状態になりますので、そこからメニューバーのユーティリティからターミナルを起動してcsrutil disable(SIPを停止させる。)もしくは、csrutil enable --without kext(ドライバのインストール可能にする)を実行。(どちらにせよ後述するTensorflowをソースからコンパイルする場合はSIPを停止させる必要があります。)

IMG_0529.jpg

High SierraでNVIDIAのGPUを動作をさせる。

このリンク先のリストにあるリンクを「macOS version」と「NVidia driver」のバージョンに合わせてダウンロードしてインストール。

スクリーンショット 2017-12-16 17.21.23.png

ダウンロードできないときは、safariを使ってダウンロードを試してください。

ディスプレイの表示や、省エネルギー設定にあるはずのGPU切り替え関連は変わっていないが、システムレポートのグラフィックス/ディスプレイ項目にはちゃんと表示されている。
スクリーンショット 2017-11-20 12.09.27.png

https://hnakamur.github.io/blog/2015/07/25/setup_cuda_on_macbook_pro_with_geforce/

ここまでで注意すべきところ

eGPU接続して起動時に真っ暗な状態から起動しない場合

一部の機種では、eGPUを接続した状態で起動した場合、真っ暗なままで起動画面が映らないことがある(当方そんな感じ)。
対処法は、一旦eGPUを切断した状態で起動してからeGPUを接続、電源を入れて、その後に一旦ログアウトする。すると、eGPU側のディスプレイも、元のディスプレイも表示されるし、認識もされる。
さらに、外部ディスプレイを繋いでディスプレイをミラーリングすると使用GPUがeGPUになるっぽい。

03bgqho4lugtlnmi.png

その他注意点

  • 上記の真っ暗な画面になる端末の場合、eGPUが有効(ケーブルが刺さっていてeGPUの電源が入っている)場合は通常の再起動をすると再起動後真っ暗になりますので、再起動は使わずにシステム終了してから起動したほうが良い。
  • ケーブルを抜くとクラッシュします。
  • GPUが認識されない場合は、「High SierraでNVidiaの動作をさせる。」項目のNVIDIA eGPU supportのバージョンがMacOSのバージョンと合っていない場合が考えられます。

Tensorflowをソースからコンパイル

ここからは各自の環境に強く左右されてエラーが起きやすいです。

このスレッドでエラー対応とか色々ノウハウが記載されています。上手く行かないときはこちらを読んでみては。
https://github.com/tensorflow/tensorflow/issues/12052#issuecomment-341937498

Anacondaをインストール

https://anaconda.org

Anacondaをインストールします。
python関連の処理をするまでであれば、特にどのタイミングでインストールしなければというわけではないです。

JDK

Homebrewを使うためにはJDKが必要です。
リンク先の「Accept License Agreement」をクリックしてからOSX用をダウンロードしてインストール。

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

Homebrew

Homebrewをインストール

一度もXcodeを起動したことがなかった場合、コンパイラを使うためにXcodeの利用規約を承認しろといった旨のエラーが出ますので、承認作業をしておくこと。

https://brew.sh/index_ja.html

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrewを使って色々インストール

brew update
brew upgrade

brew install coreutils
brew install swig
brew install bazel

Homebrewを使ってnvidia-cudaをインストール

最近、cask上ではcudaではなくnvidia-cudaという名前に変更されたらしい。
このタイミングでもドライバをインストールするので、前述のWebドライバはインストールする必要があるのかどうかは不明。

brew tap caskroom/drivers
brew cask install nvidia-cuda
# 確認
brew cask info nvidia-cuda

ejib8jhcr6tlz0k9.png

インストール後

BrewによるCUDAインストール後はバージョンが少し古くなっているので、「システム環境設定」の「CUDA」項目にある「Install Cuda Updage」をクリックしてバージョンを最新にしておく。
Webドライバも同じくバージョンを最新にしておく。

9zqv5d2ktgh3q5mi.png

cuDNN

NVIDIAにメンバー登録してサインインする。

https://developer.nvidia.com/accelerated-computing-developer

cuDNNをダウンロードする

https://developer.nvidia.com/cudnn

17年12月現在cuDNN v7.0.5のCUDA 9.0とCUDA 8.0にはMac版は有りません。
※Download cuDNN v7.0.5 (Dec 11, 2017), for CUDA 9.1や、Download cuDNN v7.0.4 (Nov 13, 2017), for CUDA 9.0を利用しましょう。

kqgzaxlibz2awcdi.png

ダウンロードしたら、cudnn-9.0-osx-x64-v7.tgzとかcudnn-9.1-osx-x64-v7-ga.tarのようなものがダウンロードされたかと思うので解凍。
解凍すると、

- cuda
- lib
- - libcudnn_static.a
- - libcudnn.dylib
- - libcudnn.7.dylib
- NVIDIA_SLA_cuDNN_Support
- include
- - cudnn.h

f4gksy6es4jf9a4i.png

のようになっていると思います。
ダウンロードフォルダにダウンロードされたと仮定して、新しくターミナルを開いて下記を実行

cd Downloads
sudo cp cuda/include/cudnn.h /usr/local/cuda/include/
sudo cp cuda/lib/libcudnn* /usr/local/cuda/lib/

実行したら、そのターミナルは閉じて構いません。

.bash_profile

.bash_profileを編集します。
(ユーザ名)は適宜変更。
CUDAのバージョンによっては、ディレクトリ名が変わっている可能性があるので、適宜変更。

# Anacondaインストール時に作られると思います。
# added by Anaconda3 5.0.1 installer
export PATH="/Users/(ユーザ名)/anaconda3/bin:$PATH"

# ここから追記

export CUDA_HOME=/usr/local/cuda

# 先述のCUDAが9.0の場合
# export DYLD_LIBRARY_PATH=/Users/(ユーザ名)/lib:/usr/local/cuda/lib:/usr/local/cuda/extras/CUPTI/lib:/Developer/NVIDIA/CUDA-9.0/lib
# CUDAが9.1の場合
export DYLD_LIBRARY_PATH=/Users/(ユーザ名)/lib:/usr/local/cuda/lib:/usr/local/cuda/extras/CUPTI/lib:/Developer/NVIDIA/CUDA-9.1/lib

export LD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
export PATH=$DYLD_LIBRARY_PATH:$PATH

# CUDAが9.0の場合
# export PATH=/Developer/NVIDIA/CUDA-9.0/bin${PATH:+:${PATH}}
# CUDAが9.1の場合
export PATH=/Developer/NVIDIA/CUDA-9.1/bin${PATH:+:${PATH}}

出来れば再起動したいところですが、bash_profileを再読込でも対応出来ます。

source ~/.bash_profile

コンパイル

コンパイルが動作しだすと大体2,3時間ほどかかるかと思います。

参考
https://gist.github.com/smitshilu/53cf9ff0fd6cdb64cca69a7e2827ed0f
https://github.com/nathanielatom/tensorflow/releases/tag/v1.4.0-mac

Xdoce command line tools

Xcodeとは別にコンパイラだけを独自に動かすため、Xcode command line toolsをインストール。
使用バージョンは8.3.2か8.2を推奨(9.Xは非対応)。

https://developer.apple.com/download/more/

pihs46b9x0jgiudi.png

なお、ソフトウェア・アップデートが最新版をインストールさせようと邪魔をしてくるので要注意。

clangの切り替え

# 現在のclangのバージョンの確認方法
/usr/bin/clang --version
# コマンドラインツールに変更
sudo xcode-select -s /Library/Developer/CommandLineTools
# バージョンが変わったのを確認する。
/usr/bin/clang --version
# パスの確認
sudo xcode-select -p
# 元に戻すときは下記を実行
# sudo xcode-select -r

ちなみにアンインストール方法はsudo xcode-select -rで元に戻してから/Library/Developer/CommandLineToolsを削除。

GPUのCompute Capabilityを確認する。

下記URLから利用するGPUのCompute Capabilityを確認。

https://developer.nvidia.com/cuda-gpus

GPU Compute Capability
... ...
GeForce GTX 1060 6.1
... ...

私はGTX1060を利用するので、この場合6.1という番号が必要です。

skhjy157tujzia4i.png

Gitからクローン

事前にGitをインストールしておく必要があります。
新たにターミナルを開いて下記を実行。
作業フォルダにtensorflowフォルダが出来ると思います。

git clone https://github.com/tensorflow/tensorflow
cd tensorflow

# Tensorflow 1.4の場合
# git checkout r1.4
# Tensorflow 1.5の場合
git checkout r1.5

コードを書き換える

特定のファイルの__align__(sizeof(T))の記述を削除する。
下記の行数になると思いますが、行番号が変わってる可能性もあります。

ファイル名 行番号 r1.4 r1.5
tensorflow/core/kernels/depthwise_conv_op_gpu.cu.cc 166 166
436 436
1054 1056
1313 1315
tensorflow/core/kernels/split_lib_gpu.cu.cc 122 122
tensorflow/core/kernels/concat_lib_gpu.impl.cu.cc 72 72

例えば

extern __shared__ __align__(sizeof(T)) unsigned char shared_memory[];

の場合は

extern __shared__ unsigned char shared_memory[];

となる。

さらにコードを書き換える。

少し前のclangにはOpenMPという並列スレッドのライブラリに対応していないようで、これが原因で下記のようなエラーが表示され、コンパイルが通らない時があります。

clang: warning: argument unused during compilation: '-pthread'
ld: library not found for -lgomp
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Target //tensorflow/tools/pip_package:build_pip_package failed to build
Use --verbose_failures to see the command lines of failed build steps.

https://qiita.com/r9y9/items/2e382887ee7e9fa0fb9f

対応策として、gens4でTensorflowを構築するか、該当部分のコードを消す必要があります。(今回は後者を選びました。)

https://medium.com/@mattias.arro/installing-tensorflow-1-2-from-sources-with-gpu-support-on-macos-4f2c5cab8186

(TensorflowのGitクローン先)/third_party/gpus/cuda/BUILD.tplが書き換え対象で、念のためにこのファイルのバックアップを取ったら112行目あたり(バージョンによって誤差あり)の

linkopts = [“-lgomp”]

を消して保存します。

SIPを無効にする

先述の方法でSIPを無効にします。

仮想環境を作る

ルート環境でも可能ですが、今回は仮想環境上で作業します。
ターミナルで下記のコードを使ってPythonの仮想環境を構築します。

# sudo conda create -n (仮想環境名) python=3.6.3 anaconda
sudo conda create -n tensor_env python=3.6.3 anaconda
source activate tensor_env
# 色々インストール
sudo pip install six numpy wheel --upgrade
# 失敗して環境を削除する場合
# sudo conda remove -n tensor_env --all

注意

仮想環境上にtensorflowをインストールしていても、ルート環境のパッケージが優先されるので、ルート環境にはTensorflowもkerasも入れないようにしましょう。
ルート環境上に構築しても良い場合は、ルート環境上で構築してください。

シンボリックリンク

エラー回避のため、いくつかのシンボリックリンクを張ります。
新しいターミナルを開いて 下記を実行。ここで使用したターミナルは閉じて構いません。

# 必ず必要っぽい
cd /usr/local/cuda/lib
sudo ln -s libcuda.dylib libcuda.1.dylib
# (ユーザ名)を適宜変更
sudo ln /Users/(ユーザ名)/anaconda3/lib/libgomp.1.dylib /usr/local/lib/libgomp.1.dylib
# anacondaのインストール先によっては、
# sudo ln /anaconda3/lib/libgomp.1.dylib /usr/local/lib/libgomp.1.dylib

# シンボリックリンク解除方法
# unlink /usr/local/cuda/lib/libcuda.1.dylib
# unlink /usr/local/lib/libgomp.1.dylib

# シンボリックリンクを張る事によって下記のCUDAのバージョン確認方法が使えます。
# nvcc -V

18/02/22 # unlink /usr/local/lib/libcuda.1.dylib# unlink /usr/local/cuda/lib/libcuda.1.dylibに修正しました。

configure

作業ディレクトリはGitのクローン上で行います。もし新しいターミナルで作業する場合はcd tensorflowsource activate tensor_env(仮想環境名)を実行し、もし、.bash_profileを変更後に再起動していなければsource ~/.bash_profileで再読込をしてから下記を実行してください。

./configure

もし、コンパイルが失敗したりした場合、下記を実行してから./configureをやり直す。

# やり直しの場合等
# https://qiita.com/tnzk/items/111a4450142fbb250b0b
bazel clean

./configureを実行すると、質問形式での入力を行うことになります。
私は下記のように実行。
その際にPlease note that each additional compute capability significantly increases your build time and binary size. [Default is: 3.5,5.2]には、GPUのCompute Capabilityを確認する。で調べておいた数値を入力。
Please specify the CUDA SDK version....の項目はバージョンによって変更。

Tensorflow 1.5での修正箇所

Tensorflow 1.5では、Do you wish to build TensorFlow with XLA JIT support?が上手く対応出来なかったのでnにして使用しないように変更しました。
また、Please specify the CUDA SDK version you want to use,~を9.1に変更しております。CUDAが9.0の方は9.0と入力ください。
r1.5の場合、最後の質問にWould you like to interactively configure ./WORKSPACE for Android builds?が増えておりますが、Nを選択してます。

(tensor_env) XXX-macbook-pro:tensorflow XXX$ ./configure
You have bazel 0.10.1-homebrew installed.
Please specify the location of python. [Default is /Users/XXX/anaconda3/envs/tensor_env/bin/python]: 

Found possible Python library paths:
  /Users/XXX/anaconda3/envs/tensor_env/lib/python3.6/site-packages
Please input the desired Python library path to use.  Default is [/Users/XXX/anaconda3/envs/tensor_env/lib/python3.6/site-packages]


Do you wish to build TensorFlow with Google Cloud Platform support? [Y/n]: n
No Google Cloud Platform support will be enabled for TensorFlow.

Do you wish to build TensorFlow with Hadoop File System support? [Y/n]: n
No Hadoop File System support will be enabled for TensorFlow.

Do you wish to build TensorFlow with Amazon S3 File System support? [Y/n]: n
No Amazon S3 File System support will be enabled for TensorFlow.

Do you wish to build TensorFlow with XLA JIT support? [y/N]: n
No XLA JIT support will be enabled for TensorFlow.

Do you wish to build TensorFlow with GDR support? [y/N]: n
No GDR support will be enabled for TensorFlow.

Do you wish to build TensorFlow with VERBS support? [y/N]: n
No VERBS support will be enabled for TensorFlow.

Do you wish to build TensorFlow with OpenCL SYCL support? [y/N]: n
No OpenCL SYCL support will be enabled for TensorFlow.

Do you wish to build TensorFlow with CUDA support? [y/N]: y
CUDA support will be enabled for TensorFlow.

Please specify the CUDA SDK version you want to use, e.g. 7.0. [Leave empty to default to CUDA 9.0]: 9.1


Please specify the location where CUDA 9.1 toolkit is installed. Refer to README.md for more details. [Default is /usr/local/cuda]: 


Please specify the cuDNN version you want to use. [Leave empty to default to cuDNN 7.0]: 7


Please specify the location where cuDNN 7 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda]:


Please specify a list of comma-separated Cuda compute capabilities you want to build with.
You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
Please note that each additional compute capability significantly increases your build time and binary size. [Default is: 3.5,5.2]6.1


Do you want to use clang as CUDA compiler? [y/N]: n
nvcc will be used as CUDA compiler.

Please specify which gcc should be used by nvcc as the host compiler. [Default is /usr/bin/gcc]: 


Do you wish to build TensorFlow with MPI support? [y/N]: 
No MPI support will be enabled for TensorFlow.

Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native]: 


Add "--config=mkl" to your bazel command to build with MKL support.
Please note that MKL on MacOS or windows is still not supported.
If you would like to use a local MKL instead of downloading, please set the environment variable "TF_MKL_ROOT" every time before build.

Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: 
Not configuring the WORKSPACE for Android builds.

Configuration finished

ビルド

大体2,3時間以上かかります。

bazel build --config=cuda --config=opt --action_env PATH --action_env LD_LIBRARY_PATH --action_env DYLD_LIBRARY_PATH //tensorflow/tools/pip_package:build_pip_package

エラーメモ

ここまででエラーが出たら下記を見直したり試したりしてみる。

  • bazel clean してから./configureのやり直し。
  • source activate (pythonの仮想環境名)でアクティベートした状態でコンパイルしてみる。
  • .bash_profileの書き換え。
  • 先述の「さらにコードを書き換える。」項目の内容を試してみる。
  • bazel buildコマンド内に--cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0"を追記してビルド。
  • ./configureの内容を変えてみる(CUDA以外のサポートをNにして使わないようにしてみる等)

既にコンパイル済みのパッケージを利用する

どうしてもコンパイルが通らないという人は、前述したスレッド にコンパイル済みの環境をアップロードしている人がいるので、そちらをパッケージ化してインストールして試してみるというのも一つの手です。ただし当然ですがオフィシャルではないので利用は自己責任で。

Pythonへパッケージのインストール

source activate tensor_env(仮想環境名)で仮想環境に入っている状態で下記を実行。

setuptoolsをインストール

sudo pip install -U pip setuptools

パッケージ化

bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

多少エラーが出ても通っていても、出力がされていればOK

パッケージのインストール

# 1.4
# sudo pip install /tmp/tensorflow_pkg/tensorflow-1.4.1-cp36-cp36m-macosx_10_7_x86_64.whl
# 1.5
sudo pip install /tmp/tensorflow_pkg/tensorflow-1.5.0-cp36-cp36m-macosx_10_7_x86_64.whl

もしくは

# キャッシュ無効、再インストール
# sudo pip --no-cache-dir install -I /tmp/tensorflow_pkg/tensorflow-1.4.1-cp36-cp36m-macosx_10_7_x86_64.whl
sudo pip --no-cache-dir install -I /tmp/tensorflow_pkg/tensorflow-1.5.0-cp36-cp36m-macosx_10_7_x86_64.whl

keras

kerasを使うのであれば、それも入れてみましょう。

pip install keras --upgrade

https://gist.github.com/smitshilu/53cf9ff0fd6cdb64cca69a7e2827ed0f

実際にkerasを使って実行したら下記のような感じで動作しました。

/Users/XXX/anaconda3/envs/tensor_env/bin/python /Users/XXX/python/projects/プロジェクト名/main.py
Using TensorFlow backend.
2017-11-27 17:40:08.986765: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2017-11-27 17:40:09.250666: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:856] OS X does not support NUMA - returning NUMA node zero
2017-11-27 17:40:09.252086: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties: 
name: GeForce GTX 1060 6GB major: 6 minor: 1 memoryClockRate(GHz): 1.759
pciBusID: 0000:c3:00.0
totalMemory: 6.00GiB freeMemory: 5.49GiB
2017-11-27 17:40:09.252127: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: GeForce GTX 1060 6GB, pci bus id: 0000:c3:00.0, compute capability: 6.1)
/Users/XXX/python.py:154: UserWarning: Update your `Model` call to the Keras 2 API: `Model(inputs=Tensor("in..., outputs=Tensor("de...)`
  model = Model(input=inputs, output=predictions)
Train on 351 samples, validate on 50 samples
Epoch 1/10

  8/351 [..............................] - ETA: 3:36 - loss: 0.7039 - acc: 0.5000
 48/351 [===>..........................] - ETA: 32s - loss: 0.6816 - acc: 0.6250 
 96/351 [=======>......................] - ETA: 13s - loss: 0.6604 - acc: 0.6354
152/351 [===========>..................] - ETA: 6s - loss: 0.6430 - acc: 0.6776 
以下略

d002ltqo8mt5ipb9.png

要注意事項

システムの変更(OSのアップデート等)はeGPU接続状態で行わない方が良いです
理由は、機種によりますがOSのアップデート中に画面が真っ暗な状態になり、OSのアップデートがどこまで進んでるか分からない状態になる事があるためです。
アップデートの最中に電源を無理やり落とすと、最悪システムが破損して起動しなくなります。

その他参考

https://gist.github.com/ageitgey/819a51afa4613649bd18
日本語訳
http://tensorflow.hatenablog.com/entry/2015/12/31/210000
https://github.com/tensorflow/tensorflow/issues/13243
https://srikanthpagadala.github.io/notes/2016/11/07/enable-gpu-support-for-tensorflow-on-macos
http://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html
https://medium.com/@mattias.arro/installing-tensorflow-1-2-from-sources-with-gpu-support-on-macos-4f2c5cab8186

修正

17/12/16 MacOS10.13.2用に変更。
17/12/16 cuDNNの7.0.5以降にMac用がなくなっています。
18/01/09 CUDAドライバのURLが間違っておりましたので、修正しました。
18/01/29 ドライバのURL、cuDNN7.0.5、CUDA 9.1にOSX版が追加されました。
18/02/22 Tensorflow 1.5に対応しました。
18/02/22 ハードウェアに変換機を書いてなかったので追記しました。