Create a helper lib for some utility functions in the benchmark tool.

PiperOrigin-RevId: 259910553
This commit is contained in:
Chao Mei 2019-07-25 02:34:38 -07:00 committed by TensorFlower Gardener
parent 02a4290cbd
commit 5518980ae5
6 changed files with 200 additions and 44 deletions

View File

@ -87,6 +87,7 @@ cc_library(
copts = common_copts,
deps = [
":benchmark_model_lib",
":benchmark_utils",
":logging",
"//tensorflow/lite:framework",
"//tensorflow/lite:string_util",
@ -117,6 +118,7 @@ cc_library(
copts = common_copts,
deps = [
":benchmark_params",
":benchmark_utils",
":logging",
"//tensorflow/core:stats_calculator_portable",
"//tensorflow/lite:framework",
@ -125,4 +127,27 @@ cc_library(
],
)
cc_library(
name = "benchmark_utils",
srcs = [
"benchmark_utils.cc",
],
hdrs = ["benchmark_utils.h"],
copts = common_copts,
deps = ["//tensorflow/lite/profiling:time"],
)
cc_test(
name = "benchmark_utils_test",
srcs = [
"benchmark_utils_test.cc",
],
copts = common_copts,
deps = [
":benchmark_utils",
"//tensorflow/lite/profiling:time",
"@com_google_googletest//:gtest_main",
],
)
tflite_portable_test_suite()

View File

@ -19,22 +19,9 @@ limitations under the License.
#include <sstream>
#include "tensorflow/lite/profiling/time.h"
#include "tensorflow/lite/tools/benchmark/benchmark_utils.h"
#include "tensorflow/lite/tools/benchmark/logging.h"
namespace {
void SleepForSeconds(double sleep_seconds) {
if (sleep_seconds <= 0.0) {
return;
}
// If requested, sleep between runs for an arbitrary amount of time.
// This can be helpful to determine the effect of mobile processor
// scaling and thermal throttling.
return tflite::profiling::time::SleepForMicros(
static_cast<uint64_t>(sleep_seconds * 1e6));
}
} // namespace
namespace tflite {
namespace benchmark {
using tensorflow::Stat;
@ -143,7 +130,7 @@ Stat<int64_t> BenchmarkModel::Run(int min_num_times, float min_secs,
listeners_.OnSingleRunEnd();
run_stats.UpdateStat(end_us - start_us);
SleepForSeconds(params_.Get<float>("run_delay"));
util::SleepForSeconds(params_.Get<float>("run_delay"));
now_us = profiling::time::NowMicros();
}

View File

@ -29,6 +29,7 @@ limitations under the License.
#include "tensorflow/lite/profiling/buffered_profiler.h"
#include "tensorflow/lite/profiling/profile_summarizer.h"
#include "tensorflow/lite/string_util.h"
#include "tensorflow/lite/tools/benchmark/benchmark_utils.h"
#include "tensorflow/lite/tools/benchmark/logging.h"
#include "tensorflow/lite/tools/evaluation/utils.h"
@ -119,39 +120,13 @@ void GemmlowpProfilingListener::OnBenchmarkEnd(
}
std::vector<std::string> Split(const std::string& str, const char delim) {
std::istringstream input(str);
std::vector<std::string> results;
std::string item;
while (std::getline(input, item, delim)) {
results.push_back(item);
if (!util::SplitAndParse(str, delim, &results)) {
results.clear();
}
return results;
}
template <typename T>
bool SplitAndParse(const std::string& str, char delim, std::vector<T>* values) {
std::istringstream input(str);
bool first = true;
while (!input.eof()) {
if (!first) {
char c;
input >> c;
if (c != delim) {
return false;
}
} else {
first = false;
}
T val;
input >> val;
if (!input.eof() && !input.good()) {
return false;
}
values->push_back(val);
}
return true;
}
template <typename T>
void FillRandomValue(T* ptr, int num_elements,
const std::function<T()>& random_func) {
@ -197,7 +172,7 @@ bool PopulateInputLayerInfo(
input.name = names[i];
TFLITE_BENCHMARK_CHECK(SplitAndParse(shapes[i], ',', &input.shape))
TFLITE_BENCHMARK_CHECK(util::SplitAndParse(shapes[i], ',', &input.shape))
<< "Incorrect size string specified: " << shapes[i];
for (int dim : input.shape) {
if (dim == -1) {

View File

@ -0,0 +1,37 @@
/* Copyright 2019 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/tools/benchmark/benchmark_utils.h"
#include "tensorflow/lite/profiling/time.h"
namespace tflite {
namespace benchmark {
namespace util {
void SleepForSeconds(double sleep_seconds) {
if (sleep_seconds <= 0.0) {
return;
}
// If requested, sleep between runs for an arbitrary amount of time.
// This can be helpful to determine the effect of mobile processor
// scaling and thermal throttling.
tflite::profiling::time::SleepForMicros(
static_cast<uint64_t>(sleep_seconds * 1e6));
}
} // namespace util
} // namespace benchmark
} // namespace tflite

View File

@ -0,0 +1,52 @@
/* Copyright 2019 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.
==============================================================================*/
#ifndef TENSORFLOW_LITE_TOOLS_BENCHMARK_BENCHMARK_UTILS_H_
#define TENSORFLOW_LITE_TOOLS_BENCHMARK_BENCHMARK_UTILS_H_
#include <sstream>
#include <string>
#include <vector>
namespace tflite {
namespace benchmark {
namespace util {
// A convenient function that wraps tflite::profiling::time::SleepForMicros and
// simply return if 'sleep_seconds' is negative.
void SleepForSeconds(double sleep_seconds);
// Split the 'str' according to 'delim', and store each splitted element into
// 'values'.
template <typename T>
bool SplitAndParse(const std::string& str, char delim, std::vector<T>* values) {
std::istringstream input(str);
for (std::string line; std::getline(input, line, delim);) {
std::istringstream to_parse(line);
T val;
to_parse >> val;
if (!to_parse.eof() && !to_parse.good()) {
return false;
}
values->emplace_back(val);
}
return true;
}
} // namespace util
} // namespace benchmark
} // namespace tflite
#endif // TENSORFLOW_LITE_TOOLS_BENCHMARK_BENCHMARK_UTILS_H_

View File

@ -0,0 +1,80 @@
/* 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 "tensorflow/lite/tools/benchmark/benchmark_utils.h"
#include <string>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/profiling/time.h"
namespace tflite {
namespace benchmark {
namespace {
TEST(BenchmarkHelpersTest, SleepForNegativeSeconds) {
const auto start_ts = tflite::profiling::time::NowMicros();
// The following should return immediately.
util::SleepForSeconds(-5.0);
const auto end_ts = tflite::profiling::time::NowMicros();
// As we don't have a mocked clock, we simply expect <1 sec has elapsed, which
// is admittedly not quite accurate.
EXPECT_LT(end_ts - start_ts, 1000000);
}
TEST(BenchmarkHelpersTest, SleepForSomeSeconds) {
const auto start_ts = tflite::profiling::time::NowMicros();
// The following should return after 2.0 secs
util::SleepForSeconds(2.0);
const auto end_ts = tflite::profiling::time::NowMicros();
// As we don't have a mocked clock, we simply expect >1.9 sec has elapsed.
EXPECT_GT(end_ts - start_ts, 1900000);
}
TEST(BenchmarkHelpersTest, SplitAndParseFailed) {
std::vector<int> results;
const bool splitted = util::SplitAndParse("hello;world", ';', &results);
EXPECT_FALSE(splitted);
}
TEST(BenchmarkHelpersTest, SplitAndParseString) {
std::vector<std::string> results;
const bool splitted = util::SplitAndParse("hello,world", ',', &results);
EXPECT_TRUE(splitted);
EXPECT_EQ(2, results.size());
EXPECT_EQ("hello", results[0]);
EXPECT_EQ("world", results[1]);
}
TEST(BenchmarkHelpersTest, SplitAndParseInts) {
std::vector<int> results;
const bool splitted = util::SplitAndParse("1,2", ',', &results);
EXPECT_TRUE(splitted);
EXPECT_EQ(2, results.size());
EXPECT_EQ(1, results[0]);
EXPECT_EQ(2, results[1]);
}
} // namespace
} // namespace benchmark
} // namespace tflite