Chain-Load: mapping helper for control-rules

writing a control-value rule for topology generation typically
involves some modulus and then arthmetic operations to map
only part of the value range to the expected output range.

These calculations are generic, noisy and error-prone.
Thus introduce a helper type, which allows the client just
to mark up the target range of the provided value to map and
transform to the actually expected result range, including some
slight margin to absorb rounding errors. Moreover, all calculations
done in double, to avoid the perils of unsigned-wrap-around.
This commit is contained in:
Fischlurch 2023-11-16 21:38:06 +01:00
parent cc56117574
commit 686b98ff1e
2 changed files with 81 additions and 7 deletions

View file

@ -88,6 +88,7 @@
#include "lib/iter-explorer.hpp" #include "lib/iter-explorer.hpp"
#include "lib/format-cout.hpp" #include "lib/format-cout.hpp"
#include "lib/dot-gen.hpp" #include "lib/dot-gen.hpp"
#include "lib/util.hpp"
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <functional> #include <functional>
@ -110,7 +111,9 @@ namespace test {
// using lib::time::FSecs; // using lib::time::FSecs;
// using lib::time::Offset; // using lib::time::Offset;
// using lib::meta::RebindVariadic; // using lib::meta::RebindVariadic;
using util::min;
using util::max; using util::max;
using util::limited;
using util::unConst; using util::unConst;
using util::toString; using util::toString;
using util::showHashLSB; using util::showHashLSB;
@ -125,9 +128,38 @@ namespace test {
namespace { // Default definitions for topology generation namespace { // Default definitions for topology generation
const size_t DEFAULT_FAN = 16; const size_t DEFAULT_FAN = 16;
const size_t DEFAULT_SIZ = 256; const size_t DEFAULT_SIZ = 256;
const double CAP_EPSILON = 0.001; ///< tiny bias to absorb rounding problems
} }
/**
* Helper to cap and map to a value range.
*/
struct Cap
{
double lower{0};
double value{0};
double upper{1};
Cap(int i) : value(i){ }
Cap(size_t s) : value(s){ }
Cap(double d) : value{d}{ }
size_t
mapped (size_t scale)
{
if (value==lower)
return 0;
value -= lower;
value /= upper-lower;
value *= scale;
value += CAP_EPSILON;
value = limited (size_t(0), value, scale);
return size_t(value);
}
};
/** /**
* A Generator for synthetic Render Jobs for Scheduler load testing. * A Generator for synthetic Render Jobs for Scheduler load testing.
@ -225,7 +257,7 @@ namespace test {
private: private:
using NodeTab = typename Node::Tab; using NodeTab = typename Node::Tab;
using NodeStorage = std::array<Node, numNodes>; using NodeStorage = std::array<Node, numNodes>;
using CtrlRule = std::function<size_t(size_t, double)>; using CtrlRule = std::function<Cap(size_t, double)>;
std::unique_ptr<NodeStorage> nodes_; std::unique_ptr<NodeStorage> nodes_;
@ -256,6 +288,28 @@ namespace test {
/* ===== topology control ===== */ /* ===== topology control ===== */
TestChainLoad&&
seedingRule (CtrlRule r)
{
seedingRule_ = r;
return move(*this);
}
TestChainLoad&&
expansionRule (CtrlRule r)
{
expansionRule_ = r;
return move(*this);
}
TestChainLoad&&
reductionRule (CtrlRule r)
{
reductionRule_ = r;
return move(*this);
}
/** /**
* Use current configuration and seed to (re)build Node connectivity. * Use current configuration and seed to (re)build Node connectivity.
*/ */
@ -283,7 +337,8 @@ namespace test {
}; };
auto apply = [&](CtrlRule& rule, Node* n) auto apply = [&](CtrlRule& rule, Node* n)
{ {
return rule (n->hash, height(level)); Cap param = rule (n->hash, height(level));
return param.mapped (maxFan);
}; };
addNode(); // prime next with root node addNode(); // prime next with root node
@ -352,12 +407,11 @@ namespace test {
Code TOP {"shape=box, style=rounded"}; Code TOP {"shape=box, style=rounded"};
Code DEFAULT{}; Code DEFAULT{};
auto nodeID = [&](Node& nn){ return size_t(&nn - &nodes_->front()); }; auto nodeID = [&](Node& n){ return size_t(&n - &nodes_->front()); };
// prepare time-level zero // prepare time-level zero
size_t level(0); size_t level(0);
auto timeLevel = scope(level); auto timeLevel = scope(level).rank("min ");
layers += timeLevel.rank("min ");
for (Node& n : allNodes()) for (Node& n : allNodes())
{ {
@ -372,13 +426,14 @@ namespace test {
if (level != n.level) if (level != n.level)
{// switch to next time-level {// switch to next time-level
layers += timeLevel;
++level; ++level;
ENSURE (level == n.level); ENSURE (level == n.level);
timeLevel = scope(level).rank("same"); timeLevel = scope(level).rank("same");
layers += timeLevel;
} }
timeLevel.add (node(i)); timeLevel.add (node(i));
} }
layers += timeLevel; // close last layer
// combine and render collected definitions as DOT-code // combine and render collected definitions as DOT-code
return digraph (nodes, layers, topology); return digraph (nodes, layers, topology);

View file

@ -95887,6 +95887,16 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699805813117" ID="ID_593874916" MODIFIED="1699805822698" TEXT="buildTopology: Grundstruktur"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699805813117" ID="ID_593874916" MODIFIED="1699805822698" TEXT="buildTopology: Grundstruktur">
<icon BUILTIN="pencil"/> <icon BUILTIN="pencil"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700163498328" ID="ID_14989689" MODIFIED="1700163505288" TEXT="CtrlRules + Infrastruktur">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700163679808" ID="ID_310818837" MODIFIED="1700166673231" TEXT="Hilfsmittel: Cap(lower, value, upper)">
<linktarget COLOR="#fdedce" DESTINATION="ID_310818837" ENDARROW="Default" ENDINCLINATION="174;13;" ID="Arrow_ID_184825307" SOURCE="ID_1054737506" STARTARROW="None" STARTINCLINATION="247;-214;"/>
<icon BUILTIN="pencil"/>
<node CREATED="1700163740200" ID="ID_499899287" MODIFIED="1700163769112" TEXT="greift ein beliebiges Intervall heraus"/>
<node CREATED="1700163771644" ID="ID_1990055220" MODIFIED="1700163816450" TEXT="transformiert per double-Arrithmetik"/>
<node CREATED="1700163817537" ID="ID_1890257970" MODIFIED="1700163833752" TEXT="kappt dann auf [0 ... maxFan]"/>
</node>
</node>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699746891934" ID="ID_1003055056" MODIFIED="1699803875494" TEXT="Node"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699746891934" ID="ID_1003055056" MODIFIED="1699803875494" TEXT="Node">
@ -96008,12 +96018,21 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node> </node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699805890752" ID="ID_604823204" MODIFIED="1699827731274" TEXT="Limitierungen einhalten"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699805890752" ID="ID_604823204" MODIFIED="1699827731274" TEXT="Limitierungen einhalten">
<icon BUILTIN="pencil"/> <icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700163524509" ID="ID_1054737506" MODIFIED="1700166665465" TEXT="Auswertung der CtrlRules sicher handhaben">
<arrowlink COLOR="#fdedce" DESTINATION="ID_310818837" ENDARROW="Default" ENDINCLINATION="174;13;" ID="Arrow_ID_184825307" STARTARROW="None" STARTINCLINATION="247;-214;"/>
<icon BUILTIN="pencil"/>
<node CREATED="1700163554337" ID="ID_467387724" MODIFIED="1700163567392" TEXT="diverse Fallen hier">
<icon BUILTIN="clanbomber"/>
</node>
<node CREATED="1700163568492" ID="ID_1902020306" MODIFIED="1700163589018" TEXT="unsigned-wrap-around"/>
<node CREATED="1700163611881" ID="ID_1655584485" MODIFIED="1700163625384" TEXT="numerische Probleme"/>
</node>
</node> </node>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699971822836" ID="ID_1118263931" MODIFIED="1700156360589" TEXT="Diagnostik"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699971822836" ID="ID_1118263931" MODIFIED="1700156360589" TEXT="Diagnostik">
<icon BUILTIN="pencil"/> <icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1699972014017" FOLDED="true" ID="ID_1464042796" MODIFIED="1700156443450" TEXT="Topologie sichtbar machen"> <node COLOR="#338800" CREATED="1699972014017" FOLDED="true" ID="ID_1464042796" MODIFIED="1700159727325" TEXT="Topologie sichtbar machen">
<linktarget COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" SOURCE="ID_1991398605" STARTARROW="None" STARTINCLINATION="787;55;"/> <linktarget COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" SOURCE="ID_1991398605" STARTARROW="None" STARTINCLINATION="787;55;"/>
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1699972026007" ID="ID_551004748" MODIFIED="1700105381375" TEXT="Idee: DOT generieren (Graphviz)"> <node COLOR="#435e98" CREATED="1699972026007" ID="ID_551004748" MODIFIED="1700105381375" TEXT="Idee: DOT generieren (Graphviz)">