Scheduler-test: binary search over continuous domain

- textbook implementation
- capture results from visited points
- average results form the last three points to damp statistic fluctuations
This commit is contained in:
Fischlurch 2024-01-03 22:48:49 +01:00
parent 54e489b9b6
commit bf1eac02dd
2 changed files with 148 additions and 8 deletions

View file

@ -81,6 +81,7 @@
#include "vault/gear/scheduler.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/iter-explorer.hpp"
#include "lib/meta/function.hpp"
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"//////////////////////////TODO RLY?
//#include "lib/util.hpp"
@ -99,8 +100,8 @@ namespace gear {
namespace test {
using util::_Fmt;
// using util::min;
// using util::max;
using util::min;
using util::max;
// using util::isnil;
// using util::limited;
// using util::unConst;
@ -115,7 +116,7 @@ namespace test {
// using std::string;
// using std::function;
// using std::make_pair;
using std::make_pair;
using std::make_tuple;
// using std::forward;
// using std::string;
@ -130,6 +131,71 @@ namespace test {
namespace stress_test_rig {
template<class X, class P>
struct _ValidateBinarySearchFun
{
static_assert (not sizeof(P), "Functor unsuitable for binary search. "
"Expected signature pair<bool,X>(PAR)" );
};
template<class RES, class PAR>
struct _ValidateBinarySearchFun<std::pair<bool,RES>(PAR), PAR>
{
using Result = RES;
};
template<class FUN, typename PAR>
inline auto
make_binarySearchResults()
{
using Sig = typename lib::meta::_Fun<FUN>::Sig;
using Res = typename _ValidateBinarySearchFun<Sig,PAR>::Result;
using Data = std::vector<std::pair<bool, Res>>;
return Data{};
}
template<class FUN, class CON, typename PAR>
inline auto
binarySearch_impl (FUN&& fun, CON results, PAR lower, PAR upper, PAR epsilon)
{
REQUIRE (lower <= upper);
while ((upper-lower) >= epsilon)
{
PAR div = (upper-lower) / 2;
results.emplace_back (fun(div));
bool hit = results.back().first;
if (hit)
upper = div;
else
lower = div;
}
return results;
}
template<class FUN, typename PAR>
inline auto
binarySearch_inner (FUN&& fun, PAR lower, PAR upper, PAR epsilon)
{
auto results = make_binarySearchResults<FUN,PAR>();
return binarySearch_impl(forward<FUN> (fun), results, lower,upper,epsilon);
}
template<class FUN, typename PAR>
inline auto
binarySearch_upper (FUN&& fun, PAR lower, PAR upper, PAR epsilon)
{
REQUIRE (lower <= upper);
auto results = make_binarySearchResults<FUN,PAR>();
results.emplace_back (fun(upper));
bool hit = results.back().first;
if (not hit)
{// the upper end breaks contract => search above
PAR len = (upper-lower);
lower = upper - len/10;
upper = lower + 14*len/10;
}
return binarySearch_impl(forward<FUN> (fun), results, lower,upper,epsilon);
}
/**
* Specific stress test scheme to determine the
* »breaking point« where the Scheduler starts to slip
@ -207,7 +273,30 @@ namespace test {
Res
conductBinarySearch (FUN&& runTestCase)
{
UNIMPLEMENTED ("invoke a library implementation of binary search");
auto results = binarySearch_upper (forward<FUN> (runTestCase), 0.0, CONF::UPPER_STRESS, CONF::EPSILON);
uint s = results.size();
ENSURE (s >= 2);
Res res;
auto& [sf,pf,sdev,avgD,avgT,expT] = res;
// average data over the last three steps investigated for smoothing
uint points = min (results.size(), 3u);
for (uint i=results.size()-points; i<results.size(); ++i)
{
Res resx = results[i].second;
pf += resx.percentOff;
sdev += resx.stdDev;
avgD += resx.avgDelta;
avgT += resx.avgTime;
expT += resx.expTime;
}
pf /= points;
sdev /= points;
avgD /= points;
avgT /= points;
expT /= points;
// »breaking point« stress in the middle of the last interval
sf = (results[s-1].second.stressFac + results[s-2].second.stressFac) / 2;
return res;
}
@ -273,7 +362,7 @@ namespace test {
{
configureTest (testSetup, stressFac);
auto res = runProbes (testSetup, stressFac);
return make_tuple (decideBreakPoint(res), res);
return make_pair (decideBreakPoint(res), res);
};
Res res = conductBinarySearch (move (performEvaluation));
@ -294,7 +383,9 @@ namespace test {
usec LOAD_BASE = 500us;
uint CONCURRENCY = work::Config::getDefaultComputationCapacity();
double FAIL_LIMIT = 2.0; ///< delta-limit when to count a run as failure
double EPSILON = 0.01; ///< error bound to abort binary search
double UPPER_STRESS = 0.6; ///< starting point for the upper limit, likely to fail
double FAIL_LIMIT = 2.0; ///< delta-limit when to count a run as failure
double TRIGGER_FAIL = 0.55; ///< %-fact: criterion-1 failures above this rate
double TRIGGER_SDEV = FAIL_LIMIT; ///< in ms : criterion-2 standard derivation
double TRIGGER_DELTA = 2*FAIL_LIMIT; ///< in ms : criterion-3 delta above this limit

View file

@ -107830,11 +107830,60 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1704237555914" ID="ID_1779084715" MODIFIED="1704237568213" TEXT="funktionale Konfigurations-Hooks"/>
<node CREATED="1704237569280" ID="ID_227955379" MODIFIED="1704237574469" TEXT="Basis-Setup einmischen"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1704243593362" ID="ID_1513298833" MODIFIED="1704243606440" TEXT="Statistik-Berechnung integrieren">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1704243593362" ID="ID_1513298833" MODIFIED="1704316330671" TEXT="Statistik-Berechnung integrieren">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1704243607600" ID="ID_1968188887" MODIFIED="1704243618662" TEXT="Lib-Implementierung: bin&#xe4;re Suche">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1704316333600" ID="ID_198671243" MODIFIED="1704322903614" TEXT="Basis-Algo">
<icon BUILTIN="button_ok"/>
<node CREATED="1704316348241" ID="ID_118215771" MODIFIED="1704316368237" TEXT="Parameter-Range [lower, upper]"/>
<node CREATED="1704316374393" ID="ID_1441038472" MODIFIED="1704317029516" TEXT="Invariante: test(lower) &#x2261; false &#x2227; test(upper) &#x2261; true">
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1704316425945" ID="ID_242995900" MODIFIED="1704317035203" TEXT="das wird Eingangs nicht gepr&#xfc;ft">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1704317043838" ID="ID_1366116745" MODIFIED="1704317054641" TEXT="dann stellt es jede Iteration wieder her"/>
</node>
<node CREATED="1704316569022" ID="ID_1489985848" MODIFIED="1704316590391" TEXT="Vorgabe Such-Genauigkeit &#x3b5;">
<node CREATED="1704316840481" ID="ID_1649502723" MODIFIED="1704316856915" TEXT="solange Intervall gr&#xf6;&#xdf;er, wird geteilt"/>
<node CREATED="1704316870382" ID="ID_546344675" MODIFIED="1704316917969" TEXT="sonst wird die Intervallmitte zum Ergebnis"/>
<node CREATED="1704316928158" ID="ID_208081940" MODIFIED="1704316942065" TEXT="&#x27f9; Fehler &lt; &#x3b5;"/>
</node>
<node CREATED="1704317059760" ID="ID_1022278502" MODIFIED="1704317061951" TEXT="Iteration">
<node CREATED="1704317071234" ID="ID_731227047" MODIFIED="1704317076070" TEXT="Abbruch pr&#xfc;fen"/>
<node CREATED="1704317076874" ID="ID_699422154" MODIFIED="1704317104362" TEXT="Intervall teilen: m"/>
<node CREATED="1704317083038" ID="ID_1260760369" MODIFIED="1704317115617">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Mittelpunkt <b>auswerten</b>: test(m)
</p>
</body>
</html>
</richcontent>
<node CREATED="1704317129562" ID="ID_160740709" MODIFIED="1704317166218" TEXT="true &#x27fc; [lower, m]"/>
<node CREATED="1704317167008" ID="ID_227786504" MODIFIED="1704317178064" TEXT="false &#x27fc; [m, upper]"/>
</node>
</node>
</node>
<node CREATED="1704317215639" ID="ID_250813072" MODIFIED="1704317220333" TEXT="Einstiegs-Varianten">
<node CREATED="1704317372561" ID="ID_902270424" MODIFIED="1704317376906" TEXT="lower pr&#xfc;fen">
<node CREATED="1704317242076" ID="ID_540462019" MODIFIED="1704317358168" TEXT="true &#x27fc; Intervallverschiebung+Vergr&#xf6;&#xdf;erung &#x25bd;"/>
<node CREATED="1704317389152" ID="ID_1595570689" MODIFIED="1704317398327" TEXT="sonst: upper pr&#xfc;fen"/>
</node>
<node CREATED="1704317230133" ID="ID_821454359" MODIFIED="1704317232648" TEXT="upper pr&#xfc;fen">
<node CREATED="1704317242076" ID="ID_1523564757" MODIFIED="1704317363990" TEXT="false &#x27fc; Intervallverschiebung+Vergr&#xf6;&#xdf;erung &#x25b3;"/>
<node CREATED="1704317412253" ID="ID_884069153" MODIFIED="1704317421832" TEXT="sonst Basis-Algo [lower, upper]"/>
</node>
</node>
<node CREATED="1704317427155" ID="ID_366800456" MODIFIED="1704317431566" TEXT="Datensammlung">
<node CREATED="1704317465350" ID="ID_1437456177" MODIFIED="1704317479448" TEXT="Ergebnistupel aller Auswertungen werden in einem Vector gesammelt"/>
<node CREATED="1704317540235" ID="ID_696343908" MODIFIED="1704317608812" TEXT="man kann dann das letzte Ergebnis nehmen, oder mehrere mitteln"/>
</node>
</node>
</node>
</node>