流れ
python3.5 の venv 環境で TensorFlow の実験を行うことにした。
適当な作業ディレクトリで
python -m venv P
source P/bin/activate
pip install --upgrade tensorflow
などとする。
pip が自分自身をインストールせよと言い、他に自前の script で利用していたので
pip install --upgrade pip
pip install --upgrade numpy
pip install --upgrade matplotlib
pip install --upgrade opencv-python
などとする(pip自身のインストールは最初にやってしまっていいかもしれない)。
これで、自前の script は動いたが、よく見ると gpu を使っていない。
pip install --upgrade tensorflow-gpu
すればいいような気もしたが、どうも中身が古い。
pip install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.8.0-py3-none-any.whl
するのが正しいかと思えば(現時点最新が 1.8)、公式には macOS での GPU 利用はサポートされなくなっていた。
しょうがないので tensorflow を野良 build してみる。
以下は https://qiita.com/74th/items/fc6ebb684c23f3655e7c を参考にしている。
bazel
tensorflow の build に bazel が使われる。
MacPorts からインストールを試みると、コンパイル終了後 bash completion 作成のためにローカルに git リポジトリを作って commit する箇所がある。
この時、 git を使っていない環境だと
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
を出す。
多分、正しいのは Portfile (/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/devel/bazel/Portfile) を修正して --global
抜きの
git config user.email "you@example.com"
git config user.name "Your Name"
を git init
の後に追加しておくことだと思われる。
あるいは、一旦 build 失敗した後で build ディレクトリに cd して上記 git config
して、再度 port install
でやり直させる。
bash completion 作成時には猛烈に load av. が上がる。
この時、終了しきらない java のプロセスが 1process あり、 bazel がその終了待ちになってインストールプロセスが終了しなくなっていた。
この終了しない java の process の process ID を確認して sudo kill
すると MacPorts のインストールプロセスの残りすべて完了する。
tensorflow
git clone https://github.com/tensorflow/tensorflow.git -b v1.8.0
する。前述 venv 環境のまま
./configure
して [y/n] 質問は基本 n で cuda 使用のみ y。
python は venv 環境の python が選ばれているはず。
cuDNN が必要で、 macOS 用のものは cuDNN-7.0.5 の CUDA-9.1 用が存在しているのでこれを使う。 /usr/local/ で tar で展開すればいいが、 cuda/include/ が symlink なので cudnn.h だけ配置に失敗する。適当なディレクトリで展開して手でコピーする。
その他 version などは適当に。
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
で build する。
CUDA 実行環境
現時点で、 CUDA の最新は 9.1 であり Xcode の最新が 9.3 になっているが、 CUDA 9.1 の nvcc はそれより後に出た Xcode 9.3 の clang を使えない(バージョンチェックで弾く仕様)。
そのため、 Command Line Tools (macOS 10.13) for Xcode 9.2 を https://developer.apple.com/download/more/ から取得して来てインストールして、
sudo xcode-select --switch /Library/Developer/CommandLineTools
これで nvcc は動くようになったが、なぜか実行時に
./deviceQuery
./deviceQuery Starting...
CUDA Device Query (Runtime API) version (CUDART static linking)
cudaGetDeviceCount returned 35
-> CUDA driver version is insufficient for CUDA runtime version
Result = FAIL
のようになる。
この件、結局 http://www.xlr8yourmac.com/archives/apr18/NvidiaCUDAandDriverUpdates.htm から 387.10.10.10.30.107 という nvidia web driver を取得して来てインストールしてやっと解決した(CUDA再インストールでランタイムライブラリとCUDA driverを再インストールしても直らない。環境設定のCUDA Preferenceから387.178にUpdateしても直らない)。
インストール手順は https://devtalk.nvidia.com/default/topic/1025945/mac-cuda-driver-fully-compatible-with-macos-high-sierra-10-13-error-quot-update-required-quot-solved-/?offset=173 である。
macOS で CUDA の実行環境を維持するのは本当に大変。
tensorflow build
前述の bazel コマンドで build。
以下の問題に逢うので tensorflow/workspace.bzl
を修正する(eigen_archive の分は修正不要)。
diff --git a/tensorflow/workspace.bzl b/tensorflow/workspace.bzl
index 48728ac131..268e4fe2e6 100644
--- a/tensorflow/workspace.bzl
+++ b/tensorflow/workspace.bzl
@@ -330,11 +330,11 @@ def tf_workspace(path_prefix="", tf_repo_name=""):
tf_http_archive(
name = "protobuf_archive",
urls = [
- "https://mirror.bazel.build/github.com/google/protobuf/archive/396336eb961b75f03b25824fe86cf6490fb75e3a.tar.gz",
- "https://github.com/google/protobuf/archive/396336eb961b75f03b25824fe86cf6490fb75e3a.tar.gz",
+ "https://mirror.bazel.build/github.com/dtrebbien/protobuf/archive/50f552646ba1de79e07562b41f3999fe036b4fd0.tar.gz",
+ "https://github.com/dtrebbien/protobuf/archive/50f552646ba1de79e07562b41f3999fe036b4fd0.tar.gz",
],
- sha256 = "846d907acf472ae233ec0882ef3a2d24edbbe834b80c305e867ac65a1f2c59e3",
- strip_prefix = "protobuf-396336eb961b75f03b25824fe86cf6490fb75e3a",
+ sha256 = "eb16b33431b91fe8cee479575cee8de202f3626aaf00d9bf1783c6e62b4ffbc7",
+ strip_prefix = "protobuf-50f552646ba1de79e07562b41f3999fe036b4fd0",
)
# We need to import the protobuf library under the names com_google_protobuf
TensorFlow 1.8 からは nvidia の NCCL ライブラリが前提のようだが、現時点版(2.2)には macOS 用が存在しない。
古い 1.3.4 が以下に存在しているのでダウンロードして /usr/local/cuda/ に展開して、 tensorflow/third_party/nccl/
に /usr/local/cuda/include/nccl.h への symlink を作っておく。
https://storage.googleapis.com/74thopen/tensorflow_osx/nccl_osx_1.3.4.tar.gz
Qiita の記事にある
以下の3つのソースコードの、align(sizeof(T))の文字列を削除する。
tensorflow/core/kernels/depthwise_conv_op_gpu.cu.cc
tensorflow/core/kernels/split_lib_gpu.cu.cc
tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc
を行う(正しくは、__align__(sizeof(T))
だった)。
bazel による実行、以下のように行うという指示があるが後述のように実行時エラーになる。
export CUDA_HOME=/usr/local/cuda
export DYLD_LIBRARY_PATH=/usr/local/cuda/lib:/usr/local/cuda/extras/CUPTI/lib
export LD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
export PATH=$DYLD_LIBRARY_PATH:$PATH
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
ERROR: /Users/shun/pworks/tensorflow/tensorflow/python/BUILD:1435:1: Executing genrule //tensorflow/python:control_flow_ops_pygenrule failed (Aborted): bash failed: error executing command /bin/bash bazel-out/host/genfiles/tensorflow/python/control_flow_ops_pygenrule.genrule_script.sh
dyld: Library not loaded: @rpath/libcudart.9.1.dylib
Referenced from: /private/var/tmp/_bazel_shun/8a2b32240072a9a79dbc7048c24218fa/execroot/org_tensorflow/bazel-out/host/bin/tensorflow/python/gen_control_flow_ops_py_wrappers_cc
Reason: image not found
dlopen で /usr/local/cuda/lib/libcudart.9.1.dylib
のオープンに失敗している。理由としては dylib が非標準の場所にあるのでそれを DYLD_LIBRARY_PATH で指定しているがこれがちゃんと渡っていない。
bazel 引数の --action_env
でこの環境変数を参照するように指示しているのだが、そもそも環境変数としてセットできていない(shell変数にはなる)。
bash-3.2$ export DYLD_LIBRARY_PATH=AAA
bash-3.2$ echo $DYLD_LIBRARY_PATH
AAA
bash-3.2$ env|grep DYLD_LIBRARY_PATH
bash-3.2$ cat A.sh
#!/bin/sh
echo $DYLD_LIBRARY_PATH
bash-3.2$ /bin/sh A.sh
bash-3.2$ exit
多分 SIP (System Integrity Protection) による問題で、無効化しないとどうにもならなそうである。
https://github.com/tensorflow/tensorflow/issues/6729#issuecomment-279483546
https://rcmdnk.com/blog/2015/10/10/computer-mac/
ただし今の問題は bazel による build 中の dlopen をどうにかすればよいので、
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/UsingDynamicLibraries.html にあるように ~/lib
ならば SIP 無効化不要のようでもある。
そこで $HOME/lib
に /usr/local/cuda/lib/libcudart.9.1.dylib
をコピーして作業を続けたがダメだった。
SIP を無効化して build
https://rcmdnk.com/blog/2015/10/10/computer-mac/#sipの無効化 に従って command-R を押しながら起動して、ユーティリティからターミナルを起動して、
csrutil disable
して再起動。
この条件で bazel で build すれば dlopen で失敗していた点は回避して先へ進むが
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://metakermit.com/2017/compiling-tensorflow-with-gpu-support-on-a-macbook-pro/ に従い
diff --git a/third_party/gpus/cuda/BUILD.tpl b/third_party/gpus/cuda/BUILD.tpl
index 2a37c65bc7..43446dd99b 100644
--- a/third_party/gpus/cuda/BUILD.tpl
+++ b/third_party/gpus/cuda/BUILD.tpl
@@ -110,7 +110,7 @@ cc_library(
".",
"cuda/include",
],
- linkopts = ["-lgomp"],
+ #linkopts = ["-lgomp"],
linkstatic = 1,
visibility = ["//visibility:public"],
)
のようにコメントアウトする。
ここまでの対処で
Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
bazel-bin/tensorflow/tools/pip_package/build_pip_package
INFO: Elapsed time: 7071.413s, Critical Path: 220.29s
INFO: Build completed successfully, 5588 total actions
の様に build を完走した。
インストールは以下の様に pip インストール用のパッケージを作成する。
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
Sat May 5 22:59:14 JST 2018 : === Using tmpdir: /var/folders/k2/crc7tsdx0yx1bgbrntyr67pw0000gn/T/tmp.XXXXXXXXXX.WILzRiUZ
~/pworks/tensorflow/bazel-bin/tensorflow/tools/pip_package/build_pip_package.runfiles ~/pworks/tensorflow
~/pworks/tensorflow
/var/folders/k2/crc7tsdx0yx1bgbrntyr67pw0000gn/T/tmp.XXXXXXXXXX.WILzRiUZ ~/pworks/tensorflow
Sat May 5 22:59:29 JST 2018 : === Building wheel
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: setup.py --help [cmd1 cmd2 ...]
or: setup.py --help-commands
or: setup.py cmd --help
error: invalid command 'bdist_wheel'
この様にエラーになるので
pip install --upgrade wheel
必須であった。
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
Sat May 5 23:01:41 JST 2018 : === Using tmpdir: /var/folders/k2/crc7tsdx0yx1bgbrntyr67pw0000gn/T/tmp.XXXXXXXXXX.cJJuECUm
~/pworks/tensorflow/bazel-bin/tensorflow/tools/pip_package/build_pip_package.runfiles ~/pworks/tensorflow
~/pworks/tensorflow
/var/folders/k2/crc7tsdx0yx1bgbrntyr67pw0000gn/T/tmp.XXXXXXXXXX.cJJuECUm ~/pworks/tensorflow
Sat May 5 23:01:55 JST 2018 : === Building wheel
warning: no files found matching '*.dll' under directory '*'
warning: no files found matching '*.lib' under directory '*'
warning: no files found matching '*' under directory 'tensorflow/aux-bin'
warning: no files found matching '*.h' under directory 'tensorflow/include/tensorflow'
warning: no files found matching '*' under directory 'tensorflow/include/Eigen'
warning: no files found matching '*' under directory 'tensorflow/include/external'
warning: no files found matching '*.h' under directory 'tensorflow/include/google'
warning: no files found matching '*' under directory 'tensorflow/include/third_party'
warning: no files found matching '*' under directory 'tensorflow/include/unsupported'
~/pworks/tensorflow
Sat May 5 23:02:22 JST 2018 : === Output wheel file is in: /tmp/tensorflow_pkg
この様にして作成したパッケージを
pip install /tmp/tensorflow_pkg/tensorflow-1.8.0-cp35-cp35m-macosx_10_13_x86_64.whl
でインストールする。
動作確認
python
Python 3.5.5 (default, Mar 29 2018, 16:22:58)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
2018-05-05 23:15:25.266979: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:859] OS X does not support NUMA - returning NUMA node zero
2018-05-05 23:15:25.267212: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1356] Found device 0 with properties:
name: GeForce GT 650M major: 3 minor: 0 memoryClockRate(GHz): 0.9
pciBusID: 0000:01:00.0
totalMemory: 1023.69MiB freeMemory: 683.31MiB
2018-05-05 23:15:25.267236: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1435] Adding visible gpu devices: 0
2018-05-05 23:15:25.608525: I tensorflow/core/common_runtime/gpu/gpu_device.cc:923] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-05-05 23:15:25.608554: I tensorflow/core/common_runtime/gpu/gpu_device.cc:929] 0
2018-05-05 23:15:25.608570: I tensorflow/core/common_runtime/gpu/gpu_device.cc:942] 0: N
2018-05-05 23:15:25.608715: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1053] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 421 MB memory) -> physical GPU (device: 0, name: GeForce GT 650M, pci bus id: 0000:01:00.0, compute capability: 3.0)
>>> print(sess.run(hello))
2018-05-05 23:15:35.846650: E tensorflow/core/grappler/clusters/utils.cc:127] Not found: TF GPU device with id 0 was not registered
b'Hello, TensorFlow!'
>>> ^D
何故か
tensorflow/core/grappler/clusters/utils.cc:127] Not found: TF GPU device with id 0 was not registered
とエラーになっているのだが print() はちゃんと動いている。
>>> import tensorflow as tf
>>> a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
>>> b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
>>> c = tf.matmul(a, b)
>>> sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
2018-05-05 23:42:04.506645: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:859] OS X does not support NUMA - returning NUMA node zero
2018-05-05 23:42:04.506881: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1356] Found device 0 with properties:
name: GeForce GT 650M major: 3 minor: 0 memoryClockRate(GHz): 0.9
pciBusID: 0000:01:00.0
totalMemory: 1023.69MiB freeMemory: 715.20MiB
2018-05-05 23:42:04.506903: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1435] Adding visible gpu devices: 0
2018-05-05 23:42:04.870686: I tensorflow/core/common_runtime/gpu/gpu_device.cc:923] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-05-05 23:42:04.870715: I tensorflow/core/common_runtime/gpu/gpu_device.cc:929] 0
2018-05-05 23:42:04.870723: I tensorflow/core/common_runtime/gpu/gpu_device.cc:942] 0: N
2018-05-05 23:42:04.870826: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1053] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 453 MB memory) -> physical GPU (device: 0, name: GeForce GT 650M, pci bus id: 0000:01:00.0, compute capability: 3.0)
Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: GeForce GT 650M, pci bus id: 0000:01:00.0, compute capability: 3.0
2018-05-05 23:42:04.881471: I tensorflow/core/common_runtime/direct_session.cc:284] Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: GeForce GT 650M, pci bus id: 0000:01:00.0, compute capability: 3.0
>>> print(sess.run(c))
MatMul: (MatMul): /job:localhost/replica:0/task:0/device:GPU:0
2018-05-05 23:43:01.452572: I tensorflow/core/common_runtime/placer.cc:886] MatMul: (MatMul)/job:localhost/replica:0/task:0/device:GPU:0
b: (Const): /job:localhost/replica:0/task:0/device:GPU:0
2018-05-05 23:43:01.452593: I tensorflow/core/common_runtime/placer.cc:886] b: (Const)/job:localhost/replica:0/task:0/device:GPU:0
a: (Const): /job:localhost/replica:0/task:0/device:GPU:0
2018-05-05 23:43:01.452605: I tensorflow/core/common_runtime/placer.cc:886] a: (Const)/job:localhost/replica:0/task:0/device:GPU:0
2018-05-05 23:43:01.452797: E tensorflow/core/grappler/clusters/utils.cc:127] Not found: TF GPU device with id 0 was not registered
[[22. 28.]
[49. 64.]]
ここまでやって、2年くらい前に書いた AUtoEncoder を食わせてみて、 TensorFlow が猛烈にメモリ食うことを思い出した。 MacBook でやるのは無謀そうなので、実際の実験は linux のサーバでやることにする。