LoginSignup
8
4

More than 3 years have passed since last update.

Windows向けtensorflowliteのビルド(for Visual Studio 2017)

Last updated at Posted at 2020-02-02

はじめに

先日 書いたWindows向けTensorflow liteのビルドではMinGW向けでVisualStudioを用いたアプリ開発ができませんでした
Makefile(CMake)をゴリゴリ駆使して開発しても良かったのですがデバッグ効率が悪いことからVisualStudio向けのビルドに挑戦し、うまくいったのでまとめておきます

この記事のモチベーション

  • Bazelを用いてTensorflow liteのビルドを行いたい
  • 手軽にmasterを追いかける環境を用意しておきたい

ビルド環境

  • Windows10
  • Bazel1.2.1
    • ./configure.pyで求められるバージョンを使用
  • MSYS2 + VisualStudio2017(version15.9.19)
  • Python3.6
  • tensorflow master: f285ba1aab3223279131db7168f23884fa79812c
    • origin/r2.xブランチにはまだtensorflowliteのビルドルールが無いためmasterを使います

ビルド手順

$ cd tensorflow
$ python ./configure.py #全部Noにすれば最小限
$ VSPATH="$(cygpath -u "$(reg query 'HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7' -v 15.0 | tail -n+3 | head -n1  | awk '{for (i=3;i<=NF;i++) {printf "%s ",$i;};}' | sed 's/ *$//')")"
$ export BAZEL_VS="$VSPATH" #VS2017を使用
$ bazel build -c opt --cxxopt=--std=c++11 tensorflow/lite:tensorflowlite

※BAZEL_VSを解決するためにこちらを参考にしています
※ビルドが成功すると tensorflow\bazel-out\x64_windows-opt\bin 以下にバイナリがあります

ビルドしたライブラリの利用

注意: tensorflowlite.dllのビルドに成功したと思っていたのですが、実はdllはすっからかんで.libの方を使用することになります

tensorflow/lite/examples/minimal/minimal.cc を元に最小限コードをコンパイル&実行してみます

includeパスに

tensorflow
tensorflow\bazel-tensorflow\external\com_google_absl
tensorflow\bazel-tensorflow\external\flatbuffers\include

を追加、libraryパスに

tensorflow\bazel-out\x64_windows-opt\bin\tensorflow\lite
tensorflow\bazel-out\x64_windows-opt\bin\external

を追加しておきます。

※mobilenet_v1_1.0_224.tfliteは任意の.tfliteファイルに置き換え可能です

Minimal.cpp
#include <iostream>
#pragma comment(lib, "c\\common.lo.lib")
#pragma comment(lib, "core\\api\\api.lib")
#pragma comment(lib, "delegates\\nnapi\\nnapi_delegate.lib")
#pragma comment(lib, "kernels\\builtin_op_kernels.lo.lib")
#pragma comment(lib, "kernels\\builtin_ops.lo.lib")
#pragma comment(lib, "kernels\\cpu_backend_context.lib")
#pragma comment(lib, "kernels\\cpu_backend_gemm.lib")
#pragma comment(lib, "kernels\\eigen_support.lib")
#pragma comment(lib, "kernels\\kernel_util.lib")
#pragma comment(lib, "kernels\\lstm_eval.lib")

#pragma comment(lib, "kernels\\internal\\audio_utils.lib")
#pragma comment(lib, "kernels\\internal\\kernel_utils.lib")
#pragma comment(lib, "kernels\\internal\\neon_tensor_utils.lib")
#pragma comment(lib, "kernels\\internal\\portable_tensor_utils.lib")
#pragma comment(lib, "kernels\\internal\\quantization_util.lib")
#pragma comment(lib, "kernels\\internal\\sse_tensor_utils.lib")
#pragma comment(lib, "kernels\\internal\\tensor_utils.lib")
#pragma comment(lib, "kernels\\internal\\transpose_utils.lib")

#pragma comment(lib, "experimental\\ruy\\allocator.lib")
#pragma comment(lib, "experimental\\ruy\\block_map.lib")
#pragma comment(lib, "experimental\\ruy\\blocking_counter.lib")
#pragma comment(lib, "experimental\\ruy\\context.lib")
#pragma comment(lib, "experimental\\ruy\\detect_arm.lib")
#pragma comment(lib, "experimental\\ruy\\detect_x86.lib")
#pragma comment(lib, "experimental\\ruy\\have_built_path_for_avx2.lib")
#pragma comment(lib, "experimental\\ruy\\have_built_path_for_avx512.lib")
#pragma comment(lib, "experimental\\ruy\\have_built_path_for_avxvnni.lib")
#pragma comment(lib, "experimental\\ruy\\have_built_path_for_sse42.lib")
#pragma comment(lib, "experimental\\ruy\\kernel_arm.lib")
#pragma comment(lib, "experimental\\ruy\\kernel_avx2.lib")
#pragma comment(lib, "experimental\\ruy\\kernel_avx512.lib")
#pragma comment(lib, "experimental\\ruy\\kernel_avxvnni.lib")
#pragma comment(lib, "experimental\\ruy\\kernel_sse42.lib")
#pragma comment(lib, "experimental\\ruy\\pack_arm.lib")
#pragma comment(lib, "experimental\\ruy\\pack_avx2.lib")
#pragma comment(lib, "experimental\\ruy\\pack_avx512.lib")
#pragma comment(lib, "experimental\\ruy\\pack_avxvnni.lib")
#pragma comment(lib, "experimental\\ruy\\pack_sse42.lib")
#pragma comment(lib, "experimental\\ruy\\prepacked_cache.lib")
#pragma comment(lib, "experimental\\ruy\\thread_pool.lib")
#pragma comment(lib, "experimental\\ruy\\trace.lib")
#pragma comment(lib, "experimental\\ruy\\trmul.lib")
#pragma comment(lib, "experimental\\ruy\\tune.lib")
#pragma comment(lib, "experimental\\ruy\\wait.lib")

#pragma comment(lib, "tools\\optimize\\sparsity\\format_converter.lib")

#pragma comment(lib, "farmhash_archive\\farmhash.lib")
#pragma comment(lib, "flatbuffers\\src\\flatbuffers.lib")
#pragma comment(lib, "flatbuffers\\src\\flatc.lib")

#pragma comment(lib, "fft2d\\fft2d.lib")

#pragma comment(lib, "allocation.lib")
#pragma comment(lib, "arena_planner.lib")
#pragma comment(lib, "external_cpu_backend_context.lib")
#pragma comment(lib, "framework.lo.lib")
#pragma comment(lib, "minimal_logging.lib")
#pragma comment(lib, "simple_memory_arena.lib")
#pragma comment(lib, "string_util.lib")
#pragma comment(lib, "tensorflowlite.dll.if.lib") # たぶん不要
#pragma comment(lib, "util.lib")

#include <cstdio>
#include <tensorflow/lite/interpreter.h>
#include <tensorflow/lite/kernels/register.h>
#include <tensorflow/lite/model.h>
#include <tensorflow/lite/optional_debug_tools.h>

int main()
{
    auto model = tflite::FlatBufferModel::BuildFromFile("mobilenet_v1_1.0_224.tflite");

    // Build the interpreter
    tflite::ops::builtin::BuiltinOpResolver resolver;
    tflite::InterpreterBuilder builder(*model, resolver);
    std::unique_ptr<tflite::Interpreter> interpreter;
    builder(&interpreter);

    // Allocate tensor buffers.
    printf("=== Pre-invoke Interpreter State ===\n");
    tflite::PrintInterpreterState(interpreter.get());

    // Run inference
    printf("\n\n=== Post-invoke Interpreter State ===\n");
    tflite::PrintInterpreterState(interpreter.get());
}

こんな感じの実行結果が出れば成功です

output.txt
=== Pre-invoke Interpreter State ===
Interpreter has 88 tensors and 31 nodes
Inputs: 87
Outputs: 86

Tensor   0 MobilenetV1/Conv2d_0/weights kTfLiteFloat32   kTfLiteMmapRo       3456 bytes ( 0.0 MB)  32 3 3 3
Tensor   1 MobilenetV1/Conv2d_10_depthwise/depthwise_weights kTfLiteFloat32   kTfLiteMmapRo      18432 bytes ( 0.0 MB)  1 3 3 512
Tensor   2 MobilenetV1/Conv2d_10_pointwise/weights kTfLiteFloat32   kTfLiteMmapRo    1048576 bytes ( 1.0 MB)  512 1 1 512
Tensor   3 MobilenetV1/Conv2d_11_depthwise/depthwise_weights kTfLiteFloat32   kTfLiteMmapRo      18432 bytes ( 0.0 MB)  1 3 3 512


・・・


  Inputs: 49
  Outputs: 27
Node  28 Operator Builtin Code   3 CONV_2D
  Inputs: 27 30 29
  Outputs: 28
Node  29 Operator Builtin Code  43 SQUEEZE
  Inputs: 28
  Outputs: 31
Node  30 Operator Builtin Code  25 SOFTMAX
  Inputs: 31
  Outputs: 86

8
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4