TensorFlow C++ (#1 インストール編)

どこをさらっても Python の記事しか出てこないからもう自分で書くことにした

前提として俺は宗教上の理由で Python を使わない。
普通は素直に Python で書いたほうが百万倍楽なはずである。


追記(2017/10/06):スクリプトの微調整
追記(2017/11/30):スクリプトの調整
追記(2018/06/18):最新バージョンをインストールするように更新

Google のビルドシステムに依存しないようにインストール

tensorflow のビルドには bazel なるビルドツールを用いるようだが、俺は CMake の方が使い慣れているのでそちらで使えるように tensorflow をインストールする。
具体的には、ソースから共有ライブラリオブジェクトをビルドして /usr/local/lib あたりにブチ込み、ヘッダファイル群を /usr/local/include にぶち込むという方針である。

最終的に出来上がった bash 用のインストールスプリクトが以下。
Ubuntu16.04 でしか動作確認していないので使おうとしている人は注意。

参考にしたのはこのサイト(tensorflowをソースからコンパイルしてインストールする | saito’s memo
基本的には上記サイトの内容をベースに、最新版をビルドするようにあれこれ変更しただけ。

追記(2017/10/06):
バージョンを 1.3.0 から 1.3.1 に変更。
コンパイル時に CPU 拡張命令を有効にするよう変更(ここは環境ごとに異なるが、インテルの CPU を使用しているなら、下記のままで大丈夫だと思われる)。

ヘッダファイル /usr/local/include/third_party を /usr/local/include/tensorflow 下に配置するように変更している(third_party という名前がいつか何かと衝突しそうだったのと、意味的にそこにあるべきだと思ったため)。
変更に伴い、コンパイル時に -l/usr/local/include/tensorflow の指定が必要になったので注意されたし。


追記(2017/11/30):
バージョンを 1.3.1 から 1.4.0 に変更。
CPU 拡張命令の部分を微調整。
幾つか新たにコピーが必要になったファイルがあったので追加。
恐らく漏れがまだあると思われる。

久しぶりに TensorFlow を触ったら 1.4.0 がリリースされてたので修正した。
なんだか Python API にしか無かったものが結構追加されてるようで、コアライブラリの部分にも以前は無かった(と思う)ディレクトリがある。
取り急ぎテストに使ってる MNIST のプログラムが通るようにしたが、多分、足りてない。
共有ライブラリが分割されたようで、 libtensorflow_cc.so の他に、新たに libtensorflow_framework.so をリンクする必要があるので注意されたし。

最後のファイルコピーの部分がどうも bazel の仕様がよくわからないため必要なものを無理矢理かき集めている感じなのが気に入らない。
もっと上手い書き方が分かる人が居たら教えて欲しい。


追記(2018/06/18):
バージョンを 1.4.0 から 1.8.0 に変更。ついでにbazelも最新バージョンに変更。
ヘッダファイルのコピー部分をいくらか整理。絶対に抜けがあるので中止されたし。
キモになるのは $download_directory/tensorflow/bazel-tensorflow/external ディレクトリに置かれているものをパスが通ったディレクトリに直接置くか否かの部分になると思う。
こういう、make install みたいなのって bazel に無いのかね。

共有ライブラリのインストール方法としては、いささか雑(例えばバージョンアップを考慮してシンボリックリンクになってないなど)なので気になる人は自分で修正して欲しい。

なお、アンインストールするには以下のファイル、ディレクトリ、シンボリックリンクを削除すれば良い。
/usr/local/lib/libtensorflow_cc.so (シンボリックリンクの解除)
/usr/local/lib/libtensorflow_framework.so (シンボリックリンクの解除)
/usr/local/include/tensorflow 、
/usr/local/include/google 、
/usr/local/include/Eigen (サードパーティライブラリだが今回突っ込んだもののひとつ)
/usr/local/include/unsupported (Eigen のモジュールのひとつ)

調査:STL アルゴリズムの適用

C++ というと、STL アルゴリズム(STL という名前で呼ぶのは間違いだが、こちらの方が通りが良いので)が大きな魅力のひとつではあるが、TensorFlow がどの程度対応しているのかが良くわからなかった。
すべてが TensorFlow API で完結するなら考える必要はないが、実際そんなことはありえないから、 std::vector なりの標準コンテナに値を移したり、移されたりすることもあろう。

結論から言うと、出来た。
確か StackOverflow で見つけたコードだった気がする。
tensorflow::Tensor::DebugString() で吐かせて確認した限り、きちんとコピーできているようである。

擬似コードなのでメインもクソもないので注意。
tensorflow::Tensor::flat<T>() は 線形代数ライブラリ Eigen 形式のテンソルが返り、 Eigen::Tensor::data() によってその先頭アドレスを取得している。

API レファレンス上で全く同じ説明がなされている tensorflow::Tensor::vec<T>() では次元数が合わないという旨のエラーを吐いて落ちた。
flat、vec の他にも tensor、matrix、scalar などのデータアクセス用のメンバがあるが、どうもこの辺りは Eigen の方の勉強が必要だろう。

とりあえず動くのでこの件に関しては保留。