どこをさらっても 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 に無いのかね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#!/bin/bash -eu bazel_version="0.14.1" tensorflow_version="1.8.0" script_path=$(cd "$(dirname $0)"; pwd) download_directory="$HOME/Downloads" install_prefix="/usr/local" required_buildtools="openjdk-8-jdk pkg-config zip g++ zlib1g-dev unzip" sudo apt install -y $required_buildtools if [ ! -e $download_directory ]; then mkdir -p $download_directory fi if [ ! -e /usr/bin/bazel ]; # TODO check bazel version then cd $download_directory if [ ! -e $download_directory/bazel_$bazel_version-linux-x86_64.deb ]; then wget https://github.com/bazelbuild/bazel/releases/download/$bazel_version/bazel_$bazel_version-linux-x86_64.deb fi sudo dpkg -i $download_directory/bazel_$bazel_version-linux-x86_64.deb fi if [ ! -e $install_prefix/lib/libtensorflow_cc.so.$tensorflow_version ]; then git clone --recursive --verbose --progress \ https://github.com/tensorflow/tensorflow $download_directory/tensorflow cd $download_directory/tensorflow bazel clean git checkout refs/tags/v$tensorflow_version ./configure extended_instruction_sets="--copt=-mavx --copt=-mavx2 --copt=-msse4.1 --copt=-msse4.2 --copt=-mfma" bazel build -c opt $extended_instruction_sets //tensorflow:libtensorflow_cc.so sudo install -m 0644 \ $download_directory/tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so \ $install_prefix/lib/libtensorflow_cc.so.$tensorflow_version cd $install_prefix/lib sudo ln -fs libtensorflow_cc.so.$tensorflow_version libtensorflow_cc.so sudo install -m 0644 \ $download_directory/tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so \ $install_prefix/lib/libtensorflow_framework.so.$tensorflow_version cd $install_prefix/lib sudo ln -fs libtensorflow_framework.so.$tensorflow_version libtensorflow_framework.so sudo ldconfig fi sudo mkdir -p $install_prefix/include copy="cp --parents --update --verbose" cd $download_directory/tensorflow/bazel-tensorflow find tensorflow -follow -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include find third_party -follow -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include/tensorflow find external -follow -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include/tensorflow cd $download_directory/tensorflow/bazel-genfiles find tensorflow -follow -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include find external -follow -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include/tensorflow # Eigenは拡張子をつけないスタイルのヘッダなので特別扱い cd $download_directory/tensorflow/bazel-tensorflow/third_party/eigen3 find Eigen -follow -type f | xargs --replace sudo $copy {} $install_prefix/include/tensorflow/third_party/eigen3 find unsupported -follow -type f | xargs --replace sudo $copy {} $install_prefix/include/tensorflow/third_party/eigen3 cd $download_directory/tensorflow/bazel-tensorflow/external/eigen_archive find Eigen -follow -type f | xargs --replace sudo $copy {} $install_prefix/include find unsupported -follow -type f | xargs --replace sudo $copy {} $install_prefix/include # パスが通ったディレクトリのトップレベルにいないといけないので特別扱い cd $download_directory/tensorflow/bazel-tensorflow/external/protobuf_archive/src find google -follow -type f -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include # cd $download_directory/tensorflow/bazel-tensorflow/external/nsync/public # find -follow -type f -name "*.h" | xargs --replace sudo $copy {} $install_prefix/include cd $script_path echo -e "\n\e[1;32minstallation completed\e[0m\n" |
共有ライブラリのインストール方法としては、いささか雑(例えばバージョンアップを考慮してシンボリックリンクになってないなど)なので気になる人は自分で修正して欲しい。
なお、アンインストールするには以下のファイル、ディレクトリ、シンボリックリンクを削除すれば良い。
/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() で吐かせて確認した限り、きちんとコピーできているようである。
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <algorithm> // std::copy() #include <vector> #include <tensorflow/core/framework/tensor.h> // tensorflow::Tensor std::vector<float> hoge {1, 2, 3, 4}; tensorflow::Tensor fuga { tensorflow::DT_FLOAT, tensorflow::TensorShape {2, 2} }; std::copy(std::begin(hoge), std::end(hoge), fuga.flat<float>().data()); |
擬似コードなのでメインもクソもないので注意。
tensorflow::Tensor::flat<T>() は 線形代数ライブラリ Eigen 形式のテンソルが返り、
Eigen::Tensor::data() によってその先頭アドレスを取得している。
API レファレンス上で全く同じ説明がなされている
tensorflow::Tensor::vec<T>() では次元数が合わないという旨のエラーを吐いて落ちた。
flat、vec の他にも tensor、matrix、scalar などのデータアクセス用のメンバがあるが、どうもこの辺りは Eigen の方の勉強が必要だろう。
とりあえず動くのでこの件に関しては保留。