go-tfliteをWindows 10 Home PCにCoral EdgeTPUを付けて実行する

8 min read読了の目安(約7400字

mattn/go-tfliteはTensorFlow LiteのGO言語バインディングです。ここでは、Windows 10 HomeがインストールされたPCでlibtensorflowlite_c.dllをビルドし、Coral EdgeTPUのUSBドライバをインストールして、go-tfliteリポジトリ内にある例を実行するところまでの手順を紹介します。Windows 10のHomeということを強調している点ですが、Homeはパスの扱える長さが短いので、TensorFlowのビルドを失敗しがちだからです。

前提としている環境は次の通りです。他にもg++が使えるとかありますが、そのあたりは適当にpacmanで入れているものとします。

  • go: 1.15.3
  • msys2がインストールされている
  • gitがインストールされている
  • go-tfliteは現在の最新版を使用します(commit: 11e8959f01a963f78316c6f2d9d15e16c3ab25e9)

tensorflowliteライブラリのビルド

MSYS2でビルドする場合、byteswap.hが無いので、ここからインストールしてmsys64\mingw64\includeに入れておきます。

次にtensorflowのソースコードを取得します。OSがHomeの場合、GOPATHの下にtensorライブラリのビルドに失敗するので、ホームディレクトリ直下に置きます。ユーザー名がdogならばC:\Users\dog\tensorflowに置くということです。ライブラリのビルドに成功するために、ユーザー名が何文字まで取れるか分かりませんが、実際に使用したユーザー名は3文字でした。

edgetpuに対応しているバージョンがあるので、そのコミットをチェックアウトします。このコミット番号はここTENSORFLOW_COMMITのものを使用しています。よくは分からないですが、どうやらこのコミットを使用してそうだなということは予想出来ると思います。

tensorflowのソースコードをチェックアウト
$cd /c/Users/dog
$git clone https://github.com/tensorflow/tensorflow
$cd tensorflow
$git checkout -b coral d855adfc5a0195788bf5f92c3c7352e638aa1109

ソースコードのチェックアウトが済んだので、libtensorflow-lite.aをビルドします。makeを実行する前に、依存する外部のコードをダウンロードします。ダウンロードスクリプトは用意されているのですが、flatbuffersのdocsにシンボリックリンクがあって、MSYS2だと解凍に失敗します。docsはビルドとは関係無いはずなので、--excludeオプションで回避します。

/tensorflow/lite/tools/make/download_dependencies.sh
@@ -75,7 +75,7 @@ download_and_extract() {
     sha256sum -c "${filepath}.sha256"
   fi
   if [[ "${url}" == *gz ]]; then
-    tar -C "${dir}" --strip-components=1 -xzf ${filepath}
+    tar -C "${dir}" --strip-components=1 --exclude docs -xzf  ${filepath}
   elif [[ "${url}" == *zip ]]; then
     tempdir2=$(mktemp -d)
     unzip ${filepath} -d ${tempdir2}

修正が終わったら、スクリプトを実行します。

$ ./tensorflow/lite/tools/make/download_dependencies.sh

Makefileにも決定的なバグがあり、これも修正します。ここを修正しなくてもビルドは正常に終わりますが、libtensorflowlite_c.dllのビルドのときに失敗します。あとall: $(LIB_PATH)に変更しているのは、それ以降のものは使用しないのと、最後まで実行しようとしてもパスの長さが足りなくてエラーで終了するからです(失敗してもlibtensorflow-lite.aのビルドには影響しません)。

/tensorflow/lite/tools/make/Makefile
@@ -110,6 +110,7 @@ $(wildcard tensorflow/lite/kernels/*.cc) \
 $(wildcard tensorflow/lite/kernels/internal/*.cc) \
 $(wildcard tensorflow/lite/kernels/internal/optimized/*.cc) \
 $(wildcard tensorflow/lite/kernels/internal/reference/*.cc) \
+$(wildcard tensorflow/lite/tools/optimize/sparsity/*.cc) \
 $(PROFILER_SRCS) \
 tensorflow/lite/tools/make/downloads/farmhash/src/farmhash.cc \
 tensorflow/lite/tools/make/downloads/fft2d/fftsg.c \
@@ -266,7 +267,7 @@ $(OBJDIR)%.o: %.cpp
        $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@

 # The target that's compiled if there's no command-line arguments.
-all: $(LIB_PATH)  $(MINIMAL_BINARY) $(BENCHMARK_BINARY) $(BENCHMARK_PERF_OPTIONS_BINARY)
+all: $(LIB_PATH)

 # The target that's compiled for micro-controllers
 micro: $(LIB_PATH)

修正が終わったので、libtensorflow-lite.aをビルドします。

$ ./tensorflow/lite/tools/make/build_lib.sh

このビルドにはある程度、時間がかかります。ビルドが終わるとtensorflow/lite/tools/make/gen/<arch>/lib/libtensorflow-lite.aが生成されています(<arch>はOSとアーキテクチャに依存して変わります。windows_x86_64とかosx_x86_64とかになります)。

libtensorflow-lite.aが出来たので、libtensorflowlite_c.dllをビルドします。go-tfliteにMakefile(ファイル名はMakefile.tflite)が用意してあるので、それをtensorflow/lite/cにコピーします。go-tfliteのMakefileはGOPATH以下にtensorflowをインストールしている前提があるので、TENSORFLOW_ROOTだけ直します。特に他の人に使ってもらう目的も無いので、ベタ書きしてしまいます。

github.com/mattn/go-tflite/Makefile.tflite
@@ -4,7 +4,7 @@
 
 OBJS = $(subst .cc,.o,$(subst .cxx,.o,$(subst .cpp,.o,$(SRCS))))
 
-TENSORFLOW_ROOT = $(shell go env GOPATH)/src/github.com/tensorflow/tensorflow
+TENSORFLOW_ROOT = /c/Users/dog/tensorflow
 CXXFLAGS = -DTF_COMPILE_LIBRARY -I$(TENSORFLOW_ROOT) \
 	-I$(TENSORFLOW_ROOT)/tensorflow/lite/tools/make/downloads/flatbuffers/include \
 	-I$(TENSORFLOW_ROOT)/tensorflow/lite/tools/make/downloads/absl

修正が終わったら、次のコマンドを実行しビルドします。ビルドにはそれほど時間はかからないでしょう。

$ cd ./tensorflow/lite/c
$ make -f Makefile.tflite

ビルドが終わるとtensorflow/lite/clibtensorflowlite_c.dllが出来ています。ここまでで、libtensorflowlite_c.dllを適当な場所に置き、go言語から見えるように設定すれば、TPUアクセラレータ無しの実行ならすぐにでも出来る状態です。ここではgo-tfliteをCPUで試す前にTPUを設定しておきます。

Edge TPU の設定

Edge TPUアクセラレータのUSBドライバとライブラリをここからダウンロードします(ダウンロードページはここからとべます)。解凍した中にあるinstall.batをダブルクリックするとインストールが始まりますが、その前に次のような修正を加えます。

install.bat
@@ -45,7 +45,7 @@
 lodctr /M:"%ROOTDIR%\third_party\coral_accelerator_windows\coral.man"
 
 echo Copying edgetpu and libusb to System32
-copy "%ROOTDIR%\libedgetpu\%FREQ_DIR%\x64_windows\edgetpu.dll" c:\windows\system32
+copy "%ROOTDIR%\libedgetpu\%FREQ_DIR%\x64_windows\edgetpu.dll" "c:\windows\system32\edgetpu_direct_all.dll"
 copy "%ROOTDIR%\third_party\libusb_win\libusb-1.0.dll" c:\windows\system32
 
 echo Install complete!
uninstall.bat
 set ROOTDIR=%CD%
 
 echo Deleting edgetpu and libusb from System32
-del c:\windows\system32\edgetpu.dll
+del c:\windows\system32\edgetpu_direct_all.dll
 del c:\windows\system32\libusb-1.0.dll
 
 echo Unistalling WinUSB drivers

実行時にedgetpu_direct_all.dllが無いというメッセージが表示されているために名前を変更しています。
install.batをダブルクリックすると、動作周波数について質問を問われます。通常の周波数であれば、気温が35℃以下、最大の周波数の場合は25℃以下で安全に動作するように設計されているとありますが、特に理由がなければNで返事すれば良いと思います。

Warning: During normal operation, the Edge TPU Accelerator may heat up,
depending on the computation workloads and operating frequency. Touching the
metal part of the device after it has been operating for an extended period of
time may lead to discomfort and/or skin burns. As such, when running at the
default operating frequency, the device is intended to safely operate at an
ambient temperature of 35C or less. Or when running at the maximum operating
frequency, it should be operated at an ambient temperature of 25C or less.
................................................................................
Would you like to enable the maximum operating frequency for the USB Accelerator? Y/N

質問に回答するとUSBドライバがインストールされ、C:\Windows\System32にライブラリがコピーされます。USBにTPUアクセラレータを挿せば、認識すると思いますが、再起動が必要かもしれません。

go-tfliteの例を動かす

go-tfliteをまずgo getします。

$ go get github.com/mattn/go-tflite
$ cd /path/to/go-tflite
$ git checkout -b test 11e8959f01a963f78316c6f2d9d15e16c3ab25e9

go-tfliteのedge tpuを使った例をビルドするために\Users\dog\path\to\librarieslibtensorflow_c.dllと先程ダウンロードしたedgetpu_runtime_20200728.zipのedgetpu_runtime_20200728/edgetpu_runtime/libedgetpu/direct/x64_windowsにあるedgetpu.dllを置きます。

ファイルの移動が出来たら、cgoがライブラリを見つけられるように変数を設定してからgo buildします。この操作はコマンドプロンプトでしています。書いた通りに実行していれば、mingw64で実行するとエラーになるはずです。

$ cd  \path\to\go-tflite\_example\fizzbuzz_edgetpu 
$ set CGO_CFLAGS=-IC:\Users\dog\tensorflow
$ set CGO_LDFLAGS=-LC:\Users\dog\path\to\libraries
$ go build

ビルドに成功すればfizzbuzz_edgetpu.exeが生成されるのでオプション無しで実行します。出力の数行は、次のようになります。

出力
EdgeTPU Version: BuildLabel(COMPILER=MSVC 192628805,DATE=Jun 24 2020,TIME=11:34:07,CL_NUMBER=291256449), RuntimeVersion(13)
1
2
Fizz
4
...