mirror of
https://github.com/google/benchmark.git
synced 2025-01-29 05:10:19 +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_
|
#ifndef COMPLEXITY_H_
|
||||||
#define COMPLEXITY_H_
|
#define COMPLEXITY_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace benchmark {
|
namespace benchmark {
|
||||||
|
|
||||||
@ -19,24 +38,34 @@ enum BigO {
|
|||||||
oAuto
|
oAuto
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string GetBigO(BigO complexity) {
|
// This data structure will contain the result returned by MinimalLeastSq
|
||||||
switch (complexity) {
|
// - coef : Estimated coeficient for the high-order term as
|
||||||
case oN:
|
// interpolated from data.
|
||||||
return "* N";
|
// - rms : Normalized Root Mean Squared Error.
|
||||||
case oNSquared:
|
// - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability
|
||||||
return "* N**2";
|
// form has been provided to MinimalLeastSq this will return
|
||||||
case oNCubed:
|
// the same value. In case BigO::oAuto has been selected, this
|
||||||
return "* N**3";
|
// parameter will return the best fitting curve detected.
|
||||||
case oLogN:
|
|
||||||
return "* lgN";
|
struct LeastSq {
|
||||||
case oNLogN:
|
LeastSq() :
|
||||||
return "* NlgN";
|
coef(0),
|
||||||
case o1:
|
rms(0),
|
||||||
return "* 1";
|
complexity(benchmark::oNone) {}
|
||||||
default:
|
|
||||||
return "";
|
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
|
} // end namespace benchmark
|
||||||
#endif // COMPLEXITY_H_
|
#endif // COMPLEXITY_H_
|
||||||
|
@ -5,7 +5,7 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
|
|||||||
set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc"
|
set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc"
|
||||||
"console_reporter.cc" "csv_reporter.cc" "json_reporter.cc"
|
"console_reporter.cc" "csv_reporter.cc" "json_reporter.cc"
|
||||||
"log.cc" "reporter.cc" "sleep.cc" "string_util.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
|
# Determine the correct regular expression engine to use
|
||||||
if(HAVE_STD_REGEX)
|
if(HAVE_STD_REGEX)
|
||||||
set(RE_FILES "re_std.cc")
|
set(RE_FILES "re_std.cc")
|
||||||
|
@ -15,43 +15,45 @@
|
|||||||
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
|
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
|
||||||
// Adapted to be used with google benchmark
|
// Adapted to be used with google benchmark
|
||||||
|
|
||||||
#include "minimal_leastsq.h"
|
#include "benchmark/complexity.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace benchmark {
|
||||||
|
|
||||||
// Internal function to calculate the different scalability forms
|
// 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) {
|
switch (complexity) {
|
||||||
case benchmark::oN:
|
case oN:
|
||||||
return [](int n) {return n; };
|
return [](int n) {return n; };
|
||||||
case benchmark::oNSquared:
|
case oNSquared:
|
||||||
return [](int n) {return n*n; };
|
return [](int n) {return n*n; };
|
||||||
case benchmark::oNCubed:
|
case oNCubed:
|
||||||
return [](int n) {return n*n*n; };
|
return [](int n) {return n*n*n; };
|
||||||
case benchmark::oLogN:
|
case oLogN:
|
||||||
return [](int n) {return log2(n); };
|
return [](int n) {return log2(n); };
|
||||||
case benchmark::oNLogN:
|
case oNLogN:
|
||||||
return [](int n) {return n * log2(n); };
|
return [](int n) {return n * log2(n); };
|
||||||
case benchmark::o1:
|
case o1:
|
||||||
default:
|
default:
|
||||||
return [](int) {return 1; };
|
return [](int) {return 1; };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal function to to return an string for the calculated complexity
|
// Function to to return an string for the calculated complexity
|
||||||
std::string GetBigOString(benchmark::BigO complexity) {
|
std::string GetBigOString(BigO complexity) {
|
||||||
switch (complexity) {
|
switch (complexity) {
|
||||||
case benchmark::oN:
|
case oN:
|
||||||
return "* N";
|
return "* N";
|
||||||
case benchmark::oNSquared:
|
case oNSquared:
|
||||||
return "* N**2";
|
return "* N**2";
|
||||||
case benchmark::oNCubed:
|
case oNCubed:
|
||||||
return "* N**3";
|
return "* N**3";
|
||||||
case benchmark::oLogN:
|
case oLogN:
|
||||||
return "* lgN";
|
return "* lgN";
|
||||||
case benchmark::oNLogN:
|
case oNLogN:
|
||||||
return "* NlgN";
|
return "* NlgN";
|
||||||
case benchmark::o1:
|
case o1:
|
||||||
return "* 1";
|
return "* 1";
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
@ -65,6 +67,16 @@ std::string GetBigOString(benchmark::BigO complexity) {
|
|||||||
// For a deeper explanation on the algorithm logic, look the README file at
|
// For a deeper explanation on the algorithm logic, look the README file at
|
||||||
// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
|
// 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,
|
LeastSq CalculateLeastSq(const std::vector<int>& n,
|
||||||
const std::vector<double>& time,
|
const std::vector<double>& time,
|
||||||
std::function<double(int)> fitting_curve) {
|
std::function<double(int)> fitting_curve) {
|
||||||
@ -110,22 +122,20 @@ LeastSq CalculateLeastSq(const std::vector<int>& n,
|
|||||||
// fitting curve.
|
// fitting curve.
|
||||||
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
LeastSq MinimalLeastSq(const std::vector<int>& n,
|
||||||
const std::vector<double>& time,
|
const std::vector<double>& time,
|
||||||
const benchmark::BigO complexity) {
|
const BigO complexity) {
|
||||||
CHECK_EQ(n.size(), time.size());
|
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_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;
|
LeastSq best_fit;
|
||||||
|
|
||||||
if(complexity == benchmark::oAuto) {
|
if(complexity == oAuto) {
|
||||||
std::vector<benchmark::BigO> fit_curves = {
|
std::vector<BigO> fit_curves = {
|
||||||
benchmark::oLogN, benchmark::oN, benchmark::oNLogN, benchmark::oNSquared,
|
oLogN, oN, oNLogN, oNSquared, oNCubed };
|
||||||
benchmark::oNCubed };
|
|
||||||
|
|
||||||
// Take o1 as default best fitting curve
|
// Take o1 as default best fitting curve
|
||||||
best_fit = CalculateLeastSq(n, time, FittingCurve(benchmark::o1));
|
best_fit = CalculateLeastSq(n, time, FittingCurve(o1));
|
||||||
best_fit.complexity = benchmark::o1;
|
best_fit.complexity = o1;
|
||||||
best_fit.caption = GetBigOString(benchmark::o1);
|
|
||||||
|
|
||||||
// Compute all possible fitting curves and stick to the best one
|
// Compute all possible fitting curves and stick to the best one
|
||||||
for (const auto& fit : fit_curves) {
|
for (const auto& fit : fit_curves) {
|
||||||
@ -133,14 +143,14 @@ LeastSq MinimalLeastSq(const std::vector<int>& n,
|
|||||||
if (current_fit.rms < best_fit.rms) {
|
if (current_fit.rms < best_fit.rms) {
|
||||||
best_fit = current_fit;
|
best_fit = current_fit;
|
||||||
best_fit.complexity = fit;
|
best_fit.complexity = fit;
|
||||||
best_fit.caption = GetBigOString(fit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
best_fit = CalculateLeastSq(n, time, FittingCurve(complexity));
|
best_fit = CalculateLeastSq(n, time, FittingCurve(complexity));
|
||||||
best_fit.complexity = complexity;
|
best_fit.complexity = complexity;
|
||||||
best_fit.caption = GetBigOString(complexity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return best_fit;
|
return best_fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace benchmark
|
@ -117,7 +117,7 @@ void ConsoleReporter::PrintRunData(const Run& result) {
|
|||||||
name_field_width_, result.benchmark_name.c_str());
|
name_field_width_, result.benchmark_name.c_str());
|
||||||
|
|
||||||
if(result.report_big_o) {
|
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 ",
|
ColorPrintf(COLOR_YELLOW, "%10.4f %s %10.4f %s ",
|
||||||
result.real_accumulated_time * multiplier,
|
result.real_accumulated_time * multiplier,
|
||||||
big_o.c_str(),
|
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.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "benchmark/reporter.h"
|
#include "benchmark/reporter.h"
|
||||||
#include "minimal_leastsq.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
Loading…
Reference in New Issue
Block a user