はじめに
前回のOpenCAE勉強会@関西で話したネタです。
OpenFOAMの実行ファイルの中でTensorFlowをincludeする際の手順や注意事項などをまとめます。
(前の記事の清書を兼ねています。)
例としてcheckMeshの実行ファイルの中でTensorFlowのチュートリアルの一つであるlabel_imageというものを実行してみました。
※画像認識をする意味は特にないです。
コンパイル手順
○ OpenFOAMの環境
OpenFOAMはすでにインストールされているものとする。
- Ubuntu16.04LTS
- OpenFOAM-v1712(コンパイラ:gcc)
- 場所:$HOME/OpenFOAM/
TensorFlowも同様に$HOME/OpenFOAM/にインストールする。
① Bazelをインストール(詳しくはこちら)
以下の手順でTensorFlowこビルドするためにBazelをインストールする。
$ sudo apt-get install openjdk-8-jdk
$ echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
$ curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
$ sudo apt-get update && sudo apt-get install bazel
② TensorFlowをソースからビルド
この際にc++用のsoを作成するためには以下のようなコマンドを入力する。
$ git clone tensorflow/tensorflow
$ cd tensorflow
$ ./configure
$ bazel build -c opt --copt=-march=native tensorflow:libtensorflow_cc.so
この./configureの時にPythonの場所やcudaを設定するかどうかを聞かれる。
③ ヘッダファイルをコピーして収集
includeするTensorFlowのヘッダファイルを取ってくる。
Tensorflowをc++のcmakeしてるプロジェクトで使いたいの中のスクリプトをほぼそのまま使用した。
今回のチュートリアルでは以下のようなスクリプトを実行して動作を確認した。
# !/bin/bash
HEADER_DIR=$HOME/OpenFOAM/tensorflow/lnInclude ※各自のtensorflowインストール場所
if [ ! -e $HEADER_DIR ];
then
mkdir -p $HEADER_DIR
fi
cd tensorflow
find tensorflow/core -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find tensorflow/cc -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find tensorflow/c -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find bazel-genfiles -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find bazel-tensorflow -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find third_party/eigen3 -follow -type f -exec cp --parents {} $HEADER_DIR \;
pushd bazel-genfiles
find tensorflow -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
popd
pushd bazel-tensorflow/external/protobuf_archive/src
find google -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
popd
pushd bazel-tensorflow/external/eigen_archive
find Eigen -follow -type f -exec cp --parents {} $HEADER_DIR \;
find unsupported -follow -type f -exec cp --parents {} $HEADER_DIR \;
popd
pushd ~/.cache/bazel/ユーザー名/謎の文字列/external
find eigen_archive -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
find protobuf_archive -follow -type f -name "*.h" -exec cp --parents {} $HEADER_DIR \;
popd
※最後の ユーザー名 と 謎の文字列 はbazelでtensorflowをインストールした時に生成されるディレクトリ
tensorflow/bazel-binのリンク先から確認できる。
今回使用したスクリプトファイルはこれだが、謎の文字列の部分は変更する必要がある。
④ soのパスを通す
実行するためには毎回 LD_LIBRARY_PATH に tensorflow_cc.so の場所を追加する必要がある。
今回は $(HOME)/OpenFOAM/OpenFOAM-v1712/etc/bashrc に以下のコマンドを追加した。
$ export LD_LIBRARY_PATH="$(HOME)/OpenFOAM/tensorflow/bazel-bin/tensorflow:$LD_LIBRARY_PATH"
⑤ wmakeの設定変更
デフォルトのままでもコンパイルは通るが、コーディングルールの違いからコンパイル時に多くのエラーメッセージが出てくる。
これを解消するためにOpenFOAM側のwmakeのオプションを変更する。
今回はここに
$HOME/OpenFOAM/OpenFOAM-v1712/wmake/rules/linux64Gcc/c++
以下のように変更を加えた。
SUFFIXES += .C .cc .cpp .cxx
- c++WARN = -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter \
- -Wno-invalid-offsetof -Wno-attributes
+ c++WARN = -Wall -Wextra -Wnon-virtual-dtor -Wno-unused-parameter \
+ -Wno-invalid-offsetof -Wno-attributes -Wno-sign-compare
# Suppress some warnings for flex++ and CGAL
c++LESSWARN = -Wno-old-style-cast -Wno-unused-local-typedefs -Wno-array-bounds
CC = g++ -std=c++11 -m64
include $(DEFAULT_RULES)/c++$(WM_COMPILE_OPTION)
ptFLAGS = -DNoRepository -ftemplate-depth-100
c++FLAGS = $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS) -fPIC
Ctoo = $(WM_SCHEDULER) $(CC) $(c++FLAGS) -c $< -o $@
cxxtoo = $(Ctoo)
cctoo = $(Ctoo)
cpptoo = $(Ctoo)
LINK_LIBS = $(c++DBUG)
LINKLIBSO = $(CC) $(c++FLAGS) -shared -Xlinker --add-needed -Xlinker --no-as-needed
LINKEXE = $(CC) $(c++FLAGS) -Xlinker --add-needed -Xlinker --no-as-needed
⑥ ユーティリティのコンパイル
今回のテストに使用するユーティリティはcheckMeshしてから画像を認識するというもの。
GitHub/inabowerの中のossanCheckMeshがこれに該当する。
例えば以下のようなコマンドでコンパイルできる。
$ git clone https://github.com/inabower/solvers-v1712.git
$ cd solvers-v1712/utilities/ossanCheckMesh
$ wmake
実行してみる
テストケース
ケース自体は普通のpitzDaily。
Allrunファイルの中身は以下のようになっている。
# !/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/bin/tools/RunFunctions # Tutorial run functions
runApplication blockMesh
curl -L "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz" | tar -C ./data -xz
runApplication ossanCheckMesh
# runApplication $(getApplication)
# ------------------------------------------------------------------------------
最初のcurlでgoogleの学習データをダウンロードする。
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 84.5M 100 84.5M 0 0 9849k 0 0:00:08 0:00:08 --:--:-- 11.1M
またdataディレクトリに今回テストに使用する男性の顔写真が入っておりこれを認識することになる。

