diff --git a/src/lib/iter-explorer.hpp b/src/lib/iter-explorer.hpp index 92dbd897b..11effb0df 100644 --- a/src/lib/iter-explorer.hpp +++ b/src/lib/iter-explorer.hpp @@ -981,16 +981,16 @@ namespace lib { * already been exhausted. The aggregate is default-initialised at start of each group * and then the computation functor \a FAGG is invoked for each consecutive element marked * with the same _grouping value_ — and this grouping value itself is obtained by invoking - * the functor \a FGRP on each source value. No capturing or even reordering of the source - * elements takes place, rather groups are formed based on the changes of the grouping value - * over the source iterator's result sequence. + * the functor \a FGRP on each source value. All computation are performed on-the-fly. No + * capturing or reordering of the source elements takes place, rather groups are formed + * based on the changes of the grouping value over the source iterator's result sequence. * @tparam AGG data type to collect the aggregate; must be default constructible and assignable * @tparam GRP value type to indicate a group * @note while `groupFun` is adapted, the `aggFun` is _not adapted_ to the source iterator, * but expected always to take the _value type_ of the preceding iterator, i.e. `*srcIter`. * This limitation was deemed acceptable (adapting a function with several arguments would * require quite some nasty technicalities). The first argument of this `aggFun` refers - * to the accumulator by value, and thereby also implititly defines the aggregate result type. + * to the accumulator by value, and thereby also implicitly defines the aggregate result type. */ template class GroupAggregator diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index 065101877..a6d977165 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -541,16 +541,16 @@ namespace time { : Duration::NIL; } - template + template inline Offset - operator* (INT factor, Duration const& dur) + operator* (NUM factor, Duration const& dur) { return factor * Offset(dur); } - template + template inline Offset - operator* (Duration const& dur, INT factor) + operator* (Duration const& dur, NUM factor) { return factor*dur; } diff --git a/tests/vault/gear/scheduler-stress-test.cpp b/tests/vault/gear/scheduler-stress-test.cpp index 0d783226f..7aa3eac9f 100644 --- a/tests/vault/gear/scheduler-stress-test.cpp +++ b/tests/vault/gear/scheduler-stress-test.cpp @@ -329,7 +329,7 @@ namespace test { investigateWorkProcessing() { MARK_TEST_FUN - TestChainLoad<8> testLoad{64}; + TestChainLoad<8> testLoad{256}; testLoad.seedingRule(testLoad.rule().probability(0.6).minVal(2)) .pruningRule(testLoad.rule().probability(0.44)) .setSeed(55) @@ -369,7 +369,11 @@ SHOW_EXPR(loadMicros) { usec LOAD_BASE = 500us; usec BASE_EXPENSE = 200us; - double UPPER_STRESS = 8; + double UPPER_STRESS = 12; + // + double FAIL_LIMIT = 0.7; + double TRIGGER_SDEV = 0.25; + double TRIGGER_DELTA = 0.5; // uint CONCURRENCY = 4; // bool SCHED_DEPENDS = true; bool showRuns = true; @@ -377,7 +381,7 @@ SHOW_EXPR(loadMicros) auto testLoad() { - TestChainLoad<8> testLoad{64}; + TestChainLoad<8> testLoad{256}; testLoad.seedingRule(testLoad.rule().probability(0.6).minVal(2)) .pruningRule(testLoad.rule().probability(0.44)) .setSeed(55); diff --git a/tests/vault/gear/stress-test-rig.hpp b/tests/vault/gear/stress-test-rig.hpp index 72ace65dc..7488cb38d 100644 --- a/tests/vault/gear/stress-test-rig.hpp +++ b/tests/vault/gear/stress-test-rig.hpp @@ -340,7 +340,7 @@ namespace test { 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 + double TRIGGER_DELTA = 2*FAIL_LIMIT; ///< in ms : criterion-3 average delta above this limit bool showRuns = false; ///< print a line for each individual run bool showStep = true; ///< print a line for each binary search step bool showRes = true; ///< print result data diff --git a/tests/vault/gear/test-chain-load.hpp b/tests/vault/gear/test-chain-load.hpp index 4e5c7d8b2..9ca97197d 100644 --- a/tests/vault/gear/test-chain-load.hpp +++ b/tests/vault/gear/test-chain-load.hpp @@ -198,7 +198,7 @@ namespace test { const bool SCHED_NOTIFY = true; ///< explicitly set notify dispatch time to the dependency's start time. inline uint - defaultConcurr() + defaultConcurrency() { return work::Config::getDefaultComputationCapacity(); } @@ -1675,6 +1675,7 @@ namespace test { FrameRate levelSpeed_{1, SCHEDULE_LEVEL_STEP}; FrameRate planSpeed_{1, SCHEDULE_PLAN_STEP}; TimeVar nodeExpense_{SCHEDULE_NODE_STEP}; + double stressFact_{1.0}; bool schedNotify_{SCHED_NOTIFY}; bool schedDepends_{SCHED_DEPENDS}; uint blockLoadFactor_{2}; @@ -1806,7 +1807,7 @@ namespace test { getExpectedEndTime() { return _raw(startTimes_.back() - startTimes_.front() - + Duration{nodeExpense_}*chainLoad_.size()); + + Duration{nodeExpense_}*(chainLoad_.size()/stressFact_)); } @@ -1881,8 +1882,8 @@ namespace test { withAdaptedSchedule (double stressFac =1.0, uint concurrency=0) { if (not concurrency) // use hardware concurrency (#cores) by default - concurrency = defaultConcurr(); - ENSURE (isLimited (1u, concurrency, 3*defaultConcurr())); + concurrency = defaultConcurrency(); + ENSURE (isLimited (1u, concurrency, 3*defaultConcurrency())); withLevelDuration (compuLoad_->timeBase); fillAdaptedSchedule (stressFac, concurrency); return move(*this); @@ -2024,6 +2025,7 @@ namespace test { fillDefaultSchedule() { size_t numPoints = chainLoad_.topLevel()+2; + stressFact_ = 1.0; startTimes_.clear(); startTimes_.reserve (numPoints); for (size_t level=0; level 0); + stressFact_ = stressFact; size_t numPoints = chainLoad_.topLevel()+2; startTimes_.clear(); startTimes_.reserve (numPoints); startTimes_.push_back (Time::ZERO); chainLoad_.levelScheduleSequence (concurrency) - .transform([&](double scheduleFact){ return (scheduleFact/stressFact) * Offset{1,levelSpeed_};}) + .transform([&](double scheduleFact){ return (scheduleFact/stressFact_) * Offset{1,levelSpeed_};}) .effuse(startTimes_); } @@ -2048,7 +2051,7 @@ namespace test { { ENSURE (level < startTimes_.size()); return startTimes_[level] - + nodeExpense_ * nodeIDX; + + nodeExpense_ * (nodeIDX/stressFact_); } auto diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 98a9f3758..ffae2a668 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -110893,7 +110893,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -110995,9 +110997,112 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + +

+ ...das ist eine inhärente Limitierung, die ich jedoch als Grenzfall und damit nicht relevant betrachte; zum einen sind dann meistens die Laufzeiten so kurz, daß die statistischen Triggerschwellen gar nicht greifen können, und außerdem, wenn das generierte Schedule gar keine zeitliche Komponente enthält — also alle Jobs gleichzeitig starten sollen — dann läßt sich auch nichts verdichten und der binäre Suchalgorithmus konvergiert auf das erste gefundene Rand-Intervall +

+ +
+ +
+ + + + + + + + + + +

+ das ist eine im Rückblick ungeschickte Vereinfachung, die ich ganz zu Beginn für den SchedulerCtx gemacht habe; eigentlich müßte man die Implementierung jetzt wergwerfen und nochmal systematisch von Null auf neu aufbauen. Das versuche ich zu vermeiden, da es sich letztlich nur um Test / Expermental-Code handelt, und zudem gegenwärtig nur eine erste Grobeinschätzung durch die Streß-Tests gefordert ist (ich gehe davon aus, daß das ganze Test-Setup später für detailiertere Messungen ohnehin noch einmal neu implementiert werden muß, wenn wir denn auch dafür Zeit haben) +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + +

+ Die Mantisse des Double-Datentyps ist 24bit lang. Das reicht nicht, um einen 64bit-Integer fehlerfrei mit voller Genauigkeit darzustellen +

+ +
+
+ + + +
+
+
+ + + + + + + +

+ das heißt, es gibt einen Punkt ab dem die Standardabweichung deutlich ansteigt, und viele Einzel-Läufe deutlich länger brauchen +

+ +
+ +
+ + + + + + + + + + + + + + + + +

+ Er liegt tatsächlich etwas niedriger, nämlich 180µs ±5µs. Die Zahlen sind erstaunlich stabil und relativ genau, und passen auch mit dem statistischen Verhalten zusammen; insofer betrachte ich die 5.8ms Gesamtlaufzeit als einen empirischen Fakt. Und es paßt in's Bild, daß dieser Wert etwas niedriger liegt für eine lange Kette (Cache-Effekte) +

+ +
+
+
+
+ + + + +