ARMのSOCでTensorflowを動かす

2018/08/14

Tensorflowが公式にRaspberry Piでサポートされた

https://www.tensorflow.org/install/install_raspbian

のはいいけれど、この公式のものはRaspbianでしかそのままでは動作しない。

Raspberry Pi 3 model BボードにUbuntu mate https://ubuntu-mate.org/ をインストールして 動作させていたので、少し困る。というのもraspbianはUbuntu 14.04ベースであり、 mateは16.04ベースのため、pythonのバージョンが異なる(python3.4 vs. python 3.5)。

仕方ないのでソースからコンパイルをした。今現在のTensorflowのバージョンは1.9であるが、 githubからソースコードをチェックアウトすると、HEADのrevisionは1.10.0rc1となる。

https://www.tensorflow.org/install/install_raspbian の説明に従い、 x86_64のUbuntu 16.04LTSにてクロスコンパイルした。なお、ECCメモリのついたXeonでやる方が無難な模様。

説明にあるとおりのコマンドを実行すると、かなり時間がたってから、

tensorflow-1.10.0rc1-cp34-none-linux_armv7l.whl

というファイルができる。これをpipでインストールすればよい。 ただし、Ubuntu 16.04ではpython3のバージョンがpython3.5系のため、 別途Python 3.4.8をsourceコードからインストールして、

pip3.4 install tensorflow-1.10.0rc1-cp34-none-linux_armv7l.whl

でOKのはず。16.04ベースのためか、kerasもpip3.4でインストールができた。ただh5pyの部分で異常に時間がかかる。

Zybo-Z7 20 (Zynq-7000 XC7Z020)

このFPGA SoCでは、FPGA Regionを使いつつTensorflowも使うために、まずブートイメージとして https://qiita.com/ikwzm/items/7e90f0ca2165dbb9a577 にあるカーネルをSDカードにセットアップした。

シリアルコンソールでブートして、ethernetにTCP/IPの設定をしssh serverが起動するように設定すると、 普通のLinux鯖と同様に使うことができる。

まずは、Ubuntu mate用にコンパイルしたwheelファイルを持ってきてインストールしようとした。 このブートイメージはDebian 9ベースのため、Ubuntuとはパッケージ名が異なる。 また、python3のバージョンはpython3.5であり、そのままではうまくいかない。 結局、ソースからPython 3.4.9をインストールしようとしたら、 sslのパッケージが3.4.9の想定と異なっており、うまくいかない。 色々と試行錯誤した結果、パッケージのopensslは一切インストールせずに、 openssl-1.0.2(古い)をソースコードからインストールして、 python3.4.9のbuild時のオプションで必要なパスを指定する必要があった。 その上で、tensorflow-1.10.0rc1-cp34-none-linux_armv7l.whl がやっとインストールができた。

kerasから利用するため、kerasをpip3.4からインストールしようとすると、 h5py(HDF5ライブラリのラッパー)のパッケージでどうしてもこける。 まず、Debian 9公式のものはバージョンがあわず、名前も"_serial"というpostfixが追加されていて、 pipのkerasの想定とは異なっており、全然だめ。

結局、hdf5-1.8.4をソースからインストールした上で、まずはh5pyをソースからインストールし、 その上でkerasもソースからインストールすることで、ようやくkerasが動作した。

これでテストが出来ると思っていたら、先にインストールしたTensorflowの部分を実行すると、 illegal hardware instructionとでて動かない。調べたところ、Tensorflowのクロスコンパイルスクリプトは、 デフォルトでRaspberry Pi 3を想定しており、それ用に演算器の最適化オプションがついていた。 具体的にはgccのオプションとして”-mfpu=neon-vfpv4”が指定されていた

Zynq-7000へログインして/proc/cpuinfoを見てみると、vfpv4がサポートされていない(下記参照)。 これが怪しいので、スクリプトの該当部分、 具体的にはgithubからチェックアウトしたTensorflowのソースコード “tensorflow/tensorflow/tools/ci_build/pi/build_raspberry_pi.sh” 88行目の最後の部分を “-mfpu=neon"と変えた。これで一応NEON命令は使ってくれるはずなので、ひどくは遅くないはずである。 その上で、dockerを利用したクロスコンパイルをもう一度おこない、同じファイル名のwheelファイルができた。

先にインストールしたtensorflowをpip3.4でunistallしてから、新しいwheelファイルをinstallしたところ、 kerasからx86_64上でGPUを使って学習したモデルファイルを読み込んで、 Zynq-7000でもtensorflowによる画像分類の推論を実行できた。

2つのプラットフォームでの実行結果比較

Hardware : BCM2709 (Raspberry Pi 3 model B)

/proc/cpuinfo

processor       : 0
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part : 0xd03
CPU revision    : 4

Tensorflow実行結果(推論)

1/1 [==============================] - 0s 403ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 61ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 63ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 70ms/step
[[0. 1. 0.]]
1/1 [==============================] - 0s 62ms/step
[[0. 1. 0.]]
1/1 [==============================] - 0s 61ms/step
[[0. 1. 0.]]

Hardware : Xilinx Zynq Platform (Zybo Z7-20)

/proc/cpuinfo

processor : 0
model name  : ARMv7 Processor rev 0 (v7l)
BogoMIPS  : 666.66
Features  : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x3
CPU part  : 0xc09
CPU revision    : 0

Tensorflow実行結果(推論)

1/1 [==============================] - 1s 813ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 151ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 151ms/step
[[0. 0. 1.]]
1/1 [==============================] - 0s 156ms/step
[[0. 1. 0.]]
1/1 [==============================] - 0s 151ms/step
[[0. 1. 0.]]
1/1 [==============================] - 0s 150ms/step
[[0. 1. 0.]]