Generic Benchmark Tool changes (#2451)
@tensorflow/micro
Add ability to build with a model chosen at compile time. Add README with build instructions.
bug=fixes #2450
diff --git a/tensorflow/lite/micro/tools/benchmarking/Makefile.inc b/tensorflow/lite/micro/tools/benchmarking/Makefile.inc
index 036927e..32e782c 100644
--- a/tensorflow/lite/micro/tools/benchmarking/Makefile.inc
+++ b/tensorflow/lite/micro/tools/benchmarking/Makefile.inc
@@ -1,5 +1,23 @@
MICROLITE_BENCHMARK_ROOT_DIR := $(TENSORFLOW_ROOT)tensorflow/lite/micro/tools/benchmarking
+ifneq ($(BENCHMARK_MODEL_PATH),)
+ GENERIC_BENCHMARK_MODEL_DIR := $(dir $(BENCHMARK_MODEL_PATH))
+ GENERIC_BENCHMARK_MODEL_NAME := $(notdir $(basename $(BENCHMARK_MODEL_PATH)))
+ CXXFLAGS += -DMODEL_HEADER_PATH=\"$(GENERIC_BENCHMARK_MODEL_DIR)$(GENERIC_BENCHMARK_MODEL_NAME)_model_data.h\"
+ CXXFLAGS += -DMODEL_NAME=$(GENERIC_BENCHMARK_MODEL_NAME)
+ifneq ($(BENCHMARK_ARENA_SIZE),)
+ CXXFLAGS += -DTENSOR_ARENA_SIZE=$(BENCHMARK_ARENA_SIZE)
+endif
+
+ GENERIC_BENCHMARK_GENERATOR_INPUTS := $(TENSORFLOW_ROOT)$(BENCHMARK_MODEL_PATH)
+
+ GENERIC_BENCHMARK_GENERATED_SRCS := \
+ $(GENERATED_SRCS_DIR)$(TENSORFLOW_ROOT)$(GENERIC_BENCHMARK_MODEL_DIR)$(GENERIC_BENCHMARK_MODEL_NAME)_model_data.cc
+
+ GENERIC_BENCHMARK_GENERATED_HDRS := \
+ $(GENERATED_SRCS_DIR)$(TENSORFLOW_ROOT)$(GENERIC_BENCHMARK_MODEL_DIR)$(GENERIC_BENCHMARK_MODEL_NAME)_model_data.h
+endif
+
GENERIC_BENCHMARK_SRCS := \
$(MICROLITE_BENCHMARK_ROOT_DIR)/generic_model_benchmark.cc \
$(MICROLITE_BENCHMARK_ROOT_DIR)/metrics.cc
@@ -11,6 +29,7 @@
ifneq ($(TARGET),bluepill)
ifneq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), hifimini))
$(eval $(call microlite_test,tflm_benchmark,\
- $(GENERIC_BENCHMARK_SRCS),$(GENERIC_BENCHMARK_HDRS),))
+ $(GENERIC_BENCHMARK_SRCS),$(GENERIC_BENCHMARK_HDRS),\
+ $(GENERIC_BENCHMARK_GENERATOR_INPUTS)))
endif
endif
diff --git a/tensorflow/lite/micro/tools/benchmarking/README.md b/tensorflow/lite/micro/tools/benchmarking/README.md
new file mode 100644
index 0000000..0bc727e
--- /dev/null
+++ b/tensorflow/lite/micro/tools/benchmarking/README.md
@@ -0,0 +1,48 @@
+# Generic Benchmarking Tool build/run instructions
+This tool can be used to benchmark any TfLite format model. The tool can be
+compiled in one of two ways:
+1. Such that it takes command line arguments, allowing the path to the model
+file to be specified as a program argument
+2. With a model compiled into the tool, allowing use in any simulator or on
+any hardware platform
+
+Building the tool with the model compiled in uses two additional Makefile
+variables:
+* `BENCHMARK_MODEL_PATH`: the path to the TfLite format model file. This
+can be a relative or absolute path. This variable is required.
+* `BENCHMARK_ARENA_SIZE`: the size of the TFLM interpreter arena, in bytes.
+This variable is optional.
+
+## Tested, working targets
+* x86
+* cortex_m_qemu (no timing data)
+* Xtensa
+* cortex_m_corstone_300
+
+## Tested, non-working targets
+* none currently
+
+## Build and run for x86
+Build for command line arguments:
+```
+make -f tensorflow/lite/micro/tools/make/Makefile tflm_benchmark -j$(nproc)
+```
+Run with command line arguments:
+```
+gen/linux_x86_64_default/bin/tflm_benchmark tensorflow/lite/micro/models/person_detect.tflite
+```
+
+Build with model compiled into tool:
+```
+make -f tensorflow/lite/micro/tools/make/Makefile tflm_benchmark -j$(nproc) BENCHMARK_MODEL_PATH=tensorflow/lite/micro/models/person_detect.tflite BENCHMARK_ARENA_SIZE=`expr 100 \* 1024`
+```
+Run with model compiled into tool:
+```
+gen/linux_x86_64_default/bin/tflm_benchmark
+```
+
+## Build and run for Xtensa
+Build and run with model compiled into tool:
+```
+make -f tensorflow/lite/micro/tools/make/Makefile TARGET=xtensa TARGET_ARCH=vision_p6 OPTIMIZED_KERNEL_DIR=xtensa XTENSA_CORE=P6_200528 BUILD_TYPE=default run_tflm_benchmark -j$(nproc) BENCHMARK_MODEL_PATH=/tmp/keyword_scrambled.tflite BENCHMARK_ARENA_SIZE=`expr 50 \* 1024`
+```
diff --git a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc
index 5f6e4c3..eef5f4c 100644
--- a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc
+++ b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc
@@ -1,4 +1,4 @@
-/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,9 +20,11 @@
#include <cstring>
#include <memory>
#include <random>
+#include <type_traits>
#include "tensorflow/lite/c/c_api_types.h"
#include "tensorflow/lite/c/common.h"
+#include "tensorflow/lite/micro/micro_context.h"
#include "tensorflow/lite/micro/micro_log.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/micro_op_resolver.h"
@@ -34,6 +36,23 @@
#include "tensorflow/lite/micro/tools/benchmarking/op_resolver.h"
#include "tensorflow/lite/schema/schema_generated.h"
+#if defined(MODEL_HEADER_PATH)
+#if !defined(MODEL_NAME)
+#error "MODEL_NAME missing from CCFLAGS"
+#endif // !defined(MODEL_NAME)
+
+#include MODEL_HEADER_PATH
+
+#define __MODEL_DATA(x) g_##x##_model_data
+#define _MODEL_DATA(x) __MODEL_DATA(x)
+#define MODEL_DATA _MODEL_DATA(MODEL_NAME)
+#define __MODEL_SIZE(x) g_##x##_model_data_size
+#define _MODEL_SIZE(x) __MODEL_SIZE(x)
+#define MODEL_SIZE _MODEL_SIZE(MODEL_NAME)
+
+#define USING_BUILTIN_MODEL
+#endif // defind(MODEL_HEADER_PATH)
+
/*
* Generic model benchmark. Evaluates runtime performance of a provided model
* with random inputs.
@@ -45,15 +64,20 @@
using Profiler = ::tflite::MicroProfiler;
-constexpr int kTfLiteAbort = -9;
-
// Seed used for the random input. Input data shouldn't affect invocation timing
// so randomness isn't really needed.
constexpr uint32_t kRandomSeed = 0xFB;
+#if !defined(USING_BUILTIN_MODEL)
constexpr size_t kTensorArenaSize = 3e6;
-constexpr int kNumResourceVariable = 100;
constexpr size_t kModelSize = 2e6;
+#elif defined(TENSOR_ARENA_SIZE)
+constexpr size_t kTensorArenaSize = TENSOR_ARENA_SIZE;
+#else
+constexpr size_t kTensorArenaSize = 5e6 - MODEL_SIZE;
+#endif // !defined(USING_BUILTIN_MODEL)
+
+constexpr int kNumResourceVariable = 100;
void SetRandomInput(const uint32_t random_seed,
tflite::MicroInterpreter& interpreter) {
@@ -71,6 +95,7 @@
}
}
+#if !defined(USING_BUILTIN_MODEL)
bool ReadFile(const char* file_name, void* buffer, size_t buffer_size) {
std::unique_ptr<FILE, decltype(&fclose)> file(fopen(file_name, "rb"), fclose);
@@ -95,17 +120,16 @@
return true;
}
+#endif // !defined(USING_BUILTIN_MODEL)
-int Benchmark(const char* model_file_name, tflite::PrettyPrintType print_type) {
+int Benchmark(const uint8_t* model_data, tflite::PrettyPrintType print_type) {
Profiler profiler;
alignas(16) static uint8_t tensor_arena[kTensorArenaSize];
- alignas(16) static uint8_t model_file_content[kModelSize];
- if (!ReadFile(model_file_name, model_file_content, kModelSize)) {
- return -1;
- }
+ MicroPrintf("\nConfigured arena size = %d\n", kTensorArenaSize);
+
uint32_t event_handle = profiler.BeginEvent("TfliteGetModel");
- const tflite::Model* model = tflite::GetModel(model_file_content);
+ const tflite::Model* model = tflite::GetModel(model_data);
profiler.EndEvent(event_handle);
TflmOpResolver op_resolver;
@@ -156,14 +180,18 @@
} // namespace
} // namespace tflite
+#if !defined(USING_BUILTIN_MODEL)
void usage(const char* prog_name) {
MicroPrintf("usage: %s filename [--csv]", prog_name);
}
+#endif // !defined(USING_BUILTIN_MODEL)
int main(int argc, char** argv) {
// Which format should be used to output debug information.
tflite::PrettyPrintType print_type = tflite::PrettyPrintType::kTable;
+ tflite::InitializeTarget();
+#if !defined(USING_BUILTIN_MODEL)
if (argc < 2 || argc > 3) {
usage(argv[0]);
return -1;
@@ -179,5 +207,14 @@
}
}
- return tflite::Benchmark(model_filename, print_type);
+ alignas(16) static uint8_t model_data[tflite::kModelSize];
+
+ if (!tflite::ReadFile(model_filename, model_data, tflite::kModelSize)) {
+ return -1;
+ }
+#else
+ const uint8_t* model_data = MODEL_DATA;
+#endif // !defined(USING_BUILTIN_MODEL)
+
+ return tflite::Benchmark(model_data, print_type);
}
diff --git a/tensorflow/lite/micro/tools/generate_cc_arrays.py b/tensorflow/lite/micro/tools/generate_cc_arrays.py
index 4d1e54c..16d72c1 100644
--- a/tensorflow/lite/micro/tools/generate_cc_arrays.py
+++ b/tensorflow/lite/micro/tools/generate_cc_arrays.py
@@ -35,8 +35,6 @@
out_cc_file.write('#include <cstdint>\n\n')
out_cc_file.write('#include "{}"\n\n'.format(
out_fname.split('genfiles/')[-1].replace('.cc', '.h')))
- out_cc_file.write('const unsigned int {}_size = {};\n'.format(
- array_name, str(size)))
out_cc_file.write('alignas(16) const {} {}[] = {{'.format(
array_type, array_name))
out_cc_file.write(array_contents)
@@ -45,8 +43,8 @@
elif out_fname.endswith('.h'):
out_hdr_file = open(out_fname, 'w')
out_hdr_file.write('#include <cstdint>\n\n')
- out_hdr_file.write(
- 'extern const unsigned int {}_size;\n'.format(array_name))
+ out_hdr_file.write('constexpr unsigned int {}_size = {};\n'.format(
+ array_name, str(size)))
out_hdr_file.write('extern const {} {}[];\n'.format(
array_type, array_name))
out_hdr_file.close()