mirror of
https://github.com/google/benchmark.git
synced 2025-01-16 06:40:13 +08:00
refactor leastsq into complexity
This commit is contained in:
parent
087f0d3f1b
commit
2f61f8aee0
@ -1,7 +1,26 @@
|
||||
// Copyright 2016 Ismael Jimenez Martinez. 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.
|
||||
|
||||
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
|
||||
// Adapted to be used with google benchmark
|
||||
|
||||
#ifndef COMPLEXITY_H_
|
||||
#define COMPLEXITY_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
@ -19,24 +38,34 @@ enum BigO {
|
||||
oAuto
|
||||
};
|
||||
|
||||
inline std::string GetBigO(BigO complexity) {
|
||||
switch (complexity) {
|
||||
case oN:
|
||||
return "* N";
|
||||
case oNSquared:
|
||||
return "* N**2";
|
||||
case oNCubed:
|
||||
return "* N**3";
|
||||
case oLogN:
|
||||
return "* lgN";
|
||||
case oNLogN:
|
||||
return "* NlgN";
|
||||
case o1:
|
||||
return "* 1";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
// This data structure will contain the result returned by MinimalLeastSq
|
||||
// - coef : Estimated coeficient for the high-order term as
|
||||
// interpolated from data.
|
||||
// - rms : Normalized Root Mean Squared Error.
|
||||
// - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability
|
||||
// form has been provided to MinimalLeastSq this will return
|
||||
// the same value. In case BigO::oAuto has been selected, this
|
||||
// parameter will return the best fitting curve detected.
|
||||
|
||||
struct LeastSq {
|
||||
LeastSq() :
|
||||
coef(0),
|
||||
rms(0),
|
||||
complexity(benchmark::oNone) {}
|
||||
|
||||
double coef;
|
||||
double rms;
|
||||
benchmark::BigO complexity;
|
||||
};
|
||||
|
||||
// Function to to return an string for the calculated complexity
|
||||
std::string GetBigOString(benchmark::BigO complexity);
|
||||
|
||||
// Find the coefficient for the high-order term in the running time, by
|
||||
// minimizing the sum of squares of relative error.
|
||||
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||
const std::vector<double>& time,
|
||||
const benchmark::BigO complexity = benchmark::oAuto);
|
||||
|
||||
} // end namespace benchmark
|
||||
#endif // COMPLEXITY_H_
|
||||
|
@ -5,7 +5,7 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc"
|
||||
"console_reporter.cc" "csv_reporter.cc" "json_reporter.cc"
|
||||
"log.cc" "reporter.cc" "sleep.cc" "string_util.cc"
|
||||
"sysinfo.cc" "walltime.cc" "minimal_leastsq.cc")
|
||||
"sysinfo.cc" "walltime.cc" "complexity.cc")
|
||||
# Determine the correct regular expression engine to use
|
||||
if(HAVE_STD_REGEX)
|
||||
set(RE_FILES "re_std.cc")
|
||||
|
@ -15,43 +15,45 @@
|
||||
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
|
||||
// Adapted to be used with google benchmark
|
||||
|
||||
#include "minimal_leastsq.h"
|
||||
#include "benchmark/complexity.h"
|
||||
#include "check.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
// Internal function to calculate the different scalability forms
|
||||
std::function<double(int)> FittingCurve(benchmark::BigO complexity) {
|
||||
std::function<double(int)> FittingCurve(BigO complexity) {
|
||||
switch (complexity) {
|
||||
case benchmark::oN:
|
||||
case oN:
|
||||
return [](int n) {return n; };
|
||||
case benchmark::oNSquared:
|
||||
case oNSquared:
|
||||
return [](int n) {return n*n; };
|
||||
case benchmark::oNCubed:
|
||||
case oNCubed:
|
||||
return [](int n) {return n*n*n; };
|
||||
case benchmark::oLogN:
|
||||
case oLogN:
|
||||
return [](int n) {return log2(n); };
|
||||
case benchmark::oNLogN:
|
||||
case oNLogN:
|
||||
return [](int n) {return n * log2(n); };
|
||||
case benchmark::o1:
|
||||
case o1:
|
||||
default:
|
||||
return [](int) {return 1; };
|
||||
}
|
||||
}
|
||||
|
||||
// Internal function to to return an string for the calculated complexity
|
||||
std::string GetBigOString(benchmark::BigO complexity) {
|
||||
// Function to to return an string for the calculated complexity
|
||||
std::string GetBigOString(BigO complexity) {
|
||||
switch (complexity) {
|
||||
case benchmark::oN:
|
||||
case oN:
|
||||
return "* N";
|
||||
case benchmark::oNSquared:
|
||||
case oNSquared:
|
||||
return "* N**2";
|
||||
case benchmark::oNCubed:
|
||||
case oNCubed:
|
||||
return "* N**3";
|
||||
case benchmark::oLogN:
|
||||
case oLogN:
|
||||
return "* lgN";
|
||||
case benchmark::oNLogN:
|
||||
case oNLogN:
|
||||
return "* NlgN";
|
||||
case benchmark::o1:
|
||||
case o1:
|
||||
return "* 1";
|
||||
default:
|
||||
return "";
|
||||
@ -65,6 +67,16 @@ std::string GetBigOString(benchmark::BigO complexity) {
|
||||
// For a deeper explanation on the algorithm logic, look the README file at
|
||||
// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
|
||||
|
||||
// This interface is currently not used from the oustide, but it has been provided
|
||||
// for future upgrades. If in the future it is not needed to support Cxx03, then
|
||||
// all the calculations could be upgraded to use lambdas because they are more
|
||||
// powerful and provide a cleaner inferface than enumerators, but complete
|
||||
// implementation with lambdas will not work for Cxx03 (e.g. lack of std::function).
|
||||
// In case lambdas are implemented, the interface would be like :
|
||||
// -> Complexity([](int n) {return n;};)
|
||||
// and any arbitrary and valid equation would be allowed, but the option to calculate
|
||||
// the best fit to the most common scalability curves will still be kept.
|
||||
|
||||
LeastSq CalculateLeastSq(const std::vector<int>& n,
|
||||
const std::vector<double>& time,
|
||||
std::function<double(int)> fitting_curve) {
|
||||
@ -110,22 +122,20 @@ LeastSq CalculateLeastSq(const std::vector<int>& n,
|
||||
// fitting curve.
|
||||
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||
const std::vector<double>& time,
|
||||
const benchmark::BigO complexity) {
|
||||
const BigO complexity) {
|
||||
CHECK_EQ(n.size(), time.size());
|
||||
CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two benchmark runs are given
|
||||
CHECK_NE(complexity, benchmark::oNone);
|
||||
CHECK_NE(complexity, oNone);
|
||||
|
||||
LeastSq best_fit;
|
||||
|
||||
if(complexity == benchmark::oAuto) {
|
||||
std::vector<benchmark::BigO> fit_curves = {
|
||||
benchmark::oLogN, benchmark::oN, benchmark::oNLogN, benchmark::oNSquared,
|
||||
benchmark::oNCubed };
|
||||
if(complexity == oAuto) {
|
||||
std::vector<BigO> fit_curves = {
|
||||
oLogN, oN, oNLogN, oNSquared, oNCubed };
|
||||
|
||||
// Take o1 as default best fitting curve
|
||||
best_fit = CalculateLeastSq(n, time, FittingCurve(benchmark::o1));
|
||||
best_fit.complexity = benchmark::o1;
|
||||
best_fit.caption = GetBigOString(benchmark::o1);
|
||||
best_fit = CalculateLeastSq(n, time, FittingCurve(o1));
|
||||
best_fit.complexity = o1;
|
||||
|
||||
// Compute all possible fitting curves and stick to the best one
|
||||
for (const auto& fit : fit_curves) {
|
||||
@ -133,14 +143,14 @@ LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||
if (current_fit.rms < best_fit.rms) {
|
||||
best_fit = current_fit;
|
||||
best_fit.complexity = fit;
|
||||
best_fit.caption = GetBigOString(fit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
best_fit = CalculateLeastSq(n, time, FittingCurve(complexity));
|
||||
best_fit.complexity = complexity;
|
||||
best_fit.caption = GetBigOString(complexity);
|
||||
}
|
||||
|
||||
return best_fit;
|
||||
}
|
||||
|
||||
} // end namespace benchmark
|
@ -117,7 +117,7 @@ void ConsoleReporter::PrintRunData(const Run& result) {
|
||||
name_field_width_, result.benchmark_name.c_str());
|
||||
|
||||
if(result.report_big_o) {
|
||||
std::string big_o = result.report_big_o ? GetBigO(result.complexity) : "";
|
||||
std::string big_o = result.report_big_o ? GetBigOString(result.complexity) : "";
|
||||
ColorPrintf(COLOR_YELLOW, "%10.4f %s %10.4f %s ",
|
||||
result.real_accumulated_time * multiplier,
|
||||
big_o.c_str(),
|
||||
|
@ -1,68 +0,0 @@
|
||||
// Copyright 2016 Ismael Jimenez Martinez. 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.
|
||||
|
||||
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
|
||||
// Adapted to be used with google benchmark
|
||||
|
||||
#if !defined(MINIMAL_LEASTSQ_H_)
|
||||
#define MINIMAL_LEASTSQ_H_
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
// This data structure will contain the result returned by MinimalLeastSq
|
||||
// - coef : Estimated coeficient for the high-order term as
|
||||
// interpolated from data.
|
||||
// - rms : Normalized Root Mean Squared Error.
|
||||
// - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability
|
||||
// form has been provided to MinimalLeastSq this will return
|
||||
// the same value. In case BigO::oAuto has been selected, this
|
||||
// parameter will return the best fitting curve detected.
|
||||
|
||||
struct LeastSq {
|
||||
LeastSq() :
|
||||
coef(0),
|
||||
rms(0),
|
||||
complexity(benchmark::oNone),
|
||||
caption("") {}
|
||||
|
||||
double coef;
|
||||
double rms;
|
||||
benchmark::BigO complexity;
|
||||
std::string caption;
|
||||
};
|
||||
|
||||
// Find the coefficient for the high-order term in the running time, by
|
||||
// minimizing the sum of squares of relative error.
|
||||
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||
const std::vector<double>& time,
|
||||
const benchmark::BigO complexity = benchmark::oAuto);
|
||||
|
||||
// This interface is currently not used from the oustide, but it has been provided
|
||||
// for future upgrades. If in the future it is not needed to support Cxx03, then
|
||||
// all the calculations could be upgraded to use lambdas because they are more
|
||||
// powerful and provide a cleaner inferface than enumerators, but complete
|
||||
// implementation with lambdas will not work for Cxx03 (e.g. lack of std::function).
|
||||
// In case lambdas are implemented, the interface would be like :
|
||||
// -> Complexity([](int n) {return n;};)
|
||||
// and any arbitrary and valid equation would be allowed, but the option to calculate
|
||||
// the best fit to the most common scalability curves will still be kept.
|
||||
LeastSq CalculateLeastSq(const std::vector<int>& n,
|
||||
const std::vector<double>& time,
|
||||
std::function<double(int)> fitting_curve);
|
||||
|
||||
|
||||
#endif
|
@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "benchmark/reporter.h"
|
||||
#include "minimal_leastsq.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
Loading…
Reference in New Issue
Block a user