Enable ATrace profiler by Android system property.

ATrace profiler is included in Android library always.
To enable ATrace profiler when running app,
users need to set 'debug.tflite.trace' property.

$ adb shell setprop debug.tflite.trace 1

PiperOrigin-RevId: 328684900
Change-Id: I3fa9511a58e9055c3c4d371f904daf8c530abcf4
This commit is contained in:
Juho Ha 2020-08-26 23:57:00 -07:00 committed by TensorFlower Gardener
parent e9c732e847
commit 9394966102
20 changed files with 176 additions and 148 deletions

View File

@ -157,6 +157,8 @@
* Deprecate `Interpreter::UseNNAPI(bool)` C++ API
* Prefer using `NnApiDelegate()` and related delegate configuration methods directly.
* Add NNAPI Delegation support for requantization use cases by converting the operation into a dequantize-quantize pair.
* TFLite Profiler for Android is available. See the detailed
[guide](https://www.tensorflow.org/lite/performance/measurement#trace_tensorflow_lite_internals_in_android).
* <ADD RELEASE NOTES HERE>
* `tf.random`:
* <ADD RELEASE NOTES HERE>

View File

@ -16,13 +16,6 @@ exports_files(glob([
"models/testdata/*",
]))
config_setting(
name = "enable_default_profiler",
values = {
"copt": "-DTFLITE_ENABLE_DEFAULT_PROFILER",
},
)
config_setting(
name = "gemmlowp_profiling",
values = {
@ -275,13 +268,9 @@ cc_library(
"//tensorflow/lite/experimental/resource",
"//tensorflow/lite/kernels/internal:compatibility",
"//tensorflow/lite/nnapi:nnapi_implementation",
"//tensorflow/lite/profiling:platform_profiler",
"//tensorflow/lite/schema:schema_fbs",
] + select({
":enable_default_profiler": [
"//tensorflow/lite/profiling:platform_profiler",
],
"//conditions:default": [],
}),
],
alwayslink = 1,
)

View File

@ -27,15 +27,12 @@ limitations under the License.
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/core/api/flatbuffer_conversions.h"
#include "tensorflow/lite/kernels/internal/compatibility.h"
#include "tensorflow/lite/profiling/platform_profiler.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/shared_library.h"
#include "tensorflow/lite/util.h"
#include "tensorflow/lite/version.h"
#if defined(TFLITE_ENABLE_DEFAULT_PROFILER)
#include "tensorflow/lite/profiling/platform_profiler.h"
#endif
// aligned_alloc is available (via cstdlib/stdlib.h) with C++17/C11.
#if __cplusplus >= 201703L || __STDC_VERSION__ >= 201112L
#if !defined(__ANDROID__) || __ANDROID_API__ >= 28
@ -630,9 +627,7 @@ TfLiteStatus InterpreterBuilder::operator()(
(*interpreter)->AddSubgraphs(subgraphs->size() - 1);
}
#if defined(TFLITE_ENABLE_DEFAULT_PROFILER)
(*interpreter)->SetProfiler(tflite::profiling::CreatePlatformProfiler());
#endif
(*interpreter)->SetProfiler(tflite::profiling::MaybeCreatePlatformProfiler());
for (int subgraph_index = 0; subgraph_index < subgraphs->size();
++subgraph_index) {

View File

@ -1,13 +1,14 @@
load("//tensorflow:tensorflow.bzl", "if_not_windows")
load("//tensorflow:tensorflow.bzl", "get_compatible_with_portable")
load("//tensorflow/lite:build_def.bzl", "tflite_copts")
load("//tensorflow/lite:special_rules.bzl", "tflite_portable_test_suite_combined")
package(
default_visibility = ["//visibility:public"],
licenses = ["notice"], # Apache 2.0
)
common_copts = [
"-Wall",
] + tflite_copts()
common_copts = tflite_copts() + if_not_windows(["-Wall"])
cc_library(
name = "profiler",
@ -23,6 +24,16 @@ cc_library(
],
)
cc_test(
name = "profiler_test",
srcs = ["profiler_test.cc"],
deps = [
":profiler",
":test_main",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "atrace_profiler",
srcs = ["atrace_profiler.cc"],
@ -35,10 +46,21 @@ cc_library(
],
)
cc_test(
name = "atrace_profiler_test",
srcs = ["atrace_profiler_test.cc"],
deps = [
":atrace_profiler",
":test_main",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "platform_profiler",
srcs = ["platform_profiler.cc"],
hdrs = ["platform_profiler.h"],
compatible_with = get_compatible_with_portable(),
copts = common_copts,
deps = [
"//tensorflow/lite/core/api",
@ -48,16 +70,6 @@ cc_library(
}),
)
cc_test(
name = "profiler_test",
srcs = ["profiler_test.cc"],
deps = [
":profiler",
"//tensorflow/lite/testing:util",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "profile_buffer",
hdrs = ["profile_buffer.h"],
@ -69,6 +81,16 @@ cc_library(
],
)
cc_test(
name = "profile_buffer_test",
srcs = ["profile_buffer_test.cc"],
deps = [
":profile_buffer",
":test_main",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "time",
srcs = ["time.cc"],
@ -76,6 +98,16 @@ cc_library(
copts = common_copts,
)
cc_test(
name = "time_test",
srcs = ["time_test.cc"],
deps = [
":test_main",
":time",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "memory_info",
srcs = ["memory_info.cc"],
@ -83,31 +115,21 @@ cc_library(
copts = common_copts,
)
cc_test(
name = "time_test",
srcs = ["time_test.cc"],
copts = common_copts,
deps = [
":time",
"//tensorflow/lite/testing:util",
"@com_google_googletest//:gtest",
],
)
cc_test(
name = "memory_info_test",
srcs = ["memory_info_test.cc"],
copts = common_copts,
tags = [
# Some low-level checks, like heap size check, may break in asan, msan
# and tsan. So, disable such tests.
"noasan",
"nomsan",
"notsan",
# TODO(b/166227284): Fix the test for Android.
"tflite_not_portable_android",
],
deps = [
":memory_info",
"//tensorflow/lite/testing:util",
":test_main",
"@com_google_googletest//:gtest",
],
)
@ -125,10 +147,9 @@ cc_library(
cc_test(
name = "profile_summary_formatter_test",
srcs = ["profile_summary_formatter_test.cc"],
copts = common_copts,
deps = [
":profile_summary_formatter",
"//tensorflow/lite/testing:util",
":test_main",
"@com_google_googletest//:gtest",
],
)
@ -151,26 +172,28 @@ cc_library(
cc_test(
name = "profile_summarizer_test",
srcs = ["profile_summarizer_test.cc"],
copts = common_copts,
deps = [
":profile_summarizer",
":profiler",
":test_main",
"//tensorflow/lite:framework",
"//tensorflow/lite:schema_fbs_version",
"//tensorflow/lite/kernels:kernel_util",
"//tensorflow/lite/kernels:subgraph_test_util",
"//tensorflow/lite/kernels:test_util",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "test_main",
testonly = 1,
srcs = ["test_main.cc"],
visibility = ["//visibility:private"],
deps = [
"//tensorflow/lite/testing:util",
"@com_google_googletest//:gtest",
],
)
cc_test(
name = "profile_buffer_test",
srcs = ["profile_buffer_test.cc"],
deps = [
":profile_buffer",
"//tensorflow/lite/testing:util",
"@com_google_googletest//:gtest",
],
)
tflite_portable_test_suite_combined(combine_conditions = {"deps": [":test_main"]})

View File

@ -15,6 +15,9 @@ limitations under the License.
#include "tensorflow/lite/profiling/atrace_profiler.h"
#include <dlfcn.h>
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#endif
#include <type_traits>
@ -89,8 +92,16 @@ class ATraceProfiler : public tflite::Profiler {
FpEndSection atrace_end_section_;
};
std::unique_ptr<tflite::Profiler> CreateATraceProfiler() {
return std::unique_ptr<tflite::Profiler>(new ATraceProfiler());
std::unique_ptr<tflite::Profiler> MaybeCreateATraceProfiler() {
#if defined(__ANDROID__)
constexpr char kTraceProp[] = "debug.tflite.trace";
char trace_enabled[PROP_VALUE_MAX] = "";
int length = __system_property_get(kTraceProp, trace_enabled);
if (length == 1 && trace_enabled[0] == '1') {
return std::unique_ptr<tflite::Profiler>(new ATraceProfiler());
}
#endif // __ANDROID__
return nullptr;
}
} // namespace profiling

View File

@ -22,7 +22,7 @@ limitations under the License.
namespace tflite {
namespace profiling {
std::unique_ptr<tflite::Profiler> CreateATraceProfiler();
std::unique_ptr<tflite::Profiler> MaybeCreateATraceProfiler();
} // namespace profiling
} // namespace tflite

View File

@ -0,0 +1,48 @@
/* Copyright 2020 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/profiling/atrace_profiler.h"
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#endif
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace tflite {
namespace profiling {
namespace {
TEST(ATraceProfilerTest, MaybeCreateATraceProfiler) {
auto default_profiler = MaybeCreateATraceProfiler();
EXPECT_EQ(nullptr, default_profiler.get());
#if defined(__ANDROID__)
if (__system_property_set("debug.tflite.trace", "1") == 0) {
auto profiler = MaybeCreateATraceProfiler();
EXPECT_NE(nullptr, profiler.get());
}
if (__system_property_set("debug.tflite.trace", "0") == 0) {
auto no_profiler = MaybeCreateATraceProfiler();
EXPECT_EQ(nullptr, no_profiler.get());
}
#endif // __ANDROID__
}
} // namespace
} // namespace profiling
} // namespace tflite

View File

@ -15,7 +15,6 @@ limitations under the License.
#include "tensorflow/lite/profiling/memory_info.h"
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
namespace tflite {
namespace profiling {
@ -71,9 +70,3 @@ TEST(MemoryUsage, IsSupported) {
} // namespace memory
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -25,11 +25,11 @@ limitations under the License.
namespace tflite {
namespace profiling {
std::unique_ptr<tflite::Profiler> CreatePlatformProfiler() {
std::unique_ptr<tflite::Profiler> MaybeCreatePlatformProfiler() {
#if defined(__ANDROID__)
return CreateATraceProfiler();
return MaybeCreateATraceProfiler();
#else
return std::unique_ptr<tflite::Profiler>(nullptr);
return nullptr;
#endif
}

View File

@ -22,7 +22,7 @@ limitations under the License.
namespace tflite {
namespace profiling {
std::unique_ptr<tflite::Profiler> CreatePlatformProfiler();
std::unique_ptr<tflite::Profiler> MaybeCreatePlatformProfiler();
} // namespace profiling
} // namespace tflite

View File

@ -20,7 +20,6 @@ limitations under the License.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
namespace tflite {
namespace profiling {
@ -121,9 +120,3 @@ TEST(ProfileBufferTest, Enable) {
} // namespace
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -26,7 +26,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/profiling/buffered_profiler.h"
#include "tensorflow/lite/testing/util.h"
#include "tensorflow/lite/version.h"
namespace tflite {
@ -224,9 +223,3 @@ TEST_F(ProfileSummarizerIfOpTest, TestIfFalse) {
} // namespace
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -19,7 +19,6 @@ limitations under the License.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
namespace tflite {
namespace profiling {
@ -156,9 +155,3 @@ TEST(SummaryWriterTest, DelegationShortSummary) {
} // namespace
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -22,7 +22,6 @@ limitations under the License.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
namespace tflite {
namespace profiling {
@ -136,9 +135,3 @@ TEST(ProfilingTest, NoopProfiler) {
} // namespace
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,23 @@
/* Copyright 2018 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -15,7 +15,6 @@ limitations under the License.
#include "tensorflow/lite/profiling/time.h"
#include <gtest/gtest.h>
#include "tensorflow/lite/testing/util.h"
namespace tflite {
namespace profiling {
@ -48,9 +47,3 @@ TEST(TimeTest, SleepForMicros) {
} // namespace time
} // namespace profiling
} // namespace tflite
int main(int argc, char** argv) {
::tflite::LogToStderr();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -158,7 +158,6 @@ cc_library(
"//tensorflow/lite/c:common",
"//tensorflow/lite/kernels:builtin_ops",
"//tensorflow/lite/kernels:cpu_backend_context",
"//tensorflow/lite/profiling:platform_profiler",
"//tensorflow/lite/profiling:profile_summary_formatter",
"//tensorflow/lite/profiling:profiler",
"//tensorflow/lite/tools:logging",

View File

@ -36,11 +36,6 @@ and the following optional parameters:
mean use no delay.
* `enable_op_profiling`: `bool` (default=false) \
Whether to enable per-operator profiling measurement.
* `enable_platform_tracing`: `bool` (default=false) \
Whether to enable platform-wide tracing. Needs to be combined with
'enable_op_profiling'. Note, the platform-wide tracing might not work if the
tool runs as a commandline native binary. For example, on Android, the
ATrace-based tracing only works when the tool is launched as an APK.
* `profiling_output_csv_file`: `str` (default="") \
File path to export profile data to as CSV. The results are printed to
`stdout` if option is not set. Requires `enable_op_profiling` to be `true`

View File

@ -96,7 +96,13 @@ page for more detailed information.
(0)-(3) Follow the steps (0)-(3) of [build/install/run](#to-buildinstallrun)
section.
(4) Set up Quick Settings tile for System Tracing app on your device. Follow the
(4) Enable platform tracing.
```
adb shell setprop debug.tflite.trace 1
```
(5) Set up Quick Settings tile for System Tracing app on your device. Follow the
[instruction](https://developer.android.com/topic/performance/tracing/on-device#set-up-tile).
The System Tracing tile will be added to the Quick Settings panel.
@ -105,20 +111,20 @@ Refer to the
[guide](https://developer.android.com/topic/performance/tracing/on-device#app-menu)
for more information.
(5) Tap the System Tracing tile, which has the label "Record trace". The tile
(6) Tap the System Tracing tile, which has the label "Record trace". The tile
becomes enabled, and a persistent notification appears to notify you that the
system is now recording a trace.
(6) Run the benchmark with platform tracing enabled.
(7) Run the benchmark with platform tracing enabled.
```
adb shell am start -S \
-n org.tensorflow.lite.benchmark/.BenchmarkModelActivity \
--es args '"--graph=/data/local/tmp/mobilenet_quant_v1_224.tflite \
--num_threads=4 --enable_op_profiling=true --enable_platform_tracing=true"'
--num_threads=4"'
```
(7) Wait until the benchmark finishes. It can be checked from Android log
(8) Wait until the benchmark finishes. It can be checked from Android log
messages, e.g.,
```
@ -127,14 +133,14 @@ adb logcat | grep "Average inference"
... tflite : Average inference timings in us: Warmup: 91471, Init: 4108, Inference: 80660.1
```
(8) Stop tracing by tapping either the System Tracing tile in the Quick Settings
(9) Stop tracing by tapping either the System Tracing tile in the Quick Settings
panel or on the System Tracing notification. The system displays a new
notification that contains the message "Saving trace". When saving is complete,
the system dismisses the notification and displays a third notification "Trace
saved", confirming that your trace has been saved and that you're ready to share
the system trace.
(9)
(10)
[Share](https://developer.android.com/topic/performance/tracing/on-device#share-trace)
a trace file,
[convert](https://developer.android.com/topic/performance/tracing/on-device#converting_between_trace_formats)
@ -143,3 +149,9 @@ between tracing formats and
an HTML report. Note that, the captured tracing file format is either in
Perfetto format or in Systrace format depending on the Android version of your
device. Select the appropriate method to handle the generated file.
(11) Disable platform tracing.
```
adb shell setprop debug.tflite.trace 0
```

View File

@ -34,7 +34,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/op_resolver.h"
#include "tensorflow/lite/profiling/platform_profiler.h"
#include "tensorflow/lite/profiling/profile_summary_formatter.h"
#include "tensorflow/lite/string_util.h"
#include "tensorflow/lite/tools/benchmark/benchmark_utils.h"
@ -61,20 +60,6 @@ constexpr int kOpProfilingEnabledDefault = true;
constexpr int kOpProfilingEnabledDefault = false;
#endif
// Dumps platform-wide tracing files via a platform-based profiler that's built
// upon platform tracing tools, like ATrace on Android etc.
class PlatformProfilingListener : public BenchmarkListener {
public:
explicit PlatformProfilingListener(Interpreter* interpreter) {
TFLITE_TOOLS_CHECK(interpreter);
platform_profiler_ = profiling::CreatePlatformProfiler();
interpreter->SetProfiler(platform_profiler_.get());
}
private:
std::unique_ptr<tflite::Profiler> platform_profiler_;
};
// Dumps ruy profiling events if the ruy profiler is enabled.
class RuyProfileListener : public BenchmarkListener {
public:
@ -269,8 +254,6 @@ BenchmarkParams BenchmarkTfLiteModel::DefaultParams() {
BenchmarkParam::Create<int32_t>(1024));
default_params.AddParam("profiling_output_csv_file",
BenchmarkParam::Create<std::string>(""));
default_params.AddParam("enable_platform_tracing",
BenchmarkParam::Create<bool>(false));
for (const auto& delegate_provider :
tools::GetRegisteredDelegateProviders()) {
@ -331,10 +314,7 @@ std::vector<Flag> BenchmarkTfLiteModel::GetFlags() {
CreateFlag<std::string>(
"profiling_output_csv_file", &params_,
"File path to export profile data as CSV, if not set "
"prints to stdout."),
CreateFlag<bool>("enable_platform_tracing", &params_,
"enable platform-wide tracing, only meaningful when "
"--enable_op_profiling is set to true.")};
"prints to stdout.")};
flags.insert(flags.end(), specific_flags.begin(), specific_flags.end());
@ -369,8 +349,6 @@ void BenchmarkTfLiteModel::LogParams() {
"Max profiling buffer entries", verbose);
LOG_BENCHMARK_PARAM(std::string, "profiling_output_csv_file",
"CSV File to export profiling data to", verbose);
LOG_BENCHMARK_PARAM(bool, "enable_platform_tracing",
"Enable platform-wide tracing", verbose);
for (const auto& delegate_provider :
tools::GetRegisteredDelegateProviders()) {
@ -746,11 +724,6 @@ std::unique_ptr<BenchmarkListener>
BenchmarkTfLiteModel::MayCreateProfilingListener() const {
if (!params_.Get<bool>("enable_op_profiling")) return nullptr;
if (params_.Get<bool>("enable_platform_tracing")) {
return std::unique_ptr<BenchmarkListener>(
new PlatformProfilingListener(interpreter_.get()));
}
return std::unique_ptr<BenchmarkListener>(new ProfilingListener(
interpreter_.get(), params_.Get<int32_t>("max_profiling_buffer_entries"),
params_.Get<std::string>("profiling_output_csv_file"),