TensorFlowは公式でWindowsに対応しているが、C++のAPIはLinuxとMacでしかサポートされていない。
https://www.tensorflow.org/install/install_c
dllをダウンロードして、defを作成してリンクする方法もあるようだが、CPUでしか使えない。
visual studioでtensorflow - Qiita
WindowsでGPUを有効にしてC++からTensorFlowを使うには、自分でビルドする必要がある。
ビルドは以前の日記に書いたCMakeを使う方法でできる。
最新版に対応した手順は、ここを参照する。
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/cmake/README.md
以下に手順を示す。
ビルド
TensorFlowのソースダウンロード
GitHubからTensorFlow 1.5のソースをダウンロードして展開する。
Releases · tensorflow/tensorflow · GitHub
以下、「C:\tensorflow-1.5.0」に展開したものとして記述する。
cmakeコマンドでビルドファイル作成
以下のコマンドを実行する。
cmake .. -A x64 -DCMAKE_BUILD_TYPE=Release ^ -DSWIG_EXECUTABLE=C:\swigwin-3.0.10\swig.exe ^ -Dtensorflow_BUILD_PYTHON_BINDINGS=OFF ^ -Dtensorflow_ENABLE_GRPC_SUPPORT=OFF ^ -Dtensorflow_ENABLE_GPU=ON ^ -DCUDNN_HOME="%CUDA_PATH%" ^ -Dtensorflow_WIN_CPU_SIMD_OPTIONS=/arch:AVX
オプションに「-Dtensorflow_ENABLE_GPU=ON」を指定することでGPUが有効になる。
AVX命令を有効にしている。
Pythonバインディングは無効にしている。
ビルド
以下のコマンドを実行する。
MSBuild /p:Configuration=Release ALL_BUILD.vcxproj
ビルドにはCore i7 4コア 4GHzのPCで、3時間かかった。
C++で使う際のプロジェクトの設定
Building a standalone C++ Tensorflow program on Windows – Joe Antognini
こちらのページのサンプルプログラムをコンパイルするための設定を示す。
GPUを有効にする場合は、上記のページの手順では不足するため、以下に設定内容を示す。
Release/x64の構成に対して行う。(TensorFlowをデバッグビルドしていない場合、Debug/x64も同じでよい。)
インクルードディレクトリ設定
以下のパスをインクルードディレクトリに追加する。
C:\tensorflow-1.5.0 C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\eigen_archive C:\tensorflow-1.5.0\third_party\eigen3 C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\protobuf\src\protobuf\src C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\nsync\src\nsync\public
ライブラリディレクトリ設定
以下のパスをライブラリディレクトリに追加する。
C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\protobuf\src\protobuf\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_ops.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_framework.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_cpu.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_direct_session.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_framework.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_kernels.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_lib.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_ops.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\nsync\src\nsync\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\snappy\src\snappy\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\sqlite\src\sqlite-build\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_while_loop.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_stream_executor.dir\Release C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64
最後の2行がGPUを有効するために必要。
リンクするライブラリ設定
リンクの入力に以下のライブラリを追加する。
zlib\install\lib\zlibstatic.lib gif\install\lib\giflib.lib png\install\lib\libpng12_static.lib jpeg\install\lib\libjpeg.lib lmdb\install\lib\lmdb.lib jsoncpp\src\jsoncpp\src\lib_json\Release\jsoncpp.lib farmhash\install\lib\farmhash.lib fft2d\src\lib\fft2d.lib highwayhash\install\lib\highwayhash.lib libprotobuf.lib tf_protos_cc.lib tf_cc.lib tf_cc_ops.lib tf_cc_framework.lib tf_core_cpu.lib tf_core_direct_session.lib tf_core_framework.lib tf_core_kernels.lib tf_core_lib.lib tf_core_ops.lib nsync.lib snappy.lib sqlite.lib tf_cc_while_loop.lib tf_core_gpu_kernels.lib tf_stream_executor.lib cuda.lib cudart.lib cusolver.lib cublas.lib curand.lib cufft.lib cudnn.lib
tf_core_gpu_kernels.lib以降の行がGPUを有効にするために必要。
なお、必要なライブラリは、ビルドしてリンカのエラーを表示して、
dumpbin /symbols C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_contrib_rnn_lstm_ops.dir\Release\tf_contrib_rnn_lstm_ops.lib | grep perftools::gputools::Stream::Stream
のようにして、すべての.libに対してdumpbinコマンドを実行してシンボルが含まれるライブラリを調べた。
リンカのオプション設定
リンカの追加オプションに以下を追加する。
/WHOLEARCHIVE:tf_cc.lib /WHOLEARCHIVE:tf_cc_framework.lib /WHOLEARCHIVE:tf_cc_ops.lib /WHOLEARCHIVE:tf_core_cpu.lib /WHOLEARCHIVE:tf_core_direct_session.lib /WHOLEARCHIVE:tf_core_framework.lib /WHOLEARCHIVE:tf_core_kernels.lib /WHOLEARCHIVE:tf_core_lib.lib /WHOLEARCHIVE:tf_core_ops.lib /WHOLEARCHIVE:tf_stream_executor.lib /WHOLEARCHIVE:libjpeg.lib
サンプルプログラムのビルドと実行
ビルド
プロジェクトの構成をRelease/x64にしてビルドする。
ランタイムライブラリは、デフォルトの「マルチスレッドDLL(/MD)」とする。
実行
成功すると、以下のように表示される。
2018-02-26 23:47:33.024224: I C:\tensorflow-1.5.0\tensorflow\core\platform\cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 2018-02-26 23:47:33.610718: I C:\tensorflow-1.5.0\tensorflow\core\common_runtime\gpu\gpu_device.cc:1105] Found device 0 with properties: name: GeForce GTX 1080 major: 6 minor: 1 memoryClockRate(GHz): 1.8225 pciBusID: 0000:01:00.0 totalMemory: 8.00GiB freeMemory: 6.61GiB 2018-02-26 23:47:33.615178: I C:\tensorflow-1.5.0\tensorflow\core\common_runtime\gpu\gpu_device.cc:1195] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: GeForce GTX 1080, pci bus id: 0000:01:00.0, compute capability: 6.1) 7 17 -1 -3
PCを起動後の初回は時間がかかるが、2回目からはすぐに結果が表示される。
2018/2/27 追記
GPUを使うサンプルになっていなかったので、TensorFlowのソースに含まれるexample_trainer.ccをビルドした。
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/cc/tutorials/example_trainer.cc
プロジェクトの設定はcmakeで生成したtf_tutorials_example_trainerのプロジェクトとできるだけ合わせた。
インクルードディレクトリ
C:\tensorflow-1.5.0 C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\zlib_archive C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\gif_archive\giflib-5.1.4 C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\png_archive C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\jpeg_archive C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\lmdb C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\eigen_archive C:\tensorflow-1.5.0\third_party\eigen3 C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\gemmlowp\src\gemmlowp C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\jsoncpp\src\jsoncpp C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\farmhash_archive C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\farmhash_archive\util C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\highwayhash C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\cub\src\cub C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\nsync\public C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\protobuf\src\protobuf\src C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\re2\install\include C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\external\sqlite C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\snappy\src\snappy
ライブラリディレクトリ
C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_ops.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_framework.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_cpu.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_direct_session.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_framework.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_kernels.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_lib.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_core_ops.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_cc_while_loop.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\tf_stream_executor.dir\Release C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build C:\tensorflow-1.5.0\tensorflow\contrib\cmake\build\Release C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64
プリプロセッサ
以下のマクロ定義を追加
_ITERATOR_DEBUG_LEVEL=0 EIGEN_AVOID_STL_ARRAY NOMINMAX _WIN32_WINNT=0x0A00 LANG_CXX11 COMPILER_MSVC OS_WIN WIN64 WIN32_LEAN_AND_MEAN NOGDI PLATFORM_WINDOWS TENSORFLOW_USE_EIGEN_THREADPOOL EIGEN_HAS_C99_MATH TF_COMPILE_LIBRARY TF_USE_SNAPPY GOOGLE_CUDA=1
ライブラリの入力設定
tf_protos_cc.lib tf_core_gpu_kernels.lib tf_core_cpu.lib tf_stream_executor.lib tf_core_direct_session.lib tf_core_kernels.lib tf_core_ops.lib tf_cc_ops.lib tf_core_framework.lib tf_core_lib.lib tf_cc_framework.lib tf_cc_while_loop.lib zlib\install\lib\zlibstatic.lib gif\install\lib\giflib.lib png\install\lib\libpng12_static.lib jpeg\install\lib\libjpeg.lib lmdb\install\lib\lmdb.lib jsoncpp\src\jsoncpp\src\lib_json\Release\jsoncpp.lib farmhash\install\lib\farmhash.lib fft2d\src\lib\fft2d.lib highwayhash\install\lib\highwayhash.lib nsync\install\lib\nsync.lib protobuf\src\protobuf\Release\libprotobuf.lib re2\src\re2\Release\re2.lib sqlite\install\lib\sqlite.lib snappy\src\snappy\Release\snappy.lib cuda.lib cudart.lib cusolver.lib cublas.lib curand.lib cufft.lib cudnn.lib cuda.lib cudart.lib cusolver.lib cublas.lib curand.lib cufft.lib cudnn.lib
リンカの追加オプション
/machine:x64 /ignore:4049 /ignore:4197 /ignore:4217 /ignore:4221 /WHOLEARCHIVE:tf_cc.lib /WHOLEARCHIVE:tf_cc_framework.lib /WHOLEARCHIVE:tf_cc_ops.lib /WHOLEARCHIVE:tf_core_cpu.lib /WHOLEARCHIVE:tf_core_direct_session.lib /WHOLEARCHIVE:tf_core_framework.lib /WHOLEARCHIVE:tf_core_kernels.lib /WHOLEARCHIVE:tf_core_lib.lib /WHOLEARCHIVE:tf_core_ops.lib /WHOLEARCHIVE:tf_stream_executor.lib