実行結果
以下のような結果が出力される。
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1712 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : v1712
Arch : "LSB;label=32;scalar=64"
Exec : ossanCheckMesh
Date : Jan 24 2018
Time : 19:14:10
(中略)
Checking geometry...
Overall domain bounding box (-0.0206 -0.0254 -0.0005) (0.29 0.0254 0.0005)
Mesh has 2 geometric (non-empty/wedge) directions (1 1 0)
Mesh has 2 solution (non-empty) directions (1 1 0)
All edges aligned with or perpendicular to non-empty directions.
Boundary openness (-1.74458e-19 3.10465e-18 2.11178e-15) OK.
Max cell openness = 2.21044e-16 OK.
Max aspect ratio = 8.1407 OK.
Minimum face area = 1.68589e-07. Maximum face area = 5.14451e-06. Face area magnitudes OK.
Min volume = 1.6902e-10. Max volume = 3.83579e-09. Total volume = 1.4516e-05. Cell volumes OK.
Mesh non-orthogonality Max: 5.95045 average: 1.63034
Non-orthogonality check OK.
Face pyramids OK.
Max skewness = 0.260575 OK.
Coupled point location match (average 0) OK.
Mesh OK... but...
Checking image...
> Image : $HOME/OpenFOAM/test/ossanTest/data/grace_hopper.jpg
> Graph : $HOME/OpenFOAM/test/ossanTest/data/inception_v3_2016_08_28_frozen.pb
83.43% : military uniform.
2.19% : mortarboard.
1.04% : academic gown.
0.80% : pickelhaube.
0.54% : bulletproof vest.
This might be "military uniform" !!
End
無事に画像認識もできた。
注意点
先にTensorFlowをincludeする
OpenFOAMの中には TypeName というマクロがあり、TensorFlowには TypeName という関数がある。
このためOpenFOAMのヘッダを読んだあとにTensorFlowのヘッダを読むと関数として出てきた「TypeName」という文字列をマクロだと認識してしまいコンパイルエラーにつながってしまう。
ユーティリティやソルバーであれば一番最初に、境界条件などのsoであればそれの一番最初にincludeする必要がある。
namespaceに注意
例えばTensorなどの型がOpenFOAMと重複しているため using namespace が使いづらい。
未確認事項
- mpirun
- 数字や文字列や行列の受け渡し
- C++でやる意味
最後に
内容はGitHub(https://github.com/inabower/solvers-v1712)にあげてあります。
コメントやプルリクをお待ちしています。