Skip to content

Commit

Permalink
[hannk] Allow disabling TFLite+Delegate build in CMake (#6360)
Browse files Browse the repository at this point in the history
* [hannk] Allow disabling TFLite+Delegate build in CMake

Preparatory work for allowing building of hannk with Emscripten; TFLite (and its dependees) problematic to build in that environment, but this will allow us to build a tflite-parser-only environment.

(Note that more work is needed to get this working for wasm, as crosscompiling in CMake is still pretty painful; this work was split out to make subsequent reviews simpler)

* Update hannk_delegate.h

* HANNK_BUILD_TFLITE_DELEGATE -> HANNK_BUILD_TFLITE
  • Loading branch information
steven-johnson committed Oct 28, 2021
1 parent e10f104 commit 541bc37
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 10 deletions.
14 changes: 13 additions & 1 deletion apps/hannk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)

enable_testing()

option(HANNK_BUILD_TFLITE "Build TFLite+Delegate for HANNK" ON)
message(STATUS "HANNK_BUILD_TFLITE is ${HANNK_BUILD_TFLITE}")

# -fPIC is necessary for .so builds (at least on Linux); not necessary for the non-delegate
# builds but easier to enable it for everything.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
Expand All @@ -19,21 +22,30 @@ set(CMAKE_CXX_EXTENSIONS NO)
find_package(Halide REQUIRED)

# Set up the version of TFLite we expect
# (We need to do this even if HANNK_BUILD_TFLITE is off,
# so that the .tflite file parser can get the right schema)
set(TFLITE_VERSION_MAJOR "2" CACHE STRING "Major version of TFLite to assume")
set(TFLITE_VERSION_MINOR "6" CACHE STRING "Minor version of TFLite to assume")
set(TFLITE_VERSION_PATCH "0" CACHE STRING "Patch version of TFLite to assume")

add_compile_definitions(TFLITE_VERSION_MAJOR=${TFLITE_VERSION_MAJOR})
add_compile_definitions(TFLITE_VERSION_MINOR=${TFLITE_VERSION_MINOR})
add_compile_definitions(TFLITE_VERSION_PATCH=${TFLITE_VERSION_PATCH})
if (HANNK_BUILD_TFLITE)
add_compile_definitions(HANNK_BUILD_TFLITE=1)
else ()
add_compile_definitions(HANNK_BUILD_TFLITE=0)
endif ()

set(TFLITE_VERSION "${TFLITE_VERSION_MAJOR}.${TFLITE_VERSION_MINOR}.${TFLITE_VERSION_PATCH}")

add_subdirectory(delegate)
add_subdirectory(halide)
add_subdirectory(interpreter)
add_subdirectory(tflite)
add_subdirectory(util)
if (HANNK_BUILD_TFLITE)
add_subdirectory(delegate)
endif ()

# Benchmarking executable
add_executable(benchmark benchmark.cpp)
Expand Down
3 changes: 3 additions & 0 deletions apps/hannk/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ include ../support/Makefile.inc
# builds but easier to enable it for everything.
CXXFLAGS += -Wno-unused-private-field -fno-exceptions -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -Wunused-variable -Wsuggest-override -Woverloaded-virtual -I$(MAKEFILE_DIR)

# No option to build without TFLite/Delegate in Make (use CMake for that)
CXXFLAGS += -DHANNK_BUILD_TFLITE=1

BENCHMARK_OUT = benchmark
ifeq (hexagon-32-qurt,$(findstring hexagon-32-qurt,$(HL_TARGET)))
# Building benchmark application as shared object instead of elf for
Expand Down
8 changes: 8 additions & 0 deletions apps/hannk/configure_cmake.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ CMAKE_BUILD_TYPE=Release
fi
echo Using CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

if [ -z "${HANNK_BUILD_TFLITE}" ]; then
HANNK_BUILD_TFLITE=ON
else
HANNK_BUILD_TFLITE=OFF
fi
echo Using HANNK_BUILD_TFLITE=${HANNK_BUILD_TFLITE}

EXTRAS=
# TODO: this doesn't work (yet); crosscompiling in CMake is painful.
if [[ "${HL_TARGET}" =~ ^arm-64-android.* ]]; then
Expand All @@ -45,6 +52,7 @@ cmake \
-DHalide_DIR="${HALIDE_INSTALL_PATH}" \
-DCMAKE_PREFIX_PATH="${HALIDE_INSTALL_PATH}" \
-DHalide_TARGET=${HL_TARGET} \
-DHANNK_BUILD_TFLITE=${HANNK_BUILD_TFLITE} \
-S "${HANNK_DIR}" \
-B "${BUILD_DIR}"

4 changes: 4 additions & 0 deletions apps/hannk/delegate/hannk_delegate.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef HANNK_DELEGATE_H
#define HANNK_DELEGATE_H

#if !HANNK_BUILD_TFLITE
#error "This file should not be included when HANNK_BUILD_TFLITE=0"
#endif

#include "tensorflow/lite/c/c_api.h"

#ifdef __cplusplus
Expand Down
9 changes: 7 additions & 2 deletions apps/hannk/tflite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ set(FLATBUFFERS_BUILD_TESTS OFF)
set(FLATBUFFERS_INSTALL OFF)
set(FLATBUFFERS_BUILD_FLATC OFF)

# Enable this to see details about downloading -- useful for debugging
# set(FETCHCONTENT_QUIET NO)

FetchContent_Declare(tflite
GIT_REPOSITORY https://github.com/tensorflow/tensorflow
GIT_TAG ${TFLITE_TAG}
Expand All @@ -33,8 +36,10 @@ if (NOT tflite_POPULATED)
set(CMAKE_MESSAGE_LOG_LEVEL ${OLD_CMAKE_MESSAGE_LOG_LEVEL})
endif ()


# tensorflowlite_c is implicitly declared by this FetchContent
# tensorflowlite_c is implicitly declared by this FetchContent.
# Mark it as EXCLUDE_FROM_ALL so that it won't be built unless we actually
# depend on it (which we might not depending on HANNK_BUILD_TFLITE)
set_property(TARGET tensorflowlite_c PROPERTY EXCLUDE_FROM_ALL TRUE)

# Disable some noisy warnings in abseil
foreach (LIB IN ITEMS
Expand Down
12 changes: 8 additions & 4 deletions apps/hannk/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ target_include_directories(error_util PUBLIC
$<BUILD_INTERFACE:${hannk_SOURCE_DIR}>)
target_link_libraries(error_util PRIVATE Halide::Runtime)

add_library(hannk_log_stderr STATIC
add_library(hannk_log_stderr STATIC EXCLUDE_FROM_ALL
hannk_log_stderr.cpp)
target_include_directories(hannk_log_stderr PUBLIC
$<BUILD_INTERFACE:${hannk_SOURCE_DIR}>)

add_library(hannk_log_tflite STATIC
add_library(hannk_log_tflite STATIC EXCLUDE_FROM_ALL
hannk_log_tflite.cpp)
target_link_libraries(hannk_log_tflite PRIVATE tensorflowlite_headers)
target_include_directories(hannk_log_tflite PUBLIC
Expand Down Expand Up @@ -41,12 +41,16 @@ target_compile_definitions(model_runner PRIVATE
-DTFLITE_VERSION_MINOR=${TFLITE_VERSION_MINOR}
-DTFLITE_VERSION_PATCH=${TFLITE_VERSION_PATCH})
target_link_libraries(model_runner PRIVATE
tensorflowlite_c
interpreter
error_util
file_util
hannk_delegate
tflite_parser
Halide::Tools # for halide_benchmark.h
Halide::Runtime
tensorflowlite_headers)

if (HANNK_BUILD_TFLITE)
target_link_libraries(model_runner PRIVATE
tensorflowlite_c
hannk_delegate)
endif ()
43 changes: 40 additions & 3 deletions apps/hannk/util/model_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@

#include "util/model_runner.h"

#if HANNK_BUILD_TFLITE
#include "delegate/hannk_delegate.h"
#endif
#include "halide_benchmark.h"
#include "interpreter/interpreter.h"
#include "tflite/tflite_parser.h"
#include "util/buffer_util.h"
#include "util/error_util.h"
#include "util/file_util.h"

#if HANNK_BUILD_TFLITE
// IMPORTANT: use only the TFLite C API here.
#include "tensorflow/lite/c/c_api.h"
#include "tensorflow/lite/c/common.h"
#endif

namespace hannk {
namespace {
Expand All @@ -29,6 +33,7 @@ std::chrono::duration<double> bench(std::function<void()> f) {
return std::chrono::duration<double>(result.wall_time);
}

#if HANNK_BUILD_TFLITE
halide_type_t tf_lite_type_to_halide_type(TfLiteType t) {
switch (t) {
case kTfLiteBool:
Expand Down Expand Up @@ -141,6 +146,7 @@ class DelegatePtr {
}
}
};
#endif

static const char *const RunNames[ModelRunner::kNumRuns] = {
"TfLite",
Expand Down Expand Up @@ -234,6 +240,7 @@ int SeedTracker::seed_for_name(const std::string &name) {
return seed_here;
}

#if HANNK_BUILD_TFLITE
/*static*/ void TfLiteModelRunner::ErrorReporter(void *user_data, const char *format, va_list args) {
TfLiteModelRunner *self = (TfLiteModelRunner *)user_data;
if (self->verbose_output_) {
Expand Down Expand Up @@ -340,10 +347,15 @@ TfLiteModelRunner::~TfLiteModelRunner() {
TfLiteModelDelete(tf_model_);
}
}
#endif

ModelRunner::ModelRunner() {
for (int i = 0; i < kNumRuns; i++) {
#if HANNK_BUILD_TFLITE
do_run[i] = true;
#else
do_run[i] = (i == kHannk);
#endif
}
#if defined(__arm__) || defined(__aarch64__)
// TFLite on Arm devices generally uses the rounding-shift instructions,
Expand All @@ -369,13 +381,17 @@ void ModelRunner::status() {
std::cout << "Using random seed: " << seed_tracker_.next_seed() << "\n";
std::cout << "Using threads: " << threads << "\n";

#if HANNK_BUILD_TFLITE
std::string tf_ver = TfLiteVersion();
std::cout << "Using TFLite version: " << tf_ver << "\n";
std::string expected = std::to_string(TFLITE_VERSION_MAJOR) + "." + std::to_string(TFLITE_VERSION_MINOR) + ".";
if (tf_ver.find(expected) != 0) {
std::cerr << "*** WARNING: compare_vs_tflite has been tested against TFLite v" << expected << "x, "
<< "but is using " << tf_ver << "; results may be inaccurate or wrong.\n";
}
#else
std::cout << "Built without TFLite support.\n";
#endif
}
}

Expand Down Expand Up @@ -437,6 +453,7 @@ ModelRunner::RunResult ModelRunner::run_in_hannk(const std::vector<char> &buffer
return result;
}

#if HANNK_BUILD_TFLITE
ModelRunner::RunResult ModelRunner::run_in_tflite(const std::vector<char> &buffer, TfLiteDelegate *delegate) {
RunResult result;

Expand All @@ -457,6 +474,7 @@ ModelRunner::RunResult ModelRunner::run_in_tflite(const std::vector<char> &buffe

return result;
}
#endif

bool ModelRunner::compare_results(const std::string &name_a, const std::string &name_b, const RunResult &a, const RunResult &b) {
bool all_matched = true;
Expand Down Expand Up @@ -518,18 +536,27 @@ int ModelRunner::parse_flags(int argc, char **argv, std::vector<std::string> &fi
}
for (char c : value) {
switch (c) {
case 't':
this->do_run[ModelRunner::kTfLite] = true;
break;
case 'h':
this->do_run[ModelRunner::kHannk] = true;
break;
#if HANNK_BUILD_TFLITE
case 't':
this->do_run[ModelRunner::kTfLite] = true;
break;
case 'x':
this->do_run[ModelRunner::kExternalDelegate] = true;
break;
case 'i':
this->do_run[ModelRunner::kInternalDelegate] = true;
break;
#else
case 't':
case 'x':
case 'i':
std::cerr << "Unsupported option to --enable (TFLite is not enabled in this build): " << c << "\n";
return -1;
break;
#endif
default:
std::cerr << "Unknown option to --enable: " << c << "\n";
return -1;
Expand Down Expand Up @@ -623,6 +650,7 @@ void ModelRunner::run(const std::string &filename) {

const std::vector<char> buffer = read_entire_file(filename);

#if HANNK_BUILD_TFLITE
const auto exec_tflite = [this, &buffer]() {
return run_in_tflite(buffer);
};
Expand All @@ -648,9 +676,18 @@ void ModelRunner::run(const std::string &filename) {
{kExternalDelegate, exec_hannk_external_delegate},
{kInternalDelegate, exec_hannk_internal_delegate},
};
#endif

for (WhichRun i : active_runs) {
#if HANNK_BUILD_TFLITE
results[i] = execs.at(i)();
#else
if (i != kHannk) {
std::cerr << "Only kHannk is available in this build.\n";
exit(1);
}
results[i] = run_in_hannk(buffer);
#endif
}

// ----- Log benchmark times
Expand Down
6 changes: 6 additions & 0 deletions apps/hannk/util/model_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@

#include "util/buffer_util.h"

#if HANNK_BUILD_TFLITE
struct TfLiteDelegate;
struct TfLiteInterpreter;
struct TfLiteInterpreterOptions;
struct TfLiteModel;
#endif

namespace hannk {

Expand Down Expand Up @@ -60,6 +62,7 @@ struct SeedTracker {
SeedTracker &operator=(SeedTracker &&) = delete;
};

#if HANNK_BUILD_TFLITE
class TfLiteModelRunner {
TfLiteModel *tf_model_ = nullptr;
TfLiteInterpreterOptions *tf_options_ = nullptr;
Expand All @@ -84,6 +87,7 @@ class TfLiteModelRunner {
TfLiteModelRunner(TfLiteModelRunner &&) = delete;
TfLiteModelRunner &operator=(TfLiteModelRunner &&) = delete;
};
#endif

// TODO: add a way to bottleneck stdout/stdout, or just errors/warnings in general
struct ModelRunner {
Expand Down Expand Up @@ -130,7 +134,9 @@ struct ModelRunner {
std::chrono::duration<double> time{0};
};
RunResult run_in_hannk(const std::vector<char> &buffer);
#if HANNK_BUILD_TFLITE
RunResult run_in_tflite(const std::vector<char> &buffer, TfLiteDelegate *delegate = nullptr);
#endif
bool compare_results(const std::string &name_a, const std::string &name_b, const RunResult &a, const RunResult &b);
};

Expand Down

0 comments on commit 541bc37

Please sign in to comment.