Dispatcher+Scheduler: Requirement analysis and planning work

This commit is contained in:
Fischlurch 2023-05-29 04:43:10 +02:00
parent b4c0ffab25
commit 87f40c8169
9 changed files with 432 additions and 76 deletions

View file

@ -96,7 +96,7 @@ namespace time {
/** convenience shortcut: \em materialise a raw time value
* based on this grid or time axis, but returning a raw time value.
* Implemented as combination of the #gridAlign and #timeOf operations,
* Implemented as combination of the #gridPoint and #timeOf operations,
* i.e. we quantise into this scale, but transform the result back onto
* the global raw time value scale.
* @warning this operation incurs information loss. Values may be rounded

View file

@ -399,7 +399,7 @@ namespace { // implementation: basic frame quantisation....
const int64_t microScale {lib::time::TimeValue::SCALE};
// protect against numeric overflow
if (abs(time) < limit_num && microScale < limit_den)
if (abs(time) < limit_num and microScale < limit_den)
{
// safe to calculate "time * framerate"
time -= origin;
@ -425,7 +425,7 @@ lumiera_quantise_frames (gavl_time_t time, gavl_time_t origin, gavl_time_t grid)
int64_t
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate)
{
return calculate_quantisation (time,origin,framerate);
return calculate_quantisation (time, origin, framerate);
}
gavl_time_t

View file

@ -31,7 +31,7 @@
#include "steam/play/timings.hpp"
#include "vault/engine/engine-config.h"
#include "vault/engine/engine-config.hpp"
#include "lib/time/formats.hpp"
#include "lib/time/timequant.hpp"
@ -66,7 +66,7 @@ namespace play {
* in any way to the current session.
* @remarks this ctor is intended rather for testing purposes!
* Usually, when creating a play/render process,
* the actual timings \em are related to the timeline
* the actual timings _are related to the timeline_
* and the latency/speed requirements of the output.
*/
Timings::Timings (FrameRate fps)
@ -115,13 +115,6 @@ namespace play {
}
Offset
Timings::getFrameOffsetAt (TimeValue refPoint) const
{
return 1 * getFrameDurationAt (refPoint); /////////////////TODO implement a speed factor here
}
Duration
Timings::getFrameDurationAt (TimeValue refPoint) const
{
@ -183,9 +176,9 @@ namespace play {
FrameCnt
Timings::establishNextPlanningChunkStart(FrameCnt currentAnchorFrame) const
Timings::establishNextPlanningChunkStart(FrameCnt anchorFrame) const
{
TimeVar breakingPoint = grid_->timeOf(currentAnchorFrame);
TimeVar breakingPoint = grid_->timeOf(anchorFrame);
breakingPoint += getPlanningChunkDuration();
FrameCnt nextFrame = grid_->gridPoint (breakingPoint);

View file

@ -114,7 +114,6 @@ namespace play {
Time getOrigin() const;
Time getFrameStartAt (FrameCnt frameNr) const;
Offset getFrameOffsetAt (TimeValue refPoint) const;
Duration getFrameDurationAt (TimeValue refPoint) const;
Duration getFrameDurationAt (FrameCnt refFrameNr) const;
@ -141,8 +140,8 @@ namespace play {
* which is signalled by `playbackUrgency == TIMEBOUND`
* @return wall clock time to expect delivery of data
* corresponding to a frame specified relative
* to \link #getOrigin time axis origin \endlink
* @note for other playback urgencies \c Time::NEVER
* to [time axis origin](\ref #getOrigin)
* @note for other playback urgencies `Time::NEVER` is returned
*
* @warning not clear as of 1/13 if it is even possible to have such a function
* on the Timings record.
@ -161,16 +160,16 @@ namespace play {
/** establish the time point to anchor the next planning chunk,
* in accordance with #getPlanningChunkDuration
* @param currentAnchorFrame frame number where the current planning started
* @param anchorFrame frame number where the current planning chunk started
* @return number of the first frame, which is located strictly more than
* the planning chunk duration into the future
* @remarks this value is used by the frame dispatcher to create a
* follow-up planning job */
FrameCnt establishNextPlanningChunkStart(FrameCnt currentAnchorFrame) const;
FrameCnt establishNextPlanningChunkStart(FrameCnt anchorFrame) const;
/** reasonable guess of the current engine working delay.
* Frame calculation deadlines will be readjusted by that value,
* to be able to deliver in time with sufficient probability. */
* to be able to deliver in time with sufficient likeliness. */
Duration currentEngineLatency() const;

View file

@ -26,7 +26,7 @@
*/
#include "vault/engine/engine-config.h"
#include "vault/engine/engine-config.hpp"
#include "lib/time/timevalue.hpp"
#include <boost/rational.hpp>
@ -83,23 +83,3 @@ namespace engine {
}
}} // namespace vault::engine
namespace {
using vault::engine::EngineConfig;
// any C adapter functions go here...
}
extern "C" { /* ==== implementation C interface for engine configuration ======= */
gavl_time_t
lumiera_engine_get_latency ()
{
return _raw (EngineConfig::get().currentEngineLatency());
}
}//extern "C"

View file

@ -21,7 +21,7 @@
*/
/** @file engine-config.h
/** @file engine-config.hpp
** access point to configuration of engine parameters
*/
@ -31,11 +31,6 @@
#include "lib/time.h"
#ifdef __cplusplus /* ============== C++ Interface ================= */
#include "lib/time/timevalue.hpp"
#include "lib/depend.hpp"
@ -63,6 +58,8 @@ namespace engine {
* is no locking and all values are hard coded. It is conceivable to implement
* the \em access in a lock-free manner (by loosening any guarantee regarding
* the actual time point when a changed setting becomes visible)
*
* @deprecated 5/23 singleton access looks questionable; should be part of RenderEnvironmentClosure rather
*/
class EngineConfig
{
@ -101,21 +98,4 @@ namespace engine {
};
}} // namespace vault::engine
extern "C" {
#endif /* =========================== CL Interface ===================== */
/** guess of the current effective engine calculation delay */
gavl_time_t lumiera_engine_get_latency ();
#ifdef __cplusplus
}
#endif
#endif/*VAULT_ENGINE_ENGINE_CONFIG_H*/

View file

@ -98,12 +98,10 @@ namespace test {
/***************************************************************//**
* @test document and verify the engine::Dispatcher interface, used
* to translate a CalcStream into individual node jobs.
* This test covers the definition of the interface itself,
* together with the supporting types and the default
* implementation of the basic operations.
* It creates and uses a mock Dispatcher implementation.
* @test document and verify frame timing calculations, which are
* used in the Player / engine::Dispatcher, to translate a CalcStream
* into individual node jobs.
* @see TimingConstraints_test
*/
class Timings_test : public Test
{

View file

@ -7035,14 +7035,21 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin
&amp;rarr; QuantiserImpl</pre>
</div>
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" tags="Rendering spec draft" changecount="1">
<pre>//Invoke and control the time based execution of [[render jobs|RenderJob]]//
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202305290239" tags="Rendering spec draft" changecount="5">
<pre>//Invoke and control the dependency and time based execution of [[render jobs|RenderJob]]//
The Scheduler acts as the central hub in the implementation of the RenderEngine and coordinates the //processing resources// of the application. Regarding architecture, the Scheduler is located in the Vault-Layer and //running// the Scheduler is equivalent to activating the »Vault Subsystem«. An EngineFaçade acts as entrance point, providing high-level render services to other parts of the application: [[render jobs|RenderJob]] can be activated under various timing and dependency constraints. Internally, the implementation is segregated into two layers
;Layer-2: Control
:maintains a network of interconnected [[activities|RenderActivity]], tracks dependencies and observes timing constraints
;Layer-1: Invocation
:operates a low-level priority scheduling mechanism for time-bound execution of [[activities|RenderActivity]]
:coordinates a ThreadPool and dispatches the execution of individual jobs into apropriate worker threads.
:coordinates a ThreadPool and dispatches the execution of individual jobs into appropriate worker threads.
!Event based vs. time based operational control
Time bound delivery of media data is an important aspect of editing and playback -- yet other concerns are of similar importance: the ability to make optimum use of scarce resources and to complete extended processing in reasonable time, while retaining some overall responsiveness of the system. And, especially for the //final render,// it is tantamount to produce 100% correct results without any glitches -- a goal that can not be reconciled with the demand for perfect timing. These considerations alone are sufficient to indicate, that strict adherence to a pre-established calculation plan is not enough to build a viable render engine. As far as media processing is concerned, the limited I/O bandwidth is the most precious resource -- reading and writing data from persistent storage requires a lot of time, with generally unpredictable timings, necessitating asynchronous processing.
This leads to the observation that every render or playback process has to deal with rather incompatible processing patterns and trends: for one, processing has to start as soon as the event of an completed I/O-operation is published, yet on the other hand, limited computational resources must be distributed and prioritised such as to deliver the completed data as close as possible to a pre-established timing deadline, under the constraint of limited in-memory buffer capacity. The //control structure// of an render engine is thus not only a time based computation plan -- first and foremost it should be conceived as an asynchronous messaging system, with the ability however to prioritise some messages based on urgency or approaching deadlines.
The time-based ordering and prioritisation of [[render activities|RenderActivity]] is thus used as a //generic medium and agent// to support and implement complex interwoven computational tasks. On the layer-1 mentioned above, a combination of a lock-free dispatch queue is used, feeding into a single threaded priority queue organised by temporal deadlines. Most render activities are lightweight and fast updates of some state flags, while some activities are extremely long running -- and those are shifted into worker threads based on priority.
</pre>
</div>
<div title="SchedulerRequirements" modifier="Ichthyostega" created="201107080145" modified="201112171835" tags="Rendering spec draft discuss">

View file

@ -68533,7 +68533,9 @@
</html></richcontent>
</node>
<node CREATED="1681597167602" ID="ID_205208976" MODIFIED="1681597182099" TEXT="playbackUrgency = {ASAP,NICE,TIMEBOUND}"/>
<node CREATED="1681597212993" ID="ID_615732474" MODIFIED="1681597273762" TEXT="scheduledDelivery(nur TIMEBOUND) &#x2254; &#xbb;wall clock time&#xab; des Grid-Ursprungs"/>
<node CREATED="1681597212993" ID="ID_615732474" MODIFIED="1681597273762" TEXT="scheduledDelivery(nur TIMEBOUND) &#x2254; &#xbb;wall clock time&#xab; des Grid-Ursprungs">
<arrowlink COLOR="#b7376e" DESTINATION="ID_92039924" ENDARROW="Default" ENDINCLINATION="238;-13;" ID="Arrow_ID_1490237982" STARTARROW="None" STARTINCLINATION="311;12;"/>
</node>
</node>
</node>
</node>
@ -68601,6 +68603,49 @@
</node>
</node>
</node>
<node CREATED="1685235060310" ID="ID_756189610" MODIFIED="1685235066850" TEXT="Steuerung der Timings">
<node CREATED="1685235106241" ID="ID_1118252767" MODIFIED="1685235110646" TEXT="Play-Modi">
<node CREATED="1685235134174" ID="ID_1510798334" MODIFIED="1685235162850" TEXT="ASAP ( &#x2259; &#xbb;freewheeling&#xab;)"/>
<node CREATED="1685235169786" ID="ID_1115240331" MODIFIED="1685235189342" TEXT="NICE (throtteled)"/>
<node CREATED="1685235189882" ID="ID_135856225" MODIFIED="1685235193367" TEXT="TIMEBOUND">
<node CREATED="1685235194618" ID="ID_1764599911" MODIFIED="1685235198389" TEXT="normale Wiedergabe"/>
<node CREATED="1685235200025" ID="ID_138155333" MODIFIED="1685235204223" TEXT="ggfs mit Speed-Faktor"/>
<node CREATED="1685235222582" ID="ID_176647138" MODIFIED="1685235224840" TEXT="setup">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685235225842" ID="ID_92039924" MODIFIED="1685235266821" TEXT="Timings werden mit scheduledDelivery initialisiert">
<linktarget COLOR="#b7376e" DESTINATION="ID_92039924" ENDARROW="Default" ENDINCLINATION="238;-13;" ID="Arrow_ID_1490237982" SOURCE="ID_615732474" STARTARROW="None" STARTINCLINATION="311;12;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
<node CREATED="1685235111484" ID="ID_171207659" MODIFIED="1685235129154" TEXT="Umgang mit Slippage">
<node CREATED="1685235317993" ID="ID_881286142" MODIFIED="1685235327172" TEXT="M&#xf6;glichkeiten">
<node CREATED="1685235329248" ID="ID_277669126" MODIFIED="1685235371838" TEXT="Ziel-Grid verschieben (slip)"/>
<node CREATED="1685235340213" ID="ID_197210847" MODIFIED="1685235366742" TEXT="einzelne Frames fallen lassen (drop)"/>
<node CREATED="1685235373066" ID="ID_396967363" MODIFIED="1685235385412" TEXT="erkennen und anhalten (strict)"/>
</node>
<node CREATED="1685236445931" ID="ID_416061497" MODIFIED="1685236452637" TEXT="Probleme">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1685236454793" ID="ID_215956624" MODIFIED="1685236551147" TEXT="ASAP pa&#xdf;t konzeptionell nicht mit einem time-bound-Scheduler zusammen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<ul>
<li>
die Aufschl&#252;sselung nach Zeiten enth&#228;lt &#252;berall Puffer, die insgesamt zu einer Zeitverschwendung f&#252;hren
</li>
<li>
normalerweise wird das Verletzen einer Deadline als Fehler interpretiert
</li>
</ul>
</body>
</html></richcontent>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1512923672275" ID="ID_1369059082" MODIFIED="1557498707237" TEXT="Wiring"/>
<node CREATED="1512923682530" ID="ID_1204903801" MODIFIED="1557498707237" TEXT="Planning">
@ -69517,6 +69562,18 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685227587042" ID="ID_1506519459" MODIFIED="1685227597731" TEXT="EngineConfig">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685227599324" ID="ID_996861061" MODIFIED="1685227641903" TEXT="Timings verwenden einen Singleton-Zugang">
<icon BUILTIN="stop-sign"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685227615700" ID="ID_233202097" MODIFIED="1685227641889" TEXT="sollte besser in die RenderEnvironmentClosure">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685227910712" ID="ID_176838634" MODIFIED="1685227942987" TEXT="massively concurrent access">
<icon BUILTIN="clanbomber"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681425106274" ID="ID_897788253" LINK="#ID_274575596" MODIFIED="1681425285122" TEXT="engine::Job und engine::Activity neu konzipieren">
<icon BUILTIN="flag-yellow"/>
</node>
@ -73055,6 +73112,22 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<arrowlink COLOR="#fb1618" DESTINATION="ID_548686360" ENDARROW="Default" ENDINCLINATION="-27;-313;" ID="Arrow_ID_567963048" STARTARROW="None" STARTINCLINATION="-36;126;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1685231891079" ID="ID_260441580" MODIFIED="1685231911607" TEXT="Rolle des Start-Punktes (TimeAnchor) kl&#xe4;ren">
<icon BUILTIN="yes"/>
<node CREATED="1685231941823" ID="ID_1623940961" MODIFIED="1685231953912" TEXT="verankert jeden Planning-Chunk erneut">
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1685235436161" ID="ID_468996444" MODIFIED="1685235443249" TEXT="ggfs dynamisch">
<icon BUILTIN="hourglass"/>
<node CREATED="1685235444928" ID="ID_302855619" MODIFIED="1685235467177" TEXT="slip &#x27f9; die Timings nachjustieren"/>
<node CREATED="1685235468131" ID="ID_124817718" MODIFIED="1685235532934" TEXT="drop &#x27f9; den ersten noch errichbaren Frame nehmen"/>
<node CREATED="1685235541603" ID="ID_1822458773" MODIFIED="1685235553877" TEXT="strict &#x27f9; erkennen da&#xdf; die Deadline bereits gerissen ist"/>
</node>
<node CREATED="1685235561543" ID="ID_1064939356" MODIFIED="1685235568611" TEXT="Basis-Fall">
<node CREATED="1685235946749" ID="ID_639180264" LINK="#ID_92039924" MODIFIED="1685236163177" TEXT="TIMEBOUND &#x27f9; die Timings m&#xfc;ssen relativ zur Wall-Clock-Time definiert sein (+Puffer)"/>
<node CREATED="1685236006596" ID="ID_844227051" MODIFIED="1685236120369" TEXT="sonst &#x27f9; aktuelle Zeit + Puffer f&#xfc;r Latency"/>
</node>
</node>
<node CREATED="1685231918246" ID="ID_1408660753" MODIFIED="1685231930041" TEXT="stellt zugleich den Link zur Wall-Clock-Time her"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066463050" ID="ID_1613334312" MODIFIED="1685066472930" TEXT="Mock-Setup schaffen">
<icon BUILTIN="flag-yellow"/>
@ -73165,7 +73238,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685034217649" ID="ID_838263980" MODIFIED="1685034235192" TEXT="Job kann seine eigene Performance-Charakteristik beobachten">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685034217649" ID="ID_838263980" MODIFIED="1685313347479" TEXT="Job(Closure) kann eigene Performance-Charakteristik beobachten">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685034865250" ID="ID_321040814" MODIFIED="1685050866587" TEXT="Me&#xdf;punkte per TimingObservable">
<arrowlink COLOR="#8f29b2" DESTINATION="ID_1462535336" ENDARROW="Default" ENDINCLINATION="885;-44;" ID="Arrow_ID_1037995856" STARTARROW="None" STARTINCLINATION="503;38;"/>
@ -73225,6 +73298,23 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685062757986" ID="ID_1983441100" MODIFIED="1685062769556" TEXT="TimeAnchor braucht die Frame-Nr">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1685231530086" ID="ID_1373995955" MODIFIED="1685231549597" TEXT="sollte man nicht ohnehin neu re-Quantisieren?">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1685231562523" ID="ID_301732404" MODIFIED="1685231586603" TEXT="...denn das ist genau eine Basis-Operation des Grid"/>
<node CREATED="1685313146595" ID="ID_206943359" MODIFIED="1685313167055">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
im Job w&#228;re die <i>nominelle </i>Zeit gegeben
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
</node>
</node>
</node>
@ -73770,8 +73860,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1680565476652" ID="ID_1599285907" MODIFIED="1684973334977" TEXT="#1298 Definition: Render Activity verbs">
<linktarget COLOR="#fde0ca" DESTINATION="ID_1599285907" ENDARROW="Default" ENDINCLINATION="-762;53;" ID="Arrow_ID_744981346" SOURCE="ID_1591114904" STARTARROW="None" STARTINCLINATION="-1043;88;"/>
<linktarget COLOR="#fe6d01" DESTINATION="ID_1599285907" ENDARROW="Default" ENDINCLINATION="-183;0;" ID="Arrow_ID_1756942771" SOURCE="ID_495348423" STARTARROW="None" STARTINCLINATION="-502;-42;"/>
<linktarget COLOR="#fde0ca" DESTINATION="ID_1599285907" ENDARROW="Default" ENDINCLINATION="-762;53;" ID="Arrow_ID_744981346" SOURCE="ID_1591114904" STARTARROW="None" STARTINCLINATION="-1043;88;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1684980870862" ID="ID_1051551" MODIFIED="1684980899528" TEXT="Arten">
<node CREATED="1684980900575" ID="ID_1853795602" MODIFIED="1684980920474" TEXT="invoke">
@ -74256,6 +74346,315 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node CREATED="1685313728009" ID="ID_1684013116" MODIFIED="1685313732179" TEXT="Architektur">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685313733156" ID="ID_1514384511" MODIFIED="1685313753858" TEXT="Diskussion">
<icon BUILTIN="bell"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685313772507" ID="ID_1507492066" MODIFIED="1685313796574" TEXT="ist time-bound Scheduling &#xfc;berhaupt der richtige Ansatz?">
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685313801106" ID="ID_669174882" MODIFIED="1685313820436" TEXT="Gegenargumente">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1685313827404" ID="ID_428447328" MODIFIED="1685313838734" TEXT="zeitliche Planung ist nur ein Spezialfall">
<node CREATED="1685313893707" ID="ID_268317431" MODIFIED="1685313904766" TEXT="sie gilt nur f&#xfc;r normales Standard-Playback"/>
<node CREATED="1685313905448" ID="ID_1165029374" MODIFIED="1685313930314" TEXT="dynamische &#xc4;nderungen invalidieren den Plan"/>
<node CREATED="1685313932542" ID="ID_1194636220" MODIFIED="1685313974123" TEXT="Umstands-bedingte Verz&#xf6;gerungen k&#xf6;nnen nur mit Puffer aufgefangen werden"/>
<node CREATED="1685313975342" ID="ID_1745669681" MODIFIED="1685313987526" TEXT="finales Rendern ist nicht zeitgebungen"/>
<node CREATED="1685313993958" ID="ID_1955944092" MODIFIED="1685314018982" TEXT="Pufferzeiten gehen auf Kosten der Gesamtleistung"/>
<node CREATED="1685314035535" ID="ID_1997454756" MODIFIED="1685314110039" TEXT="Hintergrund-Aktivit&#xe4;ten orientieren sich an Kapazit&#xe4;t, nicht Zeit"/>
</node>
<node CREATED="1685313842284" ID="ID_184778142" MODIFIED="1685313882542" TEXT="zeitliche Planung ist starr und aufwendig in der Anpassung">
<node CREATED="1685314214380" ID="ID_30132170" MODIFIED="1685316717679" TEXT="Zeitsteuerung dient der maximalen Ressourcen-Nutzung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Zeitsteuerung funktioniert am Besten bei eigentlich entkoppelten Aktivit&#228;ten, welche ohne weitere Pr&#252;fungen und Synchronisationen starten und enden k&#246;nnen
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#8c4d64" DESTINATION="ID_1447380879" ENDARROW="Default" ENDINCLINATION="-8;-5;" ID="Arrow_ID_435946798" STARTARROW="None" STARTINCLINATION="-79;0;"/>
</node>
<node CREATED="1685314344399" ID="ID_1217096258" MODIFIED="1685314716242" TEXT="Reaktion auf externe Ereignisse ist der absolute Gegenpol einer Zeitsteuerung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Event &#10230; <b>push</b>
</p>
<p>
Zeit &#10229; <b>pull</b>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1685314380386" ID="ID_558692946" MODIFIED="1685314749243" TEXT="jede Kontext-Abh&#xe4;ngigkeit &#xfc;bersetzt sich in zus&#xe4;tzliche Latenz">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
weil au&#223;er dem zeitgetriggerten Start...
</p>
<ul>
<li>
noch zus&#228;tzlich etwas Externes gepr&#252;ft werden mu&#223;, was Varianz einf&#252;hrt
</li>
<li>
deshalb zwischen Pr&#252;fung und eigentlicher Aktion ein k&#252;nstlicher Sicherheitspuffer liegen mu&#223;
</li>
<li>
au&#223;erdem noch eine Kommunikation stattfinden mu&#223;, schlimmstenfalls &#252;ber Thread-Grenzen hinweg
</li>
</ul>
</body>
</html></richcontent>
</node>
</node>
</node>
<node CREATED="1685314776038" ID="ID_100581546" MODIFIED="1685314801303" TEXT="so gesehen &#x2014; wir haben ein Problem">
<icon BUILTIN="broken-line"/>
<node CREATED="1685315067847" ID="ID_1447380879" MODIFIED="1685316717679" TEXT="wo Ressourcen-Nutzung am Wichtigsten w&#xe4;re, ist Zeitsteuerung grade nicht optimal">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...n&#228;mlich beim <b>finalen Rendern</b>! Lumiera ist <i>darauf ausgelegt, und grade nicht als Auff&#252;hrungs-System</i>&#160;konzipiert. Und auf der anderen Seite, wenn es um zeitgebundene Wiedergabe geht, fordern wir ohnehin, den Aufwand so sehr zu reduzieren (Proxyies), da&#223; das System weit von Vollauslastung entfernt l&#228;uft
</p>
</body>
</html></richcontent>
<linktarget COLOR="#8c4d64" DESTINATION="ID_1447380879" ENDARROW="Default" ENDINCLINATION="-8;-5;" ID="Arrow_ID_435946798" SOURCE="ID_30132170" STARTARROW="None" STARTINCLINATION="-79;0;"/>
</node>
<node CREATED="1685315368175" ID="ID_212885906" MODIFIED="1685315397463" TEXT="wir haben komplett kontr&#xe4;re Anforderungen gleicherma&#xdf;en zu befriedigen">
<node CREATED="1685315468539" ID="ID_640947563" MODIFIED="1685315806051" TEXT="Playback ist h&#xe4;ufig, w&#xe4;re aber viel billiger auch zu haben">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Denn stabiler Playback erfordert zwingend zus&#228;tzliche Leistungspuffer (sofern auch nur ein kleiner Teil der Pipeline zuf&#228;llig streut). Daher steht und f&#228;llt die M&#246;glichkeit f&#252;r fl&#252;ssigen Playback damit, den Aufwand garantiert erheblich unter das Limit zu dr&#252;cken. Unter diesen Umst&#228;nden w&#252;rde meist auch Batching plus Vorlauf mit Datenpuffer gen&#252;gen
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1685315807940" ID="ID_425768150" MODIFIED="1685315984774" TEXT="zwar hilft Parllelisierung von I/O, aber genau dies (Events) pa&#xdf;t schlecht auf Zeitsteuerung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...mehr noch, da letzten Endes die amortisierte Lade-Zeit pro Frame deutlich kleiner sein mu&#223; als die Framerate, brauchen wir ehr einen ausreichenden Vorlauf und einfache Datenpuffer &#8212; zumal fl&#252;ssiger Playback ohnehin nur mit kleinen Frames funktioniert, denn die I/O-Bandbreite ist bei Weitem nicht so angewachsen, wie die Rechenleistung
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1685315996971" ID="ID_1708683391" MODIFIED="1685316323440" TEXT="Und der seltene Fall des finalen Renders verlangt eigentlich nach (parallelem) Pipelining">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
In diesem Fall verschlechtert Zeitsteuerung eigentlich die ben&#246;tigte Gesamtzeit; die optimale L&#246;sung w&#228;re hier, jeweils parallel mehrere I/O-Pipelines, und dann einige Worker nach <i>best serve</i>-Verteilung laufen zu lassen
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1685316383184" ID="ID_774329089" MODIFIED="1685316548627" TEXT="Widerspruch zwischen Events und Lastkoordination betrifft alle F&#xe4;lle">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
praktisch alle Video-Verarbeitung involviert I/O in irgendeiner Form, und mu&#223; deshalb auf Events reagieren, dann aber einen nachfolgenden festen Arbeitsaufwand gleichm&#228;&#223;ig disponieren
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1685316553665" ID="ID_1469791" MODIFIED="1685316844661" TEXT="eigentlich m&#xfc;&#xdf;ten zwei oder drei verschiedene Prozess-Arten programmiert werden">
<arrowlink COLOR="#fffac4" DESTINATION="ID_779629114" ENDARROW="Default" ENDINCLINATION="13;-20;" ID="Arrow_ID_1083704754" STARTARROW="None" STARTINCLINATION="-69;0;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1685316762484" ID="ID_779629114" MODIFIED="1685316844661" TEXT="wir nutzen Zeitsteuerung als integrierendes Agens" VSHIFT="18">
<linktarget COLOR="#fffac4" DESTINATION="ID_779629114" ENDARROW="Default" ENDINCLINATION="13;-20;" ID="Arrow_ID_1083704754" SOURCE="ID_1469791" STARTARROW="None" STARTINCLINATION="-69;0;"/>
<icon BUILTIN="idea"/>
<node CREATED="1685317008821" ID="ID_75624396" MODIFIED="1685317551995" TEXT="den zus&#xe4;tzlichen Overhead m&#xfc;ssen wir durch Parallelisierungs-Gewinn aufwiegen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
die wirklich recht komplexe Steuerung ist einzig und allein dadurch gerechtfertigt, da&#223; so lange laufende und schwer vorhersehbare Sequenzen &#252;berlappend verschachtelt werden k&#246;nnen, was bei einem strikten Pipelining oder rein Event-getriebener Verarbeitung nicht m&#246;glich w&#228;re; letztere Ans&#228;tze funktionieren nur gut bei sehr kleinen Arbeitspaketen oder bei extremer horizontaler Skalierung
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1685317084627" ID="ID_1577438401" MODIFIED="1685317709414" TEXT="es handelt sich mehr um priorisiertes Messaging, denn um Abarbeiten eines Plans">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
das hei&#223;t, die Priority-<b>Queue</b>&#160;ist das Entscheidende; das Ordnungsma&#223; darf gar nicht prim&#228;r als ein Zeitplan verstanden werden, sondern als ein Ma&#223; an aktueller Dringlichkeit
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1685317217257" ID="ID_646611844" MODIFIED="1685317967864" TEXT="eine breitere zeitliche Streuung entzerrt die Parallelisierung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Bei einem reinen Pipelining kann es zur Stau und Lastspitzen kommen, und genau dann auch zu Lock-contention. Wir sollten also die zur Integration der widerspr&#252;chlichen Anforderungen notwendigen Pufferzeiten als eine zuf&#228;llige Streuung deuten, die Lastspitzen durch Verteilung entzerrt; sofern nicht in kurzer Zeit Aktionen an <i>mehrere Threads zugleich</i>&#160; weitergegeben werden m&#252;ssen, treten auch weniger Behinderungen durch Synchronisation auf
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1685317341273" ID="ID_229695512" MODIFIED="1685318290392" TEXT="das Lesen aus der Queue soll sich nach Durchsatz steuern">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Die Implementierung sollte sich von den exakten Zeiten l&#246;sen &#8212; besser sollte stets mit reichlich Puffer gearbeitet werden, daf&#252;r aber auch eine Activity in einer gewissen Toleranzzone um den definierten Zeitpunkt herum gestartet werden k&#246;nnen. Daf&#252;r sollte im Gegenzug die Menge der jeweils aus der Queue entommenen Activities dynamisch geregelt werden, und stets nur so viel wie gut m&#246;glich getan werden. Die concurrency-Struktur sollte zum Leitma&#223; erhoben werden; idealerweise sollte stets nur <i>ein Thread abnehmen, </i>und auch das <i>nur so lange,</i>&#160; bis er wieder auf eine gr&#246;&#223;ere Aufgabe geschickt wird.
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1685319061644" ID="ID_1128872414" MODIFIED="1685320637044" TEXT="Experimente mit der Thread-Zuteilung zulassen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<b>Keinesfalls</b>&#160;sollte a priori eine bestimmte Thread-Struktur festgelegt werden! Im Besonderen auch nicht die Annahme, da&#223; es einen &#187;Scheduler-Thread&#171; gibt, welcher Aufgaben verteilt. Denn letztlich h&#228;ngen alle Leistungs-Eigenschaften an der Cache-Locality, und diese l&#228;&#223;t sich nur empirisch optimieren, denn es ist klar, da&#223; unser Daten-Durchsatz die Cache-Kapazit&#228;t insgesamt &#252;bersteigt &#8212; inwiefern sich eine einzelne CPU f&#252;r bestimmte Aufgaben &#252;berhaupt &#8222;warm laufen&#8220; kann, mu&#223; sich in der Praxis zeigen; gut m&#246;glich, da&#223; I/O-Limitierungen jedweden Cache-Efekt &#252;berdecken. Grunds&#228;tzlich sollte die M&#246;glichkeit vorgesehen werden, da&#223; <b>jeder Thread die Queue bedienen kann </b>&#8212; sowohl eingangsseitig alsauch ausgangsseitig. Nat&#252;rlich darf es stets nur ein Thread sein, der die Queue bedient; andere unt&#228;tige Threads legen sich schlafen.
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
<node CREATED="1685320663808" ID="ID_503599380" MODIFIED="1685320675723" TEXT="Struktur-Elemente">
<node CREATED="1685320702161" ID="ID_1864388669" MODIFIED="1685320717483">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>zwei</b>&#160;Queues
</p>
</body>
</html></richcontent>
<node CREATED="1685320745481" ID="ID_466578017" MODIFIED="1685320767258" TEXT="eine N-zu-M lock-free Notification-Queue"/>
<node CREATED="1685320767988" ID="ID_721193609" MODIFIED="1685320791012" TEXT="eine Priority-Queue (not threadsafe)"/>
</node>
<node CREATED="1685320802441" ID="ID_55556868" MODIFIED="1685320814574" TEXT="ein passiver Thread-Pool">
<node CREATED="1685320820564" ID="ID_1807600749" MODIFIED="1685320829082" TEXT="keine aktive Zuteilung von Aufgaben"/>
<node CREATED="1685320830000" ID="ID_4129277" MODIFIED="1685320869284" TEXT="vielmehr konkurrieren die Threads um neue Aufgaben..."/>
<node CREATED="1685320845491" ID="ID_765952143" MODIFIED="1685320859102" TEXT="legen sich aber bei Mi&#xdf;erfolg schlafen"/>
</node>
<node CREATED="1685320923317" ID="ID_1902483191" MODIFIED="1685320942314" TEXT="die Proze&#xdf;steuerung liegt jeweils bei einem Thread">
<node CREATED="1685320945310" ID="ID_1090515306" MODIFIED="1685321041735" TEXT="und zwar wer zuf&#xe4;llig als Erster ankommt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
reguliert &#252;ber ein konventionelles Lock, oder (besser) &#252;ber ein Atomic-Token mit CaS
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1685320957468" ID="ID_1385375288" MODIFIED="1685321071585" TEXT="dieser entnimmt einen Chunk an Management-Aufgaben"/>
<node CREATED="1685321072245" ID="ID_1939345018" MODIFIED="1685321083032" TEXT="entweder bis keine dringende Aufgabe mehr anliegt"/>
<node CREATED="1685321086555" ID="ID_515210134" MODIFIED="1685321101687" TEXT="oder bis eine der Aufgaben ihn l&#xe4;ngerfristig besch&#xe4;ftigt"/>
<node CREATED="1685321102626" ID="ID_1134627598" MODIFIED="1685321118300" TEXT="oder bis er ein internes Chunk-Limit aussch&#xf6;pft"/>
</node>
<node CREATED="1685321260632" ID="ID_1245306549" MODIFIED="1685321278840">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
zu den Steuerungs-Aufgaben geh&#246;rt <i>gleicherma&#223;en</i>
</p>
</body>
</html></richcontent>
<node CREATED="1685321279620" ID="ID_1359467423" MODIFIED="1685321303575" TEXT="Prio-1 : aus der Notivication-Queue neue Activities entnehmen"/>
<node CREATED="1685321306206" ID="ID_109301359" MODIFIED="1685321359515" TEXT="Prio-2 : diese Activities in die Priority-Queue einstellen"/>
<node CREATED="1685321368627" ID="ID_335558978" MODIFIED="1685321394736" TEXT="Prio-3 : von der Spitze der Priority-Queue aktuell dringende Activities abnehmen"/>
</node>
<node CREATED="1685321415479" ID="ID_1947189271" MODIFIED="1685321424565" TEXT="die Notification-Queue ist der Eingang zum System">
<node CREATED="1685321426804" ID="ID_746352881" MODIFIED="1685321444736" TEXT="hier werden grunds&#xe4;tzlich neue Activities auf den Weg geschickt"/>
<node CREATED="1685321445292" ID="ID_79914114" MODIFIED="1685321462397" TEXT="aber auch Activities rekursiv re-priorisiert"/>
</node>
<node CREATED="1685321483574" ID="ID_1477143023" MODIFIED="1685321501986" TEXT="Tile-based Activity Storage">
<node CREATED="1685321607585" ID="ID_1565711693" MODIFIED="1685321636487">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Activities werden in/aus der Notification-Queue <b>verschoben</b>
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685321654984" ID="ID_1291294754" MODIFIED="1685321668634" TEXT="geht das direkt?">
<icon BUILTIN="help"/>
</node>
<node CREATED="1685321679399" ID="ID_1492241069" MODIFIED="1685321797340" TEXT="Grund: lock-contention auf Memory-Management vermeiden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Die Koordination von Memory-Management ist ein gef&#228;hrlicher Verz&#246;gerungs-Faktor (weil sie zu einem globalen flush der Cache-Hierarchie f&#252;hren kann).
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1685321805315" ID="ID_1461293102" MODIFIED="1685321813542" TEXT="die Laufzeit f&#xfc;r Notifications ist kurz"/>
<node CREATED="1685321814058" ID="ID_1167518732" MODIFIED="1685321822805" TEXT="aber Notifications k&#xf6;nnen aus allen Threads kommen"/>
<node CREATED="1685321823825" ID="ID_135604936" MODIFIED="1685321848244" TEXT="das Konsumieren der Notifications dagegen passiert im mit der Proze&#xdf;steuerung"/>
<node CREATED="1685321848944" ID="ID_1429281514" MODIFIED="1685321863381" TEXT="und diese wird chunk-wise single-threaded ausgef&#xfc;hrt"/>
<node CREATED="1685321874220" ID="ID_1713195430" MODIFIED="1685321882281" TEXT="ab diesem Punkt sind Activities langlebig"/>
</node>
</node>
<node CREATED="1685321970159" ID="ID_1733911974" MODIFIED="1685321991606" TEXT="Activities m&#xfc;ssen bis zu ihrer Abarbeitung erhalten bleiben"/>
<node CREATED="1685322001687" ID="ID_1323039724" MODIFIED="1685322028521" TEXT="da sie sich benachrichtigen k&#xf6;nnen, brauchen sie stabile Adressen">
<node CREATED="1685322042500" ID="ID_150807049" MODIFIED="1685322061645" TEXT="Vorsicht: das widerspricht dem Verschieben durch die Eingangsqueue"/>
<node CREATED="1685322088414" ID="ID_1024187625" MODIFIED="1685322105261" TEXT="es sei denn, man verwendet zun&#xe4;cht symbolische Referenzen"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1680563509728" ID="ID_1883500842" MODIFIED="1684869810400" TEXT="Scheduler">
<icon BUILTIN="stop"/>
<node CREATED="1680563512563" ID="ID_960191744" MODIFIED="1680563516470" TEXT="Layer-2"/>