TensorFlow C++ライブラリのWindows環境におけるビルド

 Windowsで汎用的なディープラーニング系のC++ライブラリを選ぼうとすると、導入の簡単さではPyTorchが上だが、一応TensorFlowのC++ライブラリの導入にもなれておかないとなぁということでやってみた。多分使わないと思うが。
 下記内容は基本的な流れだけであって、読者の要求に適合するとは限らない上に、ビルド中に書いているのでかなり無責任である事は述べておこう。

  • 依存関係:Windows 10/11、TensorFlow 2.11、CUDA SDK 11.2、cuDNN 8.1、python 3.7、MSYS2、Visual Studio 2019、Bazel5.3
  • 基本的な流れはここを参照pythonパッケージのビルドとインストールは無視している
  • CUDA SDKとcuDNNをインストール。cuDNNはCUDA SDKインストールディレクトリ内に統合(コピペ)
  • Bazelのバイナリをダウンロードし、下記環境変数PATHに登録する予定のディレクトリにコピー
    • 今回はtensorflow2.11が指定するバージョンである5.3を使用
  • Visual Studio 2019をインストール(2019用ビルドツールと再頒布可能パッケージにチェック)
  • pythonをインストールし、pythonで必要なパッケージをインストール
    • tensorflowのpythonパッケージのビルドを行わない場合、依存パッケージはいらないかもしれないが、python自体は無いとbazelでのビルド時にエラーが出る
    • bazelがなにをやっているのかわからないので入れておくのが無難
pip install -U six numpy wheel packaging
pip install -U keras_preprocessing --no-deps
  • MSYS2をインストールし、以下の手続きを実行
#ロングパス対策
fsutil 8dot3name set 0

#必要なパッケージをインストール
pacman -S git patch unzip
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout r2.11
./configure
#configureでは設定のためにいくつか質問をされるが、デフォルトで良いだろう。mROCを有効にするとCUDAが使えなくなるらしいので注意
# .bazelrcに以下の記述を追加。ロングパスを解決するためのものらしい。
startup --output_user_root=C:/tmp
startup --windows_enable_symlinks
build --enable_runfiles
#bazelコマンドに渡す引数とMSYSターミナルのパス解釈の問題を回避するために下記のコマンドを実行
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL="*"
#PATHを設定し、bazelとpythonを実行できるようにする
#URIの区切り文字の書き方がWindowsユーザーには独特だが、まぁ分かるだろう
export PATH="/c/dev/bin:$PATH"
export PATH="/c/Program Files/WindowsApps/PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0:$PATH"
#GPUサポートのためにCUDAとcuDNNのパスを通す
#当たり前だがtensorflowのバージョンに適合するCUDA SDKとcuDNNをインストールしておく必要がある。cuDNNのbin等はv11.2/bin以下にコピー済みという前提
export PATH="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.2/bin:$PATH"
export PATH="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.2/extras/CUPTI/libx64:$PATH"
#Visual Studio 2019ビルドツールが存在するディレクトリへのパスを通す
#他にもVC関連の環境変数設定があるが省略可能([https://bazel.build/configure/windows#build-c:title])
export BAZEL_VC="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC"
#ビルドとインクルードファイルのインストール
#DLL等のみをビルドするオプション等があるらしい
bazel build tensorflow:tensorflow_cc.dll
bazel build tensorflow:install_headers

 ビルドが正常に開始されるとCPUコアをフルに使ったビルドが始まり、OSの動きもカクカクに。
 しかし、やはりGoogleのドキュメントは行間を読みまくらないと使い物にならない作りだ。
 まだビルドに成功していないが、下に失敗例を記載しておく。

  • 失敗例
    • 大量の未解決のシンボルが出てビルド失敗。./configureしてなかったり、ロングパス問題を解決していない場合に起きるとか起きないとか
tensorflow_cc.dll.if.exp : error LNK2001: 外部シンボル "public: class std::unique_ptr<class tensorflow::data::DatasetBase,struct tsl::core::RefCountDeleter> && __cdecl tsl::StatusOr<class std::unique_ptr<class tensorflow::data::DatasetBase,struct tsl::core::RefCountDeleter> >::value(void)&& " (?value@?$StatusOr@V?$unique_ptr@VDatasetBase@data@tensorflow@@URefCountDeleter@core@tsl@@@std@@@tsl@@QEHAA$$QEAV?$unique_ptr@VDatasetBase@data@tensorflow@@URefCountDeleter@core@tsl@@@std@@XZ) は未解決です
tensorflow_cc.dll.if.exp : error LNK2001: 外部シンボル "public: class google::protobuf::RepeatedPtrField<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > const & __cdecl tensorflow::BytesList::value(void)const " (?value@BytesList@tensorflow@@QEBAAEBV?$RepeatedPtrField@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@protobuf@google@@XZ) は未解決です
tensorflow_cc.dll.if.exp : error LNK2001: 外部シンボル "public: class google::protobuf::RepeatedField<__int64> const & __cdecl tensorflow::Int64List::value(void)const " (?value@Int64List@tensorflow@@QEBAAEBV?$RepeatedField@_J@protobuf@google@@XZ) は未解決です
tensorflow_cc.dll.if.exp : error LNK2001: 外部シンボル "public: virtual class std::basic_string_view<char,struct std::char_traits<char> > __cdecl tsl::table::Block::Iter::value(void)const " (?value@Iter@Block@table@tsl@@UEBA?AV?$basic_string_view@DU?$char_traits@D@std@@@std@@XZ) は未解決です
tensorflow_cc.dll.if.exp : error LNK2001: 外部シンボル "public: class google::protobuf::RepeatedPtrField<class tensorflow::VariantTensorDataProto> const & __cdecl tensorflow::TensorProto::variant_val(void)const " (?variant_val@TensorProto@tensorflow@@QEBAAEBV?$RepeatedPtrField@VVariantTensorDataProto@tensorflow@@@protobuf@google@@XZ) は未解決です
bazel-out\x64_windows-opt\bin\tensorflow\tensorflow_cc.dll : fatal error LNK1120: 11907 件の未解決の外部参照

 色々修正しつつビルドを数回試みたが、DLLをリンクする段階で失敗する。
 MSYSではビルドが失敗するのでVS2019 Developer Command Promptからビルドを試みるとWSL2でビルドしないとCUDAを有効にしてやらないと言われる。
 いやーほんと、面倒なヤツ。とにかくWindowsに合わせるつもりは無いらしい。
 C言語用ライブラリのC++ラッパーはいくつか有るので、このあたりとPythonを組み合わせるのがWindowsでは最適か。
 C++のみで行うならPyTorch一択になるだろう。
 用途を限定するならDlibなどもある。これは画像認識用途で開発された経緯のせいか、リカレントニューラルネットワークインターフェイスが用意されていないものの、基本的なものから高度な分類や近似を行えるモデルが簡単に使えるようになっていて良い。コア機能を流用すればリカレントも実装できるとのことだが、あまり使いやすいとは言えないらしい。NLPライブラリであるMITIEがDlibのコア機能を利用して作られていたりする。
 しかしPyTorchのC++チームにはもっと頑張ってほしい。Python版Torchの記述に合わせることに拘るあまり、ドキュメントやチュートリアルで其のことばかりに言及している。C++はそれ自体に良い記述方法が有るので、Pythonしか使わない人たちに合わせる必要はない。