Scheduler-test: draft calculation of level-weight based schedule

...the idea is to use the sum of node weights per level
to create a schedule, which more closely reflects the distribution
of actual computation time. Hopefully such a schedule can then be
squeezed or stretched by a time factor to find out a ''breaking point'',
at which the Scheduler is no longer able to keep up.
This commit is contained in:
Fischlurch 2023-12-28 23:56:52 +01:00
parent 47ae4f237c
commit f04035a030
6 changed files with 1254 additions and 126 deletions

View file

@ -0,0 +1,909 @@
The same setup and a similar scheduler as Dump-06
Meanwhile however,
- the capacity focus has been sharpened within NEARTIME horizon
- a contention mitigation scheme was implemented, causing workers to throttle down
- the Scheduler's main entrance was refactored, so that planning jobs perform
reliably single threaded without the need for additional coordination
- notably this has the effect that the first planning chunk is now performed
already by a worker
- at the point where processing falls behind focus, the free work capacity shows up,
causing contention for a short period, but then regulating down to the required level
|
| »processSchedule«
invokeTestCase: ++------------------- invoking TEST: vault::gear::test::SchedulerService_test
Test-Load: Nodes: 64 Levels: 27 ∅Node/Level: 2.4 Forks: 9 Joins: 8
refTime(singleThr): 31.8014ms
runTime(Scheduler): 42.0706ms
+++ F7: seed(num:64)
ANCHOR=0 preRoll=6400
‖▷▷▷‖ F7: @ -6195 EMPTY
‖IGN‖ wof:8
‖SCH‖ F7: @-4528 ○ start=-6307 dead:100000
·‖ 31: @-4458 HT:-6307 -> ∘
·‖ F6: @-4459 HT:-6307 -> ∘
·‖ AE: @-4459 HT:-1195 -> ▶ -6307
·‖ 64: @-4455 HT:-6307 -> ∘
·‖ 13: @-4457 HT:-6307 -> ∘
!◆!plan...to:62 |curr=0 (max:64)
|n.(0,lev:0)
... dispose(i=0,lev:0) -> @0
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-4189 ○ start=0 dead:30000
|n.(1,lev:1)
... dispose(i=1,lev:1) -> @1000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-4103 ○ start=1000 dead:30000
|n.(2,lev:2)
... dispose(i=2,lev:2) -> @2000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-4008 ○ start=2000 dead:30000
|n.(3,lev:3)
... dispose(i=3,lev:3) -> @3000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3929 ○ start=3000 dead:30000
|n.(4,lev:4)
... dispose(i=4,lev:4) -> @4000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3846 ○ start=4000 dead:30000
|n.(5,lev:5)
... dispose(i=5,lev:5) -> @5000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3764 ○ start=5000 dead:30000
|n.(6,lev:6)
... dispose(i=6,lev:6) -> @6000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3684 ○ start=6000 dead:30000
|n.(7,lev:7)
... dispose(i=7,lev:7) -> @7000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3604 ○ start=7000 dead:30000
|n.(8,lev:8)
... dispose(i=8,lev:8) -> @8000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3520 ○ start=8000 dead:30000
|n.(9,lev:9)
... dispose(i=9,lev:9) -> @9000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3441 ○ start=9000 dead:30000
|n.(10,lev:9)
... dispose(i=10,lev:9) -> @9000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3361 ○ start=9000 dead:30000
|n.(11,lev:10)
... dispose(i=11,lev:10) -> @10000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3281 ○ start=10000 dead:30000
|n.(12,lev:10)
... dispose(i=12,lev:10) -> @10000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3199 ○ start=10000 dead:30000
|n.(13,lev:11)
... dispose(i=13,lev:11) -> @11000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3120 ○ start=11000 dead:30000
|n.(14,lev:11)
... dispose(i=14,lev:11) -> @11000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-3036 ○ start=11000 dead:30000
|n.(15,lev:12)
... dispose(i=15,lev:12) -> @12000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2956 ○ start=12000 dead:30000
|n.(16,lev:12)
... dispose(i=16,lev:12) -> @12000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2873 ○ start=12000 dead:30000
|n.(17,lev:13)
... dispose(i=17,lev:13) -> @13000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2794 ○ start=13000 dead:30000
|n.(18,lev:13)
... dispose(i=18,lev:13) -> @13000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2714 ○ start=13000 dead:30000
|n.(19,lev:14)
... dispose(i=19,lev:14) -> @14000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2636 ○ start=14000 dead:30000
|n.(20,lev:14)
... dispose(i=20,lev:14) -> @14000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2557 ○ start=14000 dead:30000
|n.(21,lev:15)
... dispose(i=21,lev:15) -> @15000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2478 ○ start=15000 dead:30000
|n.(22,lev:16)
... dispose(i=22,lev:16) -> @16000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2398 ○ start=16000 dead:30000
|n.(23,lev:17)
... dispose(i=23,lev:17) -> @17000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2317 ○ start=17000 dead:30000
|n.(24,lev:18)
... dispose(i=24,lev:18) -> @18000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2239 ○ start=18000 dead:30000
|n.(25,lev:18)
... dispose(i=25,lev:18) -> @18000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2160 ○ start=18000 dead:30000
|n.(26,lev:18)
... dispose(i=26,lev:18) -> @18000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2080 ○ start=18000 dead:30000
|n.(27,lev:18)
... dispose(i=27,lev:18) -> @18000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-2001 ○ start=18000 dead:30000
|n.(28,lev:18)
... dispose(i=28,lev:18) -> @18000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1923 ○ start=18000 dead:30000
|n.(29,lev:19)
... dispose(i=29,lev:19) -> @19000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1843 ○ start=19000 dead:30000
|n.(30,lev:19)
... dispose(i=30,lev:19) -> @19000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1764 ○ start=19000 dead:30000
|n.(31,lev:19)
... dispose(i=31,lev:19) -> @19000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1685 ○ start=19000 dead:30000
|n.(32,lev:19)
... dispose(i=32,lev:19) -> @19000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1601 ○ start=19000 dead:30000
|n.(33,lev:19)
... dispose(i=33,lev:19) -> @19000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1520 ○ start=19000 dead:30000
|n.(34,lev:20)
... dispose(i=34,lev:20) -> @20000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1441 ○ start=20000 dead:30000
|n.(35,lev:20)
... dispose(i=35,lev:20) -> @20000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1360 ○ start=20000 dead:30000
|n.(36,lev:21)
... dispose(i=36,lev:21) -> @21000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1279 ○ start=21000 dead:30000
|n.(37,lev:21)
... dispose(i=37,lev:21) -> @21000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @-1200 ○ start=21000 dead:30000
·‖ F6: @-1192 HT:-1195 -> ∘
·‖ 05: @-4458 HT:-6307 -> ∘
·‖ 79: @-4455 HT:-6307 -> ∘
·‖ 13: @-1188 HT:-1195 -> ∘
·‖ 20: @-1191 HT:-1195 -> ∘
|n.(38,lev:21)
... dispose(i=38,lev:21) -> @21000
‖•△•‖ wof:8 HT:-1195
·‖ F6: @-1123 HT:-1195 -> ∘
·‖ 13: @-1083 HT:-1195 -> ∘
·‖ 64: @-1189 HT:-1195 -> ∘
·‖ 31: @-1194 HT:-1195 -> ∘
·‖ 13: @-1014 HT:-1195 -> ∘
·‖ 13: @-961 HT:-1195 -> ∘
·‖ 64: @-993 HT:-1195 -> ∘
·‖ 20: @-943 HT:-1195 -> ∘
·‖ 64: @-857 HT:-1195 -> ∘
·‖ 31: @-901 HT:-1195 -> ∘
·‖ 79: @-812 HT:-1195 -> ∘
·‖ 13: @-889 HT:-1195 -> ∘
·‖ 05: @-857 HT:-1195 -> ∘
·‖ 64: @-792 HT:-1195 -> ∘
·‖ 79: @-787 HT:-1195 -> ∘
·‖ 31: @-702 HT:-1195 -> ∘
·‖ 64: @-687 HT:-1195 -> ∘
‖SCH‖ AE: @-928 ○ start=21000 dead:30000
·‖ 79: @-644 HT:-1195 -> ∘
·‖ 31: @-613 HT:-1195 -> ∘
·‖ 05: @-617 HT:-1195 -> ∘
·‖ F6: @-591 HT:-1195 -> ∘
·‖ 05: @-543 HT:-1195 -> ∘
·‖ 05: @-516 HT:-1195 -> ∘
·‖ 31: @-519 HT:-1195 -> ∘
·‖ 20: @-504 HT:-1195 -> ∘
·‖ 79: @-481 HT:-1195 -> ∘
·‖ 20: @-460 HT:-1195 -> ∘
·‖ F6: @-481 HT:-1195 -> ∘
·‖ 20: @-440 HT:-1195 -> ∘
|n.(39,lev:22)
... dispose(i=39,lev:22) -> @22000
‖•△•‖ wof:8 HT:-1195
·‖ 13: @-405 HT:-1195 -> ∘
·‖ 64: @-360 HT:-1195 -> ∘
·‖ F6: @-405 HT:-1195 -> ∘
‖SCH‖ AE: @-322 ○ start=22000 dead:30000
·‖ 05: @-297 HT:-1195 -> ∘
|n.(40,lev:22)
... dispose(i=40,lev:22) -> @22000
‖•△•‖ wof:8 HT:-1195
·‖ 31: @-255 HT:-1195 -> ∘
·‖ 20: @-229 HT:-1195 -> ∘
·‖ 79: @-175 HT:-1195 -> ∘
‖SCH‖ AE: @-170 ○ start=22000 dead:30000
·‖ F6: @-159 HT:-1195 -> ∘
·‖ 13: @-105 HT:-1195 -> ∘
|n.(41,lev:22)
... dispose(i=41,lev:22) -> @22000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @12 ○ start=22000 dead:30000
·‖ 64: @16 HT:-1195 -> ∘
·‖ 05: @16 HT:-1195 -> ∘
|n.(42,lev:22)
... dispose(i=42,lev:22) -> @22000
·‖ 20: @91 HT:-1195 -> ∘
·‖ F6: @121 HT:-1195 -> ∘
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @152 ○ start=22000 dead:30000
|n.(43,lev:22)
·‖ 31: @183 HT:-1195 -> ∘
... dispose(i=43,lev:22) -> @22000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @281 ○ start=22000 dead:30000
|n.(44,lev:22)
·‖ 79: @340 HT:-1195 -> ∘
... dispose(i=44,lev:22) -> @22000
‖•△•‖ wof:8 HT:-1195
·‖ 13: @393 HT:-1195 -> ∘
‖SCH‖ AE: @422 ○ start=22000 dead:30000
|n.(45,lev:23)
... dispose(i=45,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @548 ○ start=23000 dead:30000
|n.(46,lev:23)
·‖ F6: @601 HT:-1195 -> ∘
... dispose(i=46,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
·‖ 20: @659 HT:-1195 -> ∘
‖SCH‖ AE: @668 ○ start=23000 dead:30000
·‖ 05: @667 HT:-1195 -> ∘
·‖ 64: @705 HT:-1195 -> ∘
|n.(47,lev:23)
... dispose(i=47,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @802 ○ start=23000 dead:30000
|n.(48,lev:23)
... dispose(i=48,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
·‖ 31: @899 HT:-1195 -> ∘
‖SCH‖ AE: @921 ○ start=23000 dead:30000
|n.(49,lev:23)
... dispose(i=49,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1038 ○ start=23000 dead:30000
|n.(50,lev:23)
... dispose(i=50,lev:23) -> @23000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1153 ○ start=23000 dead:30000
|n.(51,lev:24)
... dispose(i=51,lev:24) -> @24000
·‖ 79: @1234 HT:-1195 -> ∘
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1280 ○ start=24000 dead:30000
·‖ 13: @1295 HT:-1195 -> ∘
|n.(52,lev:24)
... dispose(i=52,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1416 ○ start=24000 dead:30000
|n.(53,lev:24)
... dispose(i=53,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1533 ○ start=24000 dead:30000
|n.(54,lev:24)
·‖ F6: @1550 HT:-1195 -> ∘
... dispose(i=54,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1649 ○ start=24000 dead:30000
|n.(55,lev:24)
·‖ 20: @1702 HT:-1195 -> ∘
... dispose(i=55,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1776 ○ start=24000 dead:30000
|n.(56,lev:24)
... dispose(i=56,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @1891 ○ start=24000 dead:30000
·‖ 05: @1890 HT:-1195 -> ∘
|n.(57,lev:24)
... dispose(i=57,lev:24) -> @24000
·‖ 64: @1982 HT:-1195 -> ∘
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2010 ○ start=24000 dead:30000
|n.(58,lev:24)
... dispose(i=58,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2126 ○ start=24000 dead:30000
|n.(59,lev:24)
... dispose(i=59,lev:24) -> @24000
·‖ 31: @2201 HT:-1195 -> ∘
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2256 ○ start=24000 dead:30000
|n.(60,lev:24)
... dispose(i=60,lev:24) -> @24000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2398 ○ start=24000 dead:30000
|n.(61,lev:25)
... dispose(i=61,lev:25) -> @25000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2520 ○ start=25000 dead:30000
|n.(62,lev:25)
... dispose(i=62,lev:25) -> @25000
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2638 ○ start=25000 dead:30000
|n.(63,lev:26)
+++ AE: Continuation(lastNode=62, levelDone=25, work_left:true)
--> AE: 🔁 Next(63..63) ▽ 17600 ...
‖•△•‖ wof:8 HT:-1195
‖SCH‖ AE: @2833 ○ start=17600 dead:100000
·‖ AE: @2869 HT:0 -> ▶ -1195
‖▷▷▷‖ AE: @ 2895 HT:0
·‖ 79: @2931 HT:0 -> ∘
·‖ AE: @2956 HT:1000 -> ▶ 0
·‖ 13: @2986 HT:1000 -> ∘
!◆! AE: @3018 ⚙ calc(i=0, lev:0)
..! AE: @3074 ⤴ (i=0)
‖PST‖ AE: @3127 ◒ start=0▹▹1000 dead:30000
·‖ AE: @3181 HT:1000 -> ▶ 1000
·‖ AE: @3209 HT:2000 -> ▶ 1000
!◆! AE: @3271 ⚙ calc(i=1, lev:1)
..! AE: @3322 ⤴ (i=1)
‖PST‖ AE: @3362 ◒ start=1000▹▹2000 dead:30000
·‖ F6: @3325 HT:3000 -> ▶ 2000
·‖ AE: @3383 HT:3000 -> ∘
·‖ AE: @3405 HT:2000 -> ∘
·‖ F6: @3409 HT:3000 -> ▶ 2000
·‖ AE: @3419 HT:3000 -> ∘
·‖ AE: @3442 HT:4000 -> ▶ 3000
!◆! F6: @3437 ⚙ calc(i=2, lev:2)
·‖ AE: @4070 HT:5000 -> ▶ 4000
..! F6: @4765 ⤴ (i=2)
‖PST‖ F6: @4798 ◒ start=2000▹▹3000 dead:30000
·‖ F6: @4818 HT:5000 -> ▶ 3000
!◆! F6: @4835 ⚙ calc(i=3, lev:3)
..! F6: @4863 ⤴ (i=3)
‖PST‖ F6: @4890 ◒ start=3000▹▹4000 dead:30000
·‖ F6: @4907 HT:5000 -> ▶ 4000
!◆! F6: @4923 ⚙ calc(i=4, lev:4)
..! F6: @4950 ⤴ (i=4)
‖PST‖ F6: @4976 ◒ start=4000▹▹5000 dead:30000
·‖ F6: @5002 HT:5000 -> ▶ 5000
·‖ F6: @5019 HT:6000 -> ▶ 5000
!◆! F6: @5035 ⚙ calc(i=5, lev:5)
..! F6: @5062 ⤴ (i=5)
‖PST‖ F6: @5088 ◒ start=5000▹▹6000 dead:30000
·‖ AE: @6069 HT:6000 -> ▶ 6000
·‖ AE: @6096 HT:7000 -> ▶ 6000
!◆! AE: @6116 ⚙ calc(i=6, lev:6)
..! AE: @6675 ⤴ (i=6)
‖PST‖ AE: @6700 ◒ start=6000▹▹7000 dead:30000
·‖ 31: @7061 HT:7000 -> ▶ 7000
·‖ 31: @7100 HT:8000 -> ▶ 7000
!◆! 31: @7120 ⚙ calc(i=7, lev:7)
·‖ 20: @8071 HT:9000 -> ▶ 8000
..! 31: @8456 ⤴ (i=7)
‖PST‖ 31: @8492 ◒ start=7000▹▹8000 dead:30000
·‖ 31: @8517 HT:9000 -> ▶ 8000
!◆! 31: @8534 ⚙ calc(i=8, lev:8)
·‖ 20: @9064 HT:9000 -> ▶ 9000
·‖ 20: @9106 HT:10000 -> ▶ 9000
..! 31: @9792 ⤴ (i=8)
‖PST‖ 31: @9819 ◒ start=8000▹▹9000 dead:30000
‖PST‖ 31: @9836 ◒ start=8000▹▹9000 dead:30000
·‖ 31: @9853 HT:9000 -> ▶ 9000
!◆! 31: @9869 ⚙ calc(i=9, lev:9)
·‖ 20: @10066 HT:10000 -> ▶ 9000
!◆! 20: @10099 ⚙ calc(i=10, lev:9)
·‖ 64: @10227 HT:10000 -> ▶ 10000
·‖ 64: @10265 HT:11000 -> ▶ 10000
·‖ 79: @10265 HT:11000 -> ∘
..! 31: @10526 ⤴ (i=9)
‖PST‖ 31: @10557 ◒ start=9000▹▹10000 dead:30000
·‖ 31: @10581 HT:11000 -> ▶ 10000
!◆! 31: @10602 ⚙ calc(i=11, lev:10)
..! 31: @10638 ⤴ (i=11)
‖PST‖ 31: @10674 ◒ start=10000▹▹11000 dead:30000
·‖ 64: @11066 HT:11000 -> ▶ 11000
·‖ F6: @11084 HT:11000 -> ∘
·‖ 64: @11102 HT:11000 -> ▶ 11000
·‖ F6: @11116 HT:11000 -> ∘
·‖ F6: @11143 HT:12000 -> ▶ 11000
!◆! 64: @11126 ⚙ calc(i=13, lev:11)
..! 64: @11203 ⤴ (i=13)
..! 20: @11202 ⤴ (i=10)
‖PST‖ 64: @11256 ◒ start=11000▹▹12000 dead:30000
‖PST‖ 20: @11298 ◒ start=9000▹▹10000 dead:30000
·‖ 20: @11336 HT:12000 -> ▶ 10000
!◆! 20: @11366 ⚙ calc(i=12, lev:10)
..! 20: @11418 ⤴ (i=12)
‖PST‖ 20: @11462 ◒ start=10000▹▹11000 dead:30000
·‖ 20: @11489 HT:12000 -> ▶ 11000
!◆! 20: @11514 ⚙ calc(i=14, lev:11)
..! 20: @11563 ⤴ (i=14)
‖PST‖ 20: @11608 ◒ start=11000▹▹12000 dead:30000
·‖ F6: @12070 HT:12000 -> ▶ 12000
·‖ AE: @12083 HT:12000 -> ∘
·‖ F6: @12107 HT:12000 -> ▶ 12000
·‖ AE: @12115 HT:12000 -> ∘
·‖ AE: @12154 HT:12000 -> ▶ 12000
!◆! F6: @12140 ⚙ calc(i=15, lev:12)
!◆! AE: @12190 ⚙ calc(i=16, lev:12)
·‖ 20: @12264 HT:13000 -> ▶ 12000
·‖ 20: @13066 HT:13000 -> ▶ 13000
·‖ 13: @13077 HT:13000 -> ∘
·‖ 31: @13078 HT:13000 -> ∘
·‖ 20: @13098 HT:14000 -> ▶ 13000
..! AE: @13100 ⤴ (i=16)
‖PST‖ AE: @13156 ◒ start=12000▹▹13000 dead:30000
·‖ AE: @13191 HT:14000 -> ▶ 13000
..! F6: @13211 ⤴ (i=15)
!◆! AE: @13217 ⚙ calc(i=18, lev:13)
‖PST‖ F6: @13289 ◒ start=12000▹▹13000 dead:30000
·‖ F6: @13320 HT:14000 -> ▶ 13000
!◆! F6: @13347 ⚙ calc(i=17, lev:13)
..! AE: @14035 ⤴ (i=18)
‖PST‖ AE: @14078 ◒ start=13000▹▹14000 dead:30000
·‖ 20: @14069 HT:14000 -> ▶ 14000
·‖ AE: @14108 HT:14000 -> ∘
·‖ 20: @14119 HT:14000 -> ▶ 14000
·‖ AE: @14132 HT:14000 -> ∘
·‖ 20: @14150 HT:15000 -> ▶ 14000
!◆! 20: @14179 ⚙ calc(i=20, lev:14)
..! F6: @14386 ⤴ (i=17)
‖PST‖ F6: @14436 ◒ start=13000▹▹14000 dead:30000
·‖ F6: @14466 HT:15000 -> ▶ 14000
·‖ 31: @14468 HT:15000 -> ∘
·‖ 13: @14468 HT:15000 -> ∘
!◆! F6: @14504 ⚙ calc(i=19, lev:14)
·‖ AE: @15066 HT:16000 -> ▶ 15000
·‖ 13: @16070 HT:17000 -> ▶ 16000
..! 20: @16185 ⤴ (i=20)
‖PST‖ 20: @16238 ◒ start=14000▹▹15000 dead:30000
·‖ 64: @16272 HT:17000 -> ∘
·‖ 20: @16269 HT:17000 -> ▶ 15000
..! F6: @16466 ⤴ (i=19)
‖PST‖ F6: @16506 ◒ start=14000▹▹15000 dead:30000
·‖ F6: @16528 HT:17000 -> ▶ 15000
!◆! F6: @16548 ⚙ calc(i=21, lev:15)
..! F6: @16582 ⤴ (i=21)
‖PST‖ F6: @16614 ◒ start=15000▹▹16000 dead:30000
·‖ F6: @16634 HT:17000 -> ▶ 16000
!◆! F6: @16654 ⚙ calc(i=22, lev:16)
·‖ 13: @17141 HT:17600 -> ▶ 17000
..! F6: @17426 ⤴ (i=22)
‖PST‖ F6: @17462 ◒ start=16000▹▹17000 dead:30000
·‖ F6: @17486 HT:17600 -> ▶ 17000
!◆! F6: @17506 ⚙ calc(i=23, lev:17)
·‖ 79: @17645 HT:18000 -> ▶ 17600
!◆!plan...to:63 |curr=63 (max:64)
|n.(63,lev:26)
... dispose(i=63,lev:26) -> @26000
‖•△•‖ wof:8 HT:18000
‖SCH‖ 79: @17955 ○ start=26000 dead:30000
·‖ 13: @18001 HT:18000 -> ∘
·‖ AE: @18002 HT:18000 -> ∘
·‖ 64: @18003 HT:18000 -> ∘
·‖ 05: @18030 HT:18000 -> ∘
+++ 79: Continuation(lastNode=63, levelDone=26, work_left:false)
·‖ 05: @18063 HT:18000 -> ∘
·‖ 20: @18029 HT:18000 -> ∘
·‖ 13: @18093 HT:18000 -> ∘
·‖ 20: @18117 HT:18000 -> ∘
·‖ 20: @18152 HT:18000 -> ∘
·‖ 64: @18171 HT:18000 -> ∘
·‖ AE: @18039 HT:18000 -> ∘
·‖ 64: @18217 HT:18000 -> ∘
·‖ 13: @18225 HT:18000 -> ∘
·‖ AE: @18245 HT:18000 -> ∘
·‖ 20: @18181 HT:18000 -> ∘
·‖ 31: @18005 HT:18000 -> ∘
·‖ 64: @18317 HT:18000 -> ∘
·‖ 31: @18334 HT:18000 -> ∘
·‖ 64: @18384 HT:18000 -> ∘
·‖ 31: @18415 HT:18000 -> ∘
·‖ AE: @18443 HT:18000 -> ∘
·‖ 13: @18436 HT:18000 -> ∘
·‖ 05: @18488 HT:18000 -> ∘
·‖ AE: @18479 HT:18000 -> ∘
·‖ 31: @18510 HT:18000 -> ∘
·‖ 13: @18526 HT:18000 -> ∘
·‖ 20: @18547 HT:18000 -> ∘
·‖ 64: @18639 HT:18000 -> ∘
·‖ 31: @18646 HT:18000 -> ∘
·‖ 05: @18541 HT:18000 -> ∘
·‖ AE: @18721 HT:18000 -> ∘
·‖ 05: @18739 HT:18000 -> ∘
·‖ 20: @18805 HT:18000 -> ∘
·‖ 31: @18895 HT:18000 -> ∘
·‖ 13: @18896 HT:18000 -> ∘
·‖ 05: @18959 HT:18000 -> ∘
·‖ AE: @19023 HT:18000 -> ∘
·‖ 64: @19033 HT:18000 -> ∘
·‖ 20: @19141 HT:18000 -> ∘
·‖ 13: @19204 HT:18000 -> ∘
·‖ 31: @19240 HT:18000 -> ∘
·‖ 05: @19314 HT:18000 -> ∘
·‖ AE: @19545 HT:18000 -> ∘
‖•△•‖ wof:8 HT:18000
‖SCH‖ 79: @19589 ○ start=27000 dead:5000000
·‖ 79: @19619 HT:18000 -> ▶ 18000
·‖ 79: @19649 HT:18000 -> ▶ 18000
·‖ 79: @19675 HT:18000 -> ▶ 18000
·‖ 79: @19701 HT:18000 -> ▶ 18000
·‖ 64: @19721 HT:18000 -> ∘
·‖ 20: @19723 HT:18000 -> ∘
·‖ 13: @19714 HT:18000 -> ∘
..! F6: @19726 ⤴ (i=23)
·‖ 79: @19759 HT:19000 -> ▶ 18000
‖PST‖ F6: @19807 ◒ start=17000▹▹18000 dead:30000
‖PST‖ F6: @19826 ◒ start=17000▹▹18000 dead:30000
·‖ 79: @19818 HT:19000 -> ▶ 19000
‖PST‖ F6: @19847 ◒ start=17000▹▹18000 dead:30000
‖PST‖ F6: @19864 ◒ start=17000▹▹18000 dead:30000
·‖ 79: @19868 HT:18000 -> ▶ 18000
‖PST‖ F6: @19879 ◒ start=17000▹▹18000 dead:30000
·‖ F6: @19911 HT:18000 -> ▶ 18000
!◆! 79: @19901 ⚙ calc(i=24, lev:18)
!◆! F6: @19928 ⚙ calc(i=25, lev:18)
·‖ 31: @19932 HT:18000 -> ▶ 18000
·‖ 05: @19949 HT:18000 -> ∘
..! F6: @19986 ⤴ (i=25)
!◆! 31: @20079 ⚙ calc(i=26, lev:18)
‖PST‖ F6: @20143 ◒ start=18000▹▹19000 dead:30000
·‖ F6: @20190 HT:18000 -> ▶ 18000
..! 31: @20177 ⤴ (i=26)
!◆! F6: @20207 ⚙ calc(i=28, lev:18)
‖PST‖ 31: @20253 ◒ start=18000▹▹19000 dead:30000
..! F6: @20254 ⤴ (i=28)
..! 79: @20229 ⤴ (i=24)
‖PST‖ F6: @20300 ◒ start=18000▹▹19000 dead:30000
‖PST‖ 79: @20323 ◒ start=18000▹▹19000 dead:30000
·‖ F6: @20326 HT:19000 -> ∘
·‖ 31: @20316 HT:19000 -> ▶ 18000
·‖ F6: @20359 HT:19000 -> ∘
·‖ 79: @20359 HT:19000 -> ∘
·‖ F6: @20384 HT:19000 -> ▶ 19000
·‖ 79: @20394 HT:19000 -> ∘
·‖ F6: @20403 HT:19000 -> ▶ 19000
!◆! 31: @20372 ⚙ calc(i=27, lev:18)
·‖ F6: @20425 HT:19000 -> ▶ 19000
·‖ 79: @20425 HT:19000 -> ∘
..! 31: @20450 ⤴ (i=27)
!◆! F6: @20461 ⚙ calc(i=29, lev:19)
·‖ 79: @20497 HT:19000 -> ▶ 19000
‖PST‖ 31: @20517 ◒ start=18000▹▹19000 dead:30000
·‖ AE: @20517 HT:19000 -> ∘
·‖ 79: @20531 HT:19000 -> ▶ 19000
·‖ 31: @20555 HT:19000 -> ∘
!◆! 79: @20582 ⚙ calc(i=30, lev:19)
·‖ 13: @20636 HT:19000 -> ▶ 19000
!◆! 13: @20666 ⚙ calc(i=31, lev:19)
·‖ 20: @20815 HT:19000 -> ▶ 19000
!◆! 20: @20852 ⚙ calc(i=33, lev:19)
·‖ 31: @20956 HT:19000 -> ▶ 19000
·‖ 31: @20993 HT:20000 -> ▶ 19000
·‖ 64: @21013 HT:20000 -> ∘
!◆! 31: @21028 ⚙ calc(i=32, lev:19)
·‖ 05: @21303 HT:20000 -> ▶ 20000
·‖ 05: @21325 HT:21000 -> ▶ 20000
·‖ 05: @21344 HT:21000 -> ▶ 21000
·‖ 05: @21362 HT:21000 -> ▶ 21000
·‖ 05: @21381 HT:22000 -> ▶ 21000
..! F6: @21743 ⤴ (i=29)
‖PST‖ F6: @21775 ◒ start=19000▹▹20000 dead:30000
·‖ F6: @21797 HT:22000 -> ▶ 20000
..! 13: @21929 ⤴ (i=31)
‖PST‖ 13: @21967 ◒ start=19000▹▹20000 dead:30000
·‖ 13: @21990 HT:22000 -> ▶ 20000
·‖ 13: @22010 HT:22000 -> ▶ 22000
·‖ 13: @22030 HT:22000 -> ▶ 22000
·‖ 13: @22050 HT:22000 -> ▶ 22000
·‖ 05: @22060 HT:22000 -> ∘
·‖ 13: @22085 HT:22000 -> ▶ 22000
·‖ 05: @22109 HT:22000 -> ∘
·‖ 13: @22107 HT:22000 -> ▶ 22000
·‖ 13: @22140 HT:23000 -> ▶ 22000
..! 79: @22592 ⤴ (i=30)
‖PST‖ 79: @22643 ◒ start=19000▹▹20000 dead:30000
·‖ 79: @22675 HT:23000 -> ▶ 20000
!◆! 79: @22702 ⚙ calc(i=34, lev:20)
..! 20: @22967 ⤴ (i=33)
‖PST‖ 20: @23022 ◒ start=19000▹▹20000 dead:30000
·‖ 20: @23053 HT:23000 -> ▶ 20000
·‖ 13: @23062 HT:23000 -> ∘
·‖ 13: @23093 HT:23000 -> ∘
·‖ 20: @23086 HT:23000 -> ▶ 23000
·‖ 13: @23114 HT:23000 -> ∘
·‖ 13: @23134 HT:23000 -> ∘
·‖ 20: @23128 HT:23000 -> ▶ 23000
·‖ 13: @23159 HT:23000 -> ∘
..! 31: @23120 ⤴ (i=32)
·‖ 20: @23169 HT:23000 -> ▶ 23000
‖PST‖ 31: @23211 ◒ start=19000▹▹20000 dead:30000
·‖ 05: @23232 HT:23000 -> ∘
·‖ 20: @23215 HT:23000 -> ▶ 23000
·‖ 31: @23274 HT:23000 -> ∘
·‖ 20: @23291 HT:23000 -> ▶ 20000
!◆! 20: @23313 ⚙ calc(i=35, lev:20)
·‖ 13: @23337 HT:23000 -> ∘
·‖ AE: @23329 HT:23000 -> ▶ 23000
·‖ AE: @23386 HT:24000 -> ▶ 23000
·‖ AE: @24061 HT:24000 -> ▶ 24000
·‖ AE: @24084 HT:24000 -> ▶ 24000
·‖ AE: @24101 HT:24000 -> ▶ 24000
·‖ AE: @24117 HT:24000 -> ▶ 24000
·‖ AE: @24133 HT:24000 -> ▶ 24000
·‖ AE: @24150 HT:24000 -> ▶ 24000
·‖ AE: @24166 HT:24000 -> ▶ 24000
·‖ AE: @24182 HT:24000 -> ▶ 24000
·‖ AE: @24198 HT:24000 -> ▶ 24000
·‖ AE: @24217 HT:25000 -> ▶ 24000
·‖ 64: @24215 HT:24000 -> ∘
..! 20: @24813 ⤴ (i=35)
‖PST‖ 20: @24853 ◒ start=20000▹▹21000 dead:30000
·‖ 20: @24877 HT:25000 -> ▶ 21000
·‖ AE: @25071 HT:25000 -> ▶ 25000
·‖ 20: @25094 HT:25000 -> ∘
..! 79: @25079 ⤴ (i=34)
·‖ AE: @25101 HT:26000 -> ▶ 25000
‖PST‖ 79: @25139 ◒ start=20000▹▹21000 dead:30000
‖PST‖ 79: @25163 ◒ start=20000▹▹21000 dead:30000
‖PST‖ 79: @25181 ◒ start=20000▹▹21000 dead:30000
·‖ 79: @25201 HT:21000 -> ▶ 21000
!◆! 79: @25221 ⚙ calc(i=36, lev:21)
·‖ 13: @25448 HT:21000 -> ▶ 21000
!◆! 13: @25481 ⚙ calc(i=38, lev:21)
·‖ 05: @25644 HT:26000 -> ▶ 21000
!◆! 05: @25674 ⚙ calc(i=37, lev:21)
..! 79: @25997 ⤴ (i=36)
‖PST‖ 79: @26031 ◒ start=21000▹▹22000 dead:30000
·‖ 79: @26052 HT:26000 -> ▶ 22000
·‖ AE: @26067 HT:26000 -> ∘
!◆! 79: @26071 ⚙ calc(i=39, lev:22)
·‖ AE: @26095 HT:27000 -> ▶ 26000
..! 05: @26338 ⤴ (i=37)
‖PST‖ 05: @26368 ◒ start=21000▹▹22000 dead:30000
·‖ 05: @26390 HT:27000 -> ▶ 22000
!◆! 05: @26406 ⚙ calc(i=40, lev:22)
·‖ AE: @27062 HT:52895 -> ▶ 27000
..! 13: @27409 ⤴ (i=38)
‖PST‖ 13: @27449 ◒ start=21000▹▹22000 dead:30000
‖PST‖ 13: @27468 ◒ start=21000▹▹22000 dead:30000
‖PST‖ 13: @27483 ◒ start=21000▹▹22000 dead:30000
‖PST‖ 13: @27497 ◒ start=21000▹▹22000 dead:30000
·‖ 13: @27516 HT:22000 -> ▶ 22000
!◆! 13: @27532 ⚙ calc(i=41, lev:22)
..! 13: @27561 ⤴ (i=41)
‖PST‖ 13: @27587 ◒ start=22000▹▹23000 dead:30000
·‖ 13: @27604 HT:22000 -> ▶ 22000
!◆! 13: @27620 ⚙ calc(i=42, lev:22)
..! 13: @27647 ⤴ (i=42)
‖PST‖ 13: @27673 ◒ start=22000▹▹23000 dead:30000
·‖ 13: @27689 HT:22000 -> ∘
·‖ 13: @27703 HT:22000 -> ∘
·‖ 31: @27678 HT:22000 -> ▶ 22000
·‖ 13: @27718 HT:22000 -> ∘
·‖ 13: @27751 HT:23000 -> ▶ 22000
!◆! 13: @27768 ⚙ calc(i=43, lev:22)
..! 13: @27796 ⤴ (i=43)
!◆! 31: @27746 ⚙ calc(i=44, lev:22)
‖PST‖ 13: @27829 ◒ start=22000▹▹23000 dead:30000
·‖ 13: @27869 HT:23000 -> ▶ 23000
·‖ 13: @27885 HT:23000 -> ▶ 23000
..! 31: @27857 ⤴ (i=44)
·‖ 13: @27902 HT:52895 -> ▶ 23000
‖PST‖ 31: @27930 ◒ start=22000▹▹23000 dead:30000
·‖ 31: @27974 HT:52895 -> ▶ 23000
!◆! 31: @28004 ⚙ calc(i=50, lev:23)
..! 05: @28320 ⤴ (i=40)
‖PST‖ 05: @28354 ◒ start=22000▹▹23000 dead:30000
‖PST‖ 05: @28370 ◒ start=22000▹▹23000 dead:30000
‖PST‖ 05: @28384 ◒ start=22000▹▹23000 dead:30000
·‖ 05: @28402 HT:23000 -> ▶ 23000
..! 79: @28393 ⤴ (i=39)
·‖ 05: @28419 HT:23000 -> ▶ 23000
‖PST‖ 79: @28449 ◒ start=22000▹▹23000 dead:30000
!◆! 05: @28440 ⚙ calc(i=48, lev:23)
‖PST‖ 79: @28478 ◒ start=22000▹▹23000 dead:30000
‖PST‖ 79: @28512 ◒ start=22000▹▹23000 dead:30000
..! 05: @28499 ⤴ (i=48)
·‖ 79: @28537 HT:23000 -> ▶ 23000
‖PST‖ 05: @28545 ◒ start=23000▹▹24000 dead:30000
·‖ 05: @28575 HT:23000 -> ▶ 23000
!◆! 79: @28561 ⚙ calc(i=49, lev:23)
..! 79: @28609 ⤴ (i=49)
!◆! 05: @28621 ⚙ calc(i=45, lev:23)
‖PST‖ 79: @28644 ◒ start=23000▹▹24000 dead:30000
..! 05: @28667 ⤴ (i=45)
·‖ 79: @28684 HT:23000 -> ▶ 23000
‖PST‖ 05: @28701 ◒ start=23000▹▹24000 dead:30000
!◆! 79: @28705 ⚙ calc(i=47, lev:23)
·‖ 05: @28723 HT:24000 -> ▶ 23000
!◆! 05: @28767 ⚙ calc(i=46, lev:23)
..! 05: @28803 ⤴ (i=46)
‖PST‖ 05: @28835 ◒ start=23000▹▹24000 dead:30000
·‖ 05: @28855 HT:24000 -> ▶ 24000
·‖ 05: @28875 HT:24000 -> ▶ 24000
!◆! 05: @28893 ⚙ calc(i=51, lev:24)
..! 79: @30995 ⤴ (i=47)
‖PST‖ 79: @31032 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 79: @31053 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 79: @31072 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 79: @31091 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 79: @31110 ◒ start=23000▹▹24000 dead:30000
..! 31: @31094 ⤴ (i=50)
·‖ 79: @31134 HT:24000 -> ▶ 24000
..! 05: @31167 ⤴ (i=51)
!◆! 79: @31181 ⚙ calc(i=52, lev:24)
‖PST‖ 31: @31179 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 05: @31209 ◒ start=24000▹▹25000 dead:30000
‖PST‖ 31: @31260 ◒ start=23000▹▹24000 dead:30000
‖PST‖ 05: @31267 ◒ start=24000▹▹25000 dead:30000
‖PST‖ 31: @31290 ◒ start=23000▹▹24000 dead:30000
·‖ 05: @31302 HT:24000 -> ▶ 24000
‖PST‖ 31: @31316 ◒ start=23000▹▹24000 dead:30000
!◆! 05: @31324 ⚙ calc(i=55, lev:24)
·‖ 31: @31347 HT:24000 -> ▶ 24000
..! 05: @31362 ⤴ (i=55)
‖PST‖ 05: @31396 ◒ start=24000▹▹25000 dead:30000
!◆! 31: @31374 ⚙ calc(i=56, lev:24)
·‖ 05: @31418 HT:24000 -> ▶ 24000
·‖ 05: @31439 HT:24000 -> ▶ 24000
..! 31: @31430 ⤴ (i=56)
!◆! 05: @31458 ⚙ calc(i=60, lev:24)
‖PST‖ 31: @31481 ◒ start=24000▹▹25000 dead:30000
..! 05: @31499 ⤴ (i=60)
‖PST‖ 05: @31533 ◒ start=24000▹▹25000 dead:30000
·‖ 31: @31523 HT:24000 -> ▶ 24000
·‖ 05: @31556 HT:24000 -> ∘
·‖ 05: @31574 HT:24000 -> ∘
·‖ 31: @31572 HT:24000 -> ▶ 24000
·‖ 05: @31594 HT:24000 -> ∘
·‖ 05: @31620 HT:24000 -> ▶ 24000
!◆! 31: @31599 ⚙ calc(i=54, lev:24)
!◆! 05: @31643 ⚙ calc(i=58, lev:24)
..! 31: @31663 ⤴ (i=54)
..! 05: @31679 ⤴ (i=58)
‖PST‖ 31: @31714 ◒ start=24000▹▹25000 dead:30000
‖PST‖ 05: @31721 ◒ start=24000▹▹25000 dead:30000
·‖ 05: @31751 HT:24000 -> ∘
·‖ 31: @31747 HT:24000 -> ▶ 24000
·‖ 05: @31778 HT:24000 -> ▶ 24000
!◆! 31: @31779 ⚙ calc(i=59, lev:24)
!◆! 05: @31799 ⚙ calc(i=53, lev:24)
..! 31: @31837 ⤴ (i=59)
..! 05: @31851 ⤴ (i=53)
‖PST‖ 31: @31889 ◒ start=24000▹▹25000 dead:30000
‖PST‖ 05: @31896 ◒ start=24000▹▹25000 dead:30000
·‖ 05: @31926 HT:25000 -> ∘
·‖ 31: @31921 HT:25000 -> ▶ 24000
·‖ 05: @31953 HT:25000 -> ▶ 25000
·‖ 05: @31974 HT:25000 -> ▶ 25000
!◆! 31: @31952 ⚙ calc(i=57, lev:24)
·‖ 05: @31998 HT:25000 -> ▶ 25000
·‖ 05: @32028 HT:25000 -> ▶ 25000
·‖ 05: @32048 HT:25000 -> ▶ 25000
·‖ 05: @32067 HT:25000 -> ▶ 25000
·‖ 05: @32087 HT:25000 -> ▶ 25000
·‖ 05: @32106 HT:25000 -> ▶ 25000
!◆! 05: @32125 ⚙ calc(i=61, lev:25)
..! 79: @33473 ⤴ (i=52)
‖PST‖ 79: @33519 ◒ start=24000▹▹25000 dead:30000
·‖ 79: @33542 HT:25000 -> ▶ 25000
·‖ 79: @33562 HT:52895 -> ▶ 25000
..! 05: @33680 ⤴ (i=61)
‖PST‖ 05: @33713 ◒ start=25000▹▹26000 dead:30000
·‖ 05: @33734 HT:52895 -> ▶ 26000
..! 31: @34292 ⤴ (i=57)
‖PST‖ 31: @34336 ◒ start=24000▹▹25000 dead:30000
·‖ 31: @34365 HT:52895 -> ▶ 25000
!◆! 31: @34390 ⚙ calc(i=62, lev:25)
..! 31: @34434 ⤴ (i=62)
‖PST‖ 31: @34473 ◒ start=25000▹▹26000 dead:30000
·‖ 31: @34500 HT:52895 -> ▶ 26000
!◆! 31: @34524 ⚙ calc(i=63, lev:26)
..! 31: @35330 ⤴ (i=63)
‖PST‖ 31: @35368 ◒ start=26000▹▹27000 dead:5000000
·‖ 31: @35396 HT:52895 -> ▶ 27000
runTime(Scheduler): 42.0706ms
‖▽▼▽‖ 64: @ 47377
‖▽▼▽‖ 20: @ 47426
‖▽▼▽‖ F6: @ 47549
‖▽▼▽‖ AE: @ 53020
‖▽▼▽‖ 31: @ 55867
‖▽▼▽‖ 05: @ 59500
‖▽▼▽‖ 13: @ 60366
‖▽▼▽‖ 79: @ 64649

View file

@ -91,9 +91,16 @@ Dump-05::
at those parts of the graph where it is possible
- Note moreover, that the actual computation time spent in those nodes with
a computational weight (suffix `.1` ... `.3`) is mostly in excess of the
configured times. For example, a node with weight 3 (≙ 3·500µs) often nees
configured times. For example, a node with weight 3 (≙ 3·500µs) often needs
2-3ms to complete. This is probably due to cache effects, since the weight
calibration is performed in a hot microbenchmark loop, while here, in a
more realistic setting, the cpu-load code is invoked intermingled with
management code, atomic exchanges, sleep-waits and OS scheduler activity.
Dump-06::
The same test setup, but after rework of the Scheduler entrance and
with better schedule focus and a contention mitigation scheme (28.12.23)
+
- refTime(singleThr): 31.8014ms
- runTime(Scheduler): 42.0706ms

View file

@ -71,13 +71,16 @@ namespace test {
virtual void
run (Arg)
{
smokeTest();
//smokeTest();
setup_systematicSchedule();
generalFuckup();
walkingDeadline();
}
/** @test TODO demonstrate sustained operation under load
* - TODO this is a placeholder and works now, but need a better example
* - it should not produce so much overload, rather some stretch of steady-state processing
* @todo WIP 12/23 🔁 define implement
*/
void
@ -134,6 +137,66 @@ namespace test {
/** @test TODO build a scheme to adapt the schedule to expected runtime.
* @todo WIP 12/23 🔁 define implement
*/
void
setup_systematicSchedule()
{
MARK_TEST_FUN
TestChainLoad testLoad{64};
testLoad.configureShape_chain_loadBursts()
.buildToplolgy()
.printTopologyDOT()
.printTopologyStatistics()
;
auto LOAD_BASE = 500us;
ComputationalLoad cpuLoad;
cpuLoad.timeBase = LOAD_BASE;
cpuLoad.calibrate();
double micros = cpuLoad.invoke();
SHOW_EXPR(micros);
CHECK (micros < 550);
CHECK (micros > 450);
auto levelWeights = testLoad.allLevelWeights();
SHOW_EXPR(levelWeights.size())
for (auto& w : levelWeights)
cout<<"level:"<<w.first<<" ∑="<<w.second<<endl;
using Node = TestChainLoad<>::Node;
auto nodeData = testLoad.allNodes()
.transform([](Node& n){ return make_pair(n.level,n.weight); })
.effuse();
for (auto& n : nodeData)
cout<<"level:"<<n.first<<" w="<<n.second<<endl;
CHECK (nodeData[22].first == 16);
CHECK (nodeData[23].first == 17); CHECK (nodeData[23].second == 3); CHECK (levelWeights[17].second == 3);
CHECK (nodeData[24].first == 18); CHECK (nodeData[24].second == 0);
CHECK (nodeData[25].first == 18); CHECK (nodeData[25].second == 0);
CHECK (nodeData[26].first == 18); CHECK (nodeData[26].second == 0);
CHECK (nodeData[27].first == 18); CHECK (nodeData[27].second == 0);
CHECK (nodeData[28].first == 18); CHECK (nodeData[28].second == 0); CHECK (levelWeights[18].second == 0);
CHECK (nodeData[29].first == 19); CHECK (nodeData[29].second == 2);
CHECK (nodeData[30].first == 19); CHECK (nodeData[30].second == 2);
CHECK (nodeData[31].first == 19); CHECK (nodeData[31].second == 2);
CHECK (nodeData[32].first == 19); CHECK (nodeData[32].second == 2);
CHECK (nodeData[33].first == 19); CHECK (nodeData[33].second == 2); CHECK (levelWeights[19].second == 10);
CHECK (nodeData[34].first == 20); CHECK (nodeData[34].second == 3);
CHECK (nodeData[35].first == 20); CHECK (nodeData[35].second == 2); CHECK (levelWeights[20].second == 5);
CHECK (nodeData[36].first == 21); CHECK (nodeData[36].second == 1);
CHECK (nodeData[37].first == 21); CHECK (nodeData[37].second == 1);
CHECK (nodeData[38].first == 21); CHECK (nodeData[38].second == 3); CHECK (levelWeights[21].second == 5);
}
/** @test TODO
* @todo WIP 12/23 🔁 define implement
*/

View file

@ -748,6 +748,27 @@ namespace test {
}
/** calculate node weights aggregated per level */
auto
allLevelWeights()
{
std::vector<std::pair<size_t,size_t>> weightTab;
weightTab.reserve (topLevel()+1);
auto currLevel = [&]()-> decltype(auto) { return weightTab.back(); };
auto nextLevel = [&](size_t levelID) { weightTab.emplace_back(levelID,0); };
nextLevel (0);
for (Node& n : allNodes())
{
if (n.level > currLevel().first)
nextLevel(n.level);
// aggregate weights within level
currLevel().second += n.weight;
}
return weightTab;
}
Statistic computeGraphStatistics();
TestChainLoad&& printTopologyStatistics();

View file

@ -6183,7 +6183,7 @@ This is the core service provided by the player subsystem. The purpose is to cre
:any details of this processing remain opaque for the clients; even the player subsystem just accesses the EngineFaçade
</pre>
</div>
<div title="PlaybackVerticalSlice" creator="Ichthyostega" modifier="Ichthyostega" created="202303272236" modified="202307220249" tags="overview impl discuss draft" changecount="34">
<div title="PlaybackVerticalSlice" creator="Ichthyostega" modifier="Ichthyostega" created="202303272236" modified="202312281714" tags="overview impl discuss draft" changecount="37">
<pre>//Integration effort to promote the development of rendering, playback and video display in the GUI//
This IntegrationSlice was started in {{red{2023}}} as [[Ticket #1221|https://issues.lumiera.org/ticket/1221]] to coordinate the completion and integration of various implementation facilities, planned, drafted and built during the last years; this effort marks the return of development focus to the lower layers (after years of focussed UI development) and will implement the asynchronous and time-bound rendering coordinated by the [[Scheduler]] in the [[Vault|Vault-Layer]]
@ -6211,10 +6211,13 @@ __June23__: building upon this prototyping approach, the dispatcher pipeline cou
__July23__: this leads to a shift of work focus towards implementing the [[Scheduler]] itself.
The Scheduler will be structured into two Layers, where the lower layer is implemented as //priority queue// (using the STL). So the most tricky part to solve is the representation of //dependencies// between jobs, with the possible extension to handling IO operations asynchronously. Analysis and planning of the implementation indicate that the [[scheduler memory managment|SchedulerMemory]] can be based on //Extents//, which are interpreted as »Epochs« with a deadline. These considerations imply what steps to take next for building up Scheduler functionality and memory management required for processing a simple job
* ✔ build a first working draft for the {{{BlockFlow}}} allocation scheme [[#1311|https://issues.lumiera.org/ticket/1311]]
* 🗘 define and cover the basic [[Activities|RenderActivity]] necessary to implement a plain-simple-Job (without dependencies)
* ⌛ pass such an Activity through the two layers of the Scheduler
* ✔ define and cover the basic [[Activities|RenderActivity]] necessary to implement a plain-simple-Job (without dependencies)
* ✔ pass such an Activity through the two layers of the Scheduler
* 🗘 establish a baseline for //performance measurements//
* ⌛ adapt the [[job planning pipeline|JobPlanningPipeline]] implemented thus far to produce the appropriate {{{Activity}}} records for the scheduler
__December23__: building the Scheduler required some time and dedication, including some related topics like a [[dedicated memory management scheme|SchedulerMemory]], rework and modernisation of the [[#1279 thread handling framework|https://issues.lumiera.org/ticket/1279]], using a [[worker pool|SchedulerWorker]] and developing the [[foundation for load control|SchedulerLoadControl]]. This amounts to the creation of a considerable body of new code; some load- and stress testing helps to establish performance characteristics .
!Decisions
;Scheduler
:is understood as a high-level Service, not a bare bone implementation mechanism
@ -6227,6 +6230,10 @@ The Scheduler will be structured into two Layers, where the lower layer is imple
:a dependency check is operationalised as activity primitive and also used to hold allocations alive
:operational control and data management is //performed by the workers// interspersed with render activities
:however, only one worker at any time is allowed to perform these meta tasks, avoiding further synchronisation
;Workers
:are active agents in the Lumiera ~Render-Engine and drive the processing collaboratively
:there is no central »manager« or »dispatcher« thread, rather work is //pulled// and management work is handled alongside
:Load and capacity management is [[handled stochastically|SchedulerLoadControl]] -- workers „sample the timeline“
</pre>
</div>
<div title="Player" modifier="Ichthyostega" created="201012181700" modified="202304140114" tags="def overview" changecount="4">
@ -6858,7 +6865,7 @@ At first sight the link between asset and clip-MO is a simple logical relation b
{{red{Note 1/2015}}} several aspects regarding the relation of clips and single/multichannel media are not yet settled. There is a preliminary implementation in the code base, but it is not sure yet how multichnnel media will actually be modelled. Currently, we tend to treat the channel multiplicity rather as a property of the involved media, i.e we have //one// clip object.</pre>
</div>
<div title="RenderActivity" creator="Ichthyostega" modifier="Ichthyostega" created="202304140145" modified="202308291242" tags="Rendering spec draft" changecount="15">
<div title="RenderActivity" creator="Ichthyostega" modifier="Ichthyostega" created="202304140145" modified="202312281737" tags="Rendering spec draft" changecount="16">
<pre>//Render Activities define the execution language of the render engine.//
The [[Scheduler]] maintains the ability to perform these Activities, in a time-bound fashion, observing dependency relations; activities allow for notification of completed work, tracking of dependencies, timing measurements, re-scheduling of other activities -- and last but not least the dispatch of actual [[render jobs|RenderJob]]. Activities are what is actually enqueued with priority in the scheduler implementation, they are planned for a »µ-tick slot«, activated once when the activation time is reached, and then forgotten. Each Activity is a //verb//, but can be inhibited by conditions and carry operation object data. Formally, activating an Activity equates to a predication, and the subject of that utterance is »the render process«.
@ -6898,7 +6905,7 @@ The //meaning// of Activities can be understood on two levels. For one, there is
* guarding means inhibiting and releasing -- once the prerequisites of a {{{GATE}}} have been ticket off, and unless the deadline is violated
* notification implies a trigger -- an impulse, either to //decrement// a {{{GATE}}} or to //activate// another Activity
* posting anchors a pattern -- a complete structure of further Activities is put underway, possibly with an explicit //start time// and //deadline.//
However, the //meaning// of Activities can also be understood at the //operational level:// This is what the [[operational logic of Activity execution|RenderOperationLogic]] entails, what is implemented as interpretation of the Activity Language and what is actually backed and implemented by the [[Scheduler]].
However, the //meaning// of Activities can also be understood at the //operational level:// This is what the [[operational logic of Activity execution|RenderOperationLogic]] entails, what is implemented as interpretation of the Activity Language and what is actually backed and implemented by the [[internals of the Scheduler|SchedulerProcessing]].
</pre>
</div>
<div title="RenderDrive" creator="Ichthyostega" modifier="Ichthyostega" created="202306122212" tags="spec Player draft" changecount="1">
@ -7041,7 +7048,7 @@ __see also__
&amp;rarr; the protocol [[how to operate the nodes|NodeOperationProtocol]]
</pre>
</div>
<div title="RenderOperationLogic" creator="Ichthyostega" modifier="Ichthyostega" created="202307272322" modified="202310272134" tags="Rendering operational draft" changecount="30">
<div title="RenderOperationLogic" creator="Ichthyostega" modifier="Ichthyostega" created="202307272322" modified="202312281644" tags="Rendering operational draft" changecount="31">
<pre>//The operational logic of Activity execution is the concrete service provided by the [[Scheduler]] to implement interwoven [[render Activities|RenderActivity]] and [[Job execution|RenderJob]].//
* logically, each {{{Activity}}} record represents a //verb// to describe some act performed by »the render process«
* the {{{ActivityLang}}} provides a //builder notation// to build „sentences of activities“ and it sets the framework for //execution// of Activities
@ -7125,7 +7132,7 @@ Since the render engine can be considered performance critical, only a fixed set
!!!Post and dispatch
An Activity is //performed// by invoking its {{{activate(now, ctx)}}} function -- however, there is a twist: some Activities require interaction with the Scheduler queue or may even alter this queue -- and such Activities must be performed //in »management mode«// (single threaded, holding the {{{GroomingToken}}}). These requirements can be fulfilled by //dispatching// an Activity through the ''λ-post'', which attempts to acquire the {{{GroomingToken}}} to proceed directly -- and otherwise sends the action through the //dispatch queue.// Moreover, some follow-up activities need to happen //later// -- and this can be encoded by using a {{{POST}}}-Activity, which both defines a time window of execution and causes its chain-Activity to be sent through ''λ-post''. All the Lambda functions mentioned here are part of the //execution context,// which represents and abstracts the scheduler environment.
In a similar vein, also ''dependency notifications'' need to happen decoupled from the activity chain from which they originate; thus the Post-mechanism is also used for dispatching notifications. Yet notifications are to be treated specially, since they are directed towards a receiver, which in the standard case is a {{{GATE}}}-Activity and will respond by //decrementing its internal latch.// Consequently, receiving a notification may cause the Gate to become opened; in this case the trigger is passed through a further dispatch through the ''λ-post'' to activate the chain-Activities hooked behind the Gate. Otherwise, if the latch is already zero (or the deadline has passed), nothing happens. Thus the implementation of state transition logic ensures the chain behind a Gate can only be //activated once.//
In a similar vein, also ''dependency notifications'' need to happen decoupled from the activity chain from which they originate; thus the Post-mechanism is also used for dispatching notifications. Yet notifications are to be treated specially, since they are directed towards a receiver, which in the standard case is a {{{GATE}}}-Activity and will respond by //decrementing its internal latch.// Consequently, notifications will be sent through the ''λ-post'' -- which operationally re-schedules a continuation as a follow-up job. Receiving such a notification may cause the Gate to become opened; in this case the trigger leads to //activation of the chain// hooked behind the Gate, which at some point typically enters into another calculation job. Otherwise, if the latch (in the Gate) is already zero (or the deadline has passed), nothing happens. Thus the implementation of state transition logic ensures the chain behind a Gate can only be //activated once.//
</pre>
</div>
<div title="RenderProcess" modifier="Ichthyostega" created="200706190705" modified="201112162056" tags="Rendering operational">
@ -7167,7 +7174,7 @@ 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" modified="202310240237" tags="Rendering spec draft" changecount="24">
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202312281735" tags="Rendering spec draft" changecount="29">
<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 organised into two layers:
;Layer-2: Coordination
@ -7193,12 +7200,20 @@ The [[Language of render activities|RenderActivity]] forms the interface to the
These ''Worker Threads'' will perform actual render activities most of the time (or be idle). However -- idle workers contend for new work, and for doing so, they //also perform the internal scheduler management activities.// As a consequence, all Scheduler coordination and [[memory management|SchedulerMemory]] is ''performed non-concurrent'': only a single Worker can acquire the {{{GroomingToken}}} and will then perform managment work until the next render activity is encountered at the top side of the //priority queue.//
This leads to a »chaotic«, event-driven processing style without a central managing entity -- the scheduler does not „run the shop“ and rather fulfils a role as bookkeeping and balancing guide. Operationally, the internals of the Scheduler are grouped into several components and arranged towards two entrance lanes: defining a new schedule entry and retrieving work.
&amp;rarr; SchedulerProcessing
!!!Performance
Processing is not driven by a centralised algorithm, but rather stochastically by workers becoming available for further work. This allows for adaptation to a wide array of load patterns, but turns assessment of the Scheduler's capabilities and limitations into a challenging task. The speed and throughput of the processing are largely defined by the actual scheduler -- up to the point where the Scheduler is overloaded permanently and the //schedule slips away.// Based on that observation, a framework for [[Scheduler Load- and Performance-testing|SchedulerTest]] was^^{{red{12/2023 rather is about to be}}}^^ established.
!!!Instructing the Scheduler
The Scheduler is now considered an implementation-level facility with an interface specifically tailored at the JobPlanningPipeline: the [[»Render Activity Language«|RenderActivity]]. This //builder-style// setup allows to construct an ''~Activity-Term'' to model all the structural properties of an individual rendering invocation -- it is compriesed of a network of {{{Activity}}} records, which can be directly handled by the Scheduler.
&amp;rarr; [[Activity|RenderActivity]]
&amp;rarr; [[Memory|SchedulerMemory]]
&amp;rarr; [[Workers|SchedulerWorker]]
&amp;rarr; [[Internals|SchedulerProcessing]]
&amp;rarr; [[Testing|SchedulerTest]]
</pre>
</div>
<div title="SchedulerLoadControl" creator="Ichthyostega" modifier="Ichthyostega" created="202310240240" modified="202311010317" tags="Rendering operational spec draft" changecount="60">
@ -7255,7 +7270,7 @@ These distinct »processing classes« seem to impose almost contradictory calcul
A task placed into the scheduling timeline basically represents some //»cross-section of probability«.// If work capacity happens to „land“ into its definition realm and no further overdue task is scheduled before, the task can use the available capacity. Yet when the deadline of the task has passed without any free capacity „hitting“ its scope, its chances are wasted and the scheduler will discard the entry. And by exploiting these relationships, it is possible to craft a scheme of time slot allocation to translate an abstract processing priority into a probabilistic access to some fraction of capacity. Even more so, since it is possible to place multiple instances of the same task into the scheduling timeline, relying on the [[»Gate« mechanism|RenderOperationLogic]] of the [[Activity-Language|RenderActivity]], to spread out a small level of background processing probability over an extended period of time.
</pre>
</div>
<div title="SchedulerMemory" creator="Ichthyostega" modifier="Ichthyostega" created="202307031622" modified="202310241427" tags="Rendering operational draft" changecount="31">
<div title="SchedulerMemory" creator="Ichthyostega" modifier="Ichthyostega" created="202307031622" modified="202312281738" tags="Rendering operational draft" changecount="32">
<pre>//The Scheduler uses an »Extent« based memory management scheme known as {{{BlockFlow}}}.//
The organisation of rendering happens in terms of [[Activities|RenderActivity]], which may bound by //dependencies// and limited by //deadlines.// For the operational point of view this implies that a sequence of allocations must be able to „flow through the Scheduler“ -- in fact, only references to these {{{Activity}}}-records are passed, while the actual descriptors reside at fixed memory locations. This is essential to model the dependencies and conditional execution structures efficiently. At some point however, any {{{Activity}}}-record will either be //performed// or //obsoleted// -- and this leads to the idea of managing the allocations in //extents// of memory here termed as »Epochs«
* a new Activity is planted into a suitable //Epoch,// based on its deadline
@ -7285,6 +7300,16 @@ The auto-regulation of this allocation scheme is based on //controlling the Epoc
It should be noted that {{{BlockFlow}}} provides very specific services, which are more elaborate than just a custom memory allocator. By leveraging possible scale factors, it is possible however to bring the amortised effort for a single {{{Activity}}} allocation down into the same order of magnitude as a standard heap allocation, which equates to roughly 30ns on contemporary machines. For context, an individually managed allocation-deallocation pair with a ref-counting {{{std::shared_ptr}}} has a typical performance cost of ~100ns.
The primary scaling effects exploited to achieve this level of performance are the combined de-allocation of a complete Epoch, and the combination of several allocations tied to a common deadline. However -- since the Epoch duration is chosen dynamically, performance can potentially be //degraded drastically// once the scheme is put under pressure -- since each new allocation has to search through the list of active Epochs. Parameters are tuned such as to ensure this list remains very short (about 5 Epochs) under typical operational conditions.
&amp;rarr; [[Scheduler performance testing|SchedulerTest]]
</pre>
</div>
<div title="SchedulerProcessing" creator="Ichthyostega" modifier="Ichthyostega" created="202312281750" modified="202312281756" tags="Rendering operational draft" changecount="5">
<pre>At first sight, the internals of [[Activity|RenderActivity]] processing may seem overwhelmingly complex -- especially since there is no active »processing loop« which might serve as a starting point for the understanding. It is thus necessary to restate the working mode of the Scheduler: it is an //accounting and direction service// for the //active// [[render workers|SchedulerWorker]]. Any processing happens stochastically and is driven by events
* a //worker// becoming ready to perform further tasks
* an external //IO event// {{red{12/23 only planned yet}}}
* a //planning job// to add new elements to the schedule
The last point highlights a //circular structure:// the planning job itself was part of the schedule, picked up by a worker and activated; this way, the system feeds itself.
</pre>
</div>
<div title="SchedulerRequirements" modifier="Ichthyostega" created="201107080145" modified="201112171835" tags="Rendering spec draft discuss">
@ -7302,7 +7327,38 @@ The primary scaling effects exploited to achieve this level of performance are t
The way other parts of the system are built, requires us to obtain a guaranteed knowledge of some job's termination. It is possible to obtain that knowledge with some limited delay, but it nees to be absoultely reliable (violations leading to segfault). The requirements stated above assume this can be achieved through //jobs with guaranteed execution.// Alternatively we could consider installing specific callbacks -- in this case the scheduler itself has to guarantee the invocation of these callbacks, even if the corresponding job fails or is never invoked. It doesn't seem there is any other option.
</pre>
</div>
<div title="SchedulerWorker" creator="Ichthyostega" modifier="Ichthyostega" created="202309041605" modified="202312201342" tags="Rendering operational spec draft" changecount="15">
<div title="SchedulerTest" creator="Ichthyostega" modifier="Ichthyostega" created="202312281814" modified="202312281836" tags="Rendering operational draft" changecount="4">
<pre>With the Scheduler testing effort [[#1344|https://issues.lumiera.org/ticket/1344]], several goals are pursued
* by exposing the new scheduler implementation to excessive overload, its robustness can be assessed and defects can be spotted
* with the help of a systematic, calibrated load, characteristic performance limits and breaking points can be established
* when performed in a reproducible way, these //stress tests// can also serve to characterise the actual platform
* a synthetic load emulating standard use cases allows to watch complex interaction patterns and to optimise the implementation
!A synthetic load for performance testing
In fall 2023, a load generator component was developed [[#1346|https://issues.lumiera.org/ticket/1346]] as foundation for Scheduler testing.
The {{{TestChainLoad}}} is inspired by the idea of a blockchain, and features a //graph// of //processing steps (nodes)// to model complex interconnected computations. Each //node// in this graph stands for one render job to be scheduled, and it is connected to //predecessors// and //successors//. The node is able to compute a chained hash based on the hash values of its predecessors. When configured with a //seed value//, this graph has the capability to compute a well defined result hash, which involves the invocation of every node in the right order. For verification, this computation can be done sequentially, by a single thread performing linear pass over the graph. The actual test however is to traverse the graph to produce a schedule of render jobs, each linked to a single node and defining prerequisites in accordance to the graph's structure. It is up to the scheduler then to ensure dependency relations and work out a way to pass on activation, so that the proper result hash will be reproduced at the end.
The Scheduler thus follows the connectivity pattern, and defining a specific pattern characterises the load to produce. Patterns are formed by connecting (or re-connecting) nodes, based on the node's hash -- which implies that patterns are generated. The generation process and thus the emerging form is controlled and defined by a small number of rules. Each rule defines a probability mapping; when fed with a node hash, some output parameter value is generated randomly yet deterministically. The following //topology control rules// are recognised
;seeding rule
:when non-zero, the given number of new start (seed) nodes is injected.
:all seed nodes hold the same, preconfigured fixed seed value and only have successors, no predecessors
;expansion rule
:when non-zero, the current node forks out to the given additional number of successor nodes
;reduction rule
:when non-zero, the current node will join the given number of additional predecessor nodes
;pruning rule
:when non-zero, the current node will be an exit node and terminate the current chain without successor
:when all ongoing chains happen to be terminated, a new seed node is injected automatically
;weight rule
:when non-zero, a computational weight with the given level is applied when invoking the node as render job
:the //base time// of that weight can be configured (in microseconds) and is roughly calibrated for the current machine
* //without any rule,// the default is to connect linear chains with one predecessor and one successor
* the node graph holds a fixed preconfigured number of nodes
* the //width// is likewise preconfigured, i.e. the number of nodes on the same »level« and typically started at the same time
* generation is automatically terminated with an exit node, joining all remaining chains
</pre>
</div>
<div title="SchedulerWorker" creator="Ichthyostega" modifier="Ichthyostega" created="202309041605" modified="202312281745" tags="Rendering operational spec draft" changecount="21">
<pre>The Scheduler //maintains a ''Work Force'' (a pool of workers) to perform the next [[render activities|RenderActivity]] continuously.//
Each worker runs in a dedicated thread; the Activities are arranged in a way to avoid blocking those worker threads
* IO operations are performed asynchronously {{red{planned as of 9/23}}}
@ -7310,7 +7366,7 @@ Each worker runs in a dedicated thread; the Activities are arranged in a way to
!Workload and invocation scheme
Using a pool of workers to perform small isolated steps of work atomically and in parallel is an well established pattern in high performance computing. However, the workload for rendering media is known to have some distinctive traits, calling for a slightly different approach compared with an operation system scheduler or a load balancer. Notably, the demand for resources is high, often using „whatever it takes“ -- driving the system into load saturation. The individual chunks of work, which can be computed independently, are comparatively large, and must often be computed in a constrained order. For real-time performance, it is desirable to compute data as late as possible, to avoid blocking memory with computed results. And for the final quality render, for the same reason it is advisable to proceed in data dependency order to keep as much data as possible in memory and avoid writing temporary files.
This leads to a situation where it is more adequate to //distribute the scarce computation resources// to the tasks //sequenced in temporary and dependency order//. The computation tasks must be prepared and ordered -- but beyond that, there is not much that can be »managed« with a computation task. For this reason, the Scheduler in the Lumiera Render Engine uses a pool of workers, each providing one unit of computation resource (a »core«), and these workers will ''pull work'' actively, rather then distributing, queuing and dispatching tasks to a passive set of workers.
This leads to a situation where it is more adequate to //distribute the scarce computation resources// to the tasks //sequenced in temporary and dependency order//. The computation tasks must be prepared and ordered -- but beyond that, there is not much that can be »managed« with a computation task. For this reason, the Scheduler in the Lumiera Render Engine uses a pool of workers, each providing one unit of computation resource (a »core«), and these workers will ''pull work'' actively, which stands in contrast to the usual pattern of distributing, queuing and dispatching tasks towards a passive set of workers.
Moreover, the actual computation tasks, which can be parallelised, are at least by an order of magnitude more expensive than any administrative work for sorting tasks, checking dependencies and maintaining process state. This leads to a scheme where a worker first performs some »management work«, until encountering the next actual computation job, at which point the worker leaves the //management mode// and transitions into //concurrent work mode//. All workers are expected to be in work mode almost entirely most of the time, and thus we can expect not much contention between workers performing »management work« -- allowing to confine this management work to //single threaded operation,// thereby drastically reducing the complexity of management data structures and memory allocation.
!!!Regulating workers
@ -7332,6 +7388,8 @@ Following the rules of [[C++ atomic Release-Acquire ordering|https://en.cpprefer
# an atomic store is performed with {{{memory_order_release}}} (thereby dropping the token)
# now another thread can perform an atomic load with {{{memory_order_acquire}}} -- but it is essential to check and branch on the loaded value
# and only when the loaded value indicates that the load is //synchronised-with// the preceding store, then the other management data can be processed
&amp;rarr; [[Internals of processing in the Scheduler|SchedulerProcessing]]
</pre>
</div>
<div title="ScopeLocator" modifier="Ichthyostega" created="200911192145" modified="200911202035" tags="def SessionLogic">

View file

@ -86663,9 +86663,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1703634299488" ID="ID_1821925680" MODIFIED="1703703607115" TEXT="Vergleich mit dem alten Stand vom 22.Juli.2023">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
commit 28b39002846aba9ef3dab18dae10f67fa8b063dd
@ -86719,17 +86717,14 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
&#160;&#160;&#160;&#160;- Documentation
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node COLOR="#338800" CREATED="1703635665168" ID="ID_290246416" MODIFIED="1703635744545" TEXT="Baue kompletten Lumiera-Tree auf Stand 28b39002846">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1703634318350" ID="ID_338241268" MODIFIED="1703634324809" TEXT="Benchmark-Ergebnisse">
<node CREATED="1703634325860" ID="ID_696157189" MODIFIED="1703634362905" TEXT="DEBUG">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -86774,14 +86769,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1703634367911" ID="ID_190199783" MODIFIED="1703635629003" TEXT="RELEASE">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -86826,30 +86818,24 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#a9b4c1" DESTINATION="ID_190199783" ENDARROW="Default" ENDINCLINATION="447;0;" ID="Arrow_ID_1073083352" SOURCE="ID_610113635" STARTARROW="None" STARTINCLINATION="224;-7;"/>
</node>
</node>
<node CREATED="1703635349432" ID="ID_1574318421" MODIFIED="1703639766505" TEXT="versuche backport der neuen(aktuellen) Impl">
<node CREATED="1703635365056" ID="ID_538802939" MODIFIED="1703635423957" TEXT="geht nicht ganz (kann nicht das GATE) verwenden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
inzwischen kann die GATE-Activity den Deadline-Check f&#252;r eine Epoch machen; das kann ich nicht so ohne weiteres backporten
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1703635448813" ID="ID_1193309062" MODIFIED="1703637629387" TEXT="DEBUG">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -86894,17 +86880,14 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1703635542321" HGAP="34" ID="ID_912796682" MODIFIED="1703635577249" TEXT="best&#xe4;tigt Boost durch Caching" VSHIFT="3">
<arrowlink DESTINATION="ID_963318017" ENDARROW="Default" ENDINCLINATION="930;0;" ID="Arrow_ID_1375718629" STARTARROW="None" STARTINCLINATION="422;0;"/>
</node>
</node>
<node CREATED="1703635451717" ID="ID_1724522819" MODIFIED="1703635473415" TEXT="RELEASE">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -86949,8 +86932,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1703635587433" HGAP="23" ID="ID_610113635" MODIFIED="1703635629003" TEXT="im Rahmen der Genauigkeit: gleich/kein Einflu&#xdf; feststellbar" VSHIFT="4">
<arrowlink DESTINATION="ID_190199783" ENDARROW="Default" ENDINCLINATION="447;0;" ID="Arrow_ID_1073083352" STARTARROW="None" STARTINCLINATION="224;-7;"/>
</node>
@ -86972,9 +86954,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703637529666" ID="ID_990734360" MODIFIED="1703637543160" TEXT="aktueller HEAD (incl. Fixes)">
<node CREATED="1703637544994" ID="ID_1737866362" MODIFIED="1703637940173" TEXT="DEBUG">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87019,14 +86999,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1703637867720" ID="ID_437333549" MODIFIED="1703637933394" TEXT="RELEASE">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____X </font>
@ -87071,16 +87048,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1703637993311" ID="ID_311327455" MODIFIED="1703638000394" TEXT="forward-port alter Stand">
<node CREATED="1703638971490" ID="ID_38381979" MODIFIED="1703639498076" TEXT="DEBUG">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87125,14 +87099,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1703639118711" ID="ID_460152969" MODIFIED="1703639141305" TEXT="RELEASE">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87177,8 +87148,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1703639208642" ID="ID_125259768" MODIFIED="1703639227291" TEXT="das sind essentiell die gleichen Me&#xdf;werte">
@ -87215,16 +87185,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703703868131" ID="ID_726207700" MODIFIED="1703703880603" TEXT="der Test verwendet n&#xe4;mlich nur eine einzige Funktion"/>
<node CREATED="1703703881877" ID="ID_475394127" MODIFIED="1703703963065" TEXT="diese l&#xe4;&#xdf;t sich isolieren und hat praktisch keine &#xc4;nderungen erfahren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
sowohl die Umstellung des Threadwrappers, alsauch das automatische Adaptieren der Test-Lambdas betrifft nur die anderen Funktionen; auch damals habe ich bereits per std::Chrono gemessen, und der Unterschied system_clock vs. steady_clock scheint keinen Einflu&#223; zu haben
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1703703971747" ID="ID_1634949703" MODIFIED="1703703991109" TEXT="messe nun sicherheitshalber stets mit einem vereinfachten, alten Framework"/>
</node>
@ -87269,22 +87236,17 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1703717999703" ID="ID_411398744" MODIFIED="1703718687418">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
best&#228;tigt: mit <b>komplettem Release-Build</b>&#160;l&#228;uft auch der aktuelle Code schnell(er)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="forward"/>
<node CREATED="1703718111696" ID="ID_210881011" MODIFIED="1703718850087" TEXT="nach Umbau 17ns">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87329,16 +87291,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#58929b" DESTINATION="ID_210881011" ENDARROW="Default" ENDINCLINATION="-321;-33;" ID="Arrow_ID_79637079" SOURCE="ID_1403261019" STARTARROW="None" STARTINCLINATION="1038;66;"/>
<icon BUILTIN="info"/>
</node>
<node CREATED="1703718641487" ID="ID_1495894763" MODIFIED="1703718679576" TEXT="vor Umbau 31ns">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87383,8 +87342,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
</node>
@ -87397,16 +87355,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703718202196" ID="ID_145500252" MODIFIED="1703718216205" TEXT="mit einem kompletten Release-Build sind die Timings konsistent"/>
<node CREATED="1703718217050" ID="ID_1090349590" MODIFIED="1703718717984">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
die neuerlichen &#196;nderungen f&#252;hren zu einer <b>deutlichen Verbesserung</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="forward"/>
</node>
</node>
@ -87422,9 +87377,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703723485104" ID="ID_37862789" MODIFIED="1703723514400" TEXT="kostet einen Gro&#xdf;teil der soeben gewonnenen Performance"/>
<node CREATED="1703723516316" ID="ID_576453194" MODIFIED="1703724798331" TEXT="Me&#xdf;werte mit dieser L&#xf6;sung: 24ns">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">___Microbenchmark____ </font>
@ -87469,23 +87422,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced">alloc pool... 10 </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#2b72c5" DESTINATION="ID_576453194" ENDARROW="Default" ENDINCLINATION="357;24;" ID="Arrow_ID_1759861140" SOURCE="ID_933611212" STARTARROW="None" STARTINCLINATION="573;22;"/>
<icon BUILTIN="forward"/>
</node>
<node CREATED="1703723571556" ID="ID_93293223" MODIFIED="1703723626996">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
jetzt <font size="2">(nur noch)</font>&#160;<b>+22%</b>&#160;Performance-Gewinn
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="smiley-neutral"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1703724187666" HGAP="18" ID="ID_550383888" MODIFIED="1703724205691" TEXT="aber ich kann wieder schlafen" VSHIFT="9">
@ -98617,7 +98566,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1703013769654" ID="ID_494403810" LINK="#ID_1570400114" MODIFIED="1703013818815" TEXT="nun l&#xe4;uft ein Test mit 64 Nodes + &#xdc;berlastung glatt durch">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1703013833134" ID="ID_1533352432" MODIFIED="1703013842460" TEXT="Crash bei l&#xe4;ngerem Lauf">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1703013833134" ID="ID_1533352432" MODIFIED="1703797923485" TEXT="Crash bei l&#xe4;ngerem Lauf">
<icon BUILTIN="broken-line"/>
</node>
<node COLOR="#338800" CREATED="1703100826420" FOLDED="true" ID="ID_453686950" MODIFIED="1703100998714" TEXT="Contention bremst massiv aus">
@ -98638,6 +98587,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1703797884592" ID="ID_1054108689" LINK="#ID_451970697" MODIFIED="1703797908103" TEXT="Crashes aufgekl&#xe4;rt und Planungs-Locking gel&#xf6;st">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1703797959342" ID="ID_1434946452" MODIFIED="1703798007163" TEXT="Ermitteln von Lastgrenzen">
<arrowlink COLOR="#618eb4" DESTINATION="ID_816186443" ENDARROW="Default" ENDINCLINATION="-871;-40;" ID="Arrow_ID_888227312" STARTARROW="None" STARTINCLINATION="-203;20;"/>
<icon BUILTIN="pencil"/>
</node>
</node>
</node>
@ -103819,22 +103775,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#435e98" CREATED="1702264680182" ID="ID_1945693212" MODIFIED="1702319534283" TEXT="kann man einen theoretischen Concurrency-Faktor bestimmen?">
<node COLOR="#435e98" CREATED="1702264680182" ID="ID_1945693212" MODIFIED="1703794807104" TEXT="kann man einen theoretischen Concurrency-Faktor bestimmen?">
<arrowlink COLOR="#497dbb" DESTINATION="ID_599869061" ENDARROW="Default" ENDINCLINATION="-146;-288;" ID="Arrow_ID_312816279" STARTARROW="None" STARTINCLINATION="523;22;"/>
<icon BUILTIN="help"/>
<node CREATED="1702265262323" ID="ID_1908727445" MODIFIED="1702265353793" TEXT="ja ... die Datenstruktur ist g&#xfc;nstig">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
und zwar der Umstand, da&#223; die Nodes <i>innerhalb eines Levels stets voneinander unabh&#228;ngig sind; </i>deshalb sind <i>zumindest</i>&#160;diese Nodes komplett parallelisierbar
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1702265418472" ID="ID_565310505" MODIFIED="1702265468382" TEXT="Beschleunigungsfaktor: &#x2205;w / floor(&#x2205;w/concurrency)">
<icon BUILTIN="forward"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1700105555476" ID="ID_587761135" MODIFIED="1702317677406" TEXT="Scheduling">
@ -107460,9 +107403,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<linktarget COLOR="#980e34" DESTINATION="ID_451970697" ENDARROW="Default" ENDINCLINATION="163;698;" ID="Arrow_ID_1930824070" SOURCE="ID_1994748011" STARTARROW="None" STARTINCLINATION="-607;42;"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702944889122" ID="ID_816186443" MODIFIED="1703125925828" TEXT="Berechnung der systematisch-erwartbaren Ausf&#xfc;hrungszeit">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1702944889122" ID="ID_816186443" MODIFIED="1703807949690" TEXT="Berechnung der systematisch-erwartbaren Ausf&#xfc;hrungszeit">
<linktarget COLOR="#5d567f" DESTINATION="ID_816186443" ENDARROW="Default" ENDINCLINATION="-25;77;" ID="Arrow_ID_280715198" SOURCE="ID_1983964457" STARTARROW="None" STARTINCLINATION="-621;-17;"/>
<icon BUILTIN="flag-yellow"/>
<linktarget COLOR="#618eb4" DESTINATION="ID_816186443" ENDARROW="Default" ENDINCLINATION="-871;-40;" ID="Arrow_ID_888227312" SOURCE="ID_1434946452" STARTARROW="None" STARTINCLINATION="-203;20;"/>
<icon BUILTIN="pencil"/>
<node CREATED="1702944906320" ID="ID_1870513553" MODIFIED="1702944934194" TEXT="per Chain-Load Graph-processing">
<icon BUILTIN="info"/>
<node CREATED="1702945021981" ID="ID_723525598" MODIFIED="1702945026149" TEXT="Level finden"/>
@ -107471,18 +107415,134 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702944916656" ID="ID_1187169308" MODIFIED="1702944931701" TEXT="Fall1: singlethreaded">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1703792015525" ID="ID_851282799" MODIFIED="1703792030956" TEXT="ermittelt Gewichtsfaktor pro Level"/>
<node CREATED="1703797597576" ID="ID_496053162" MODIFIED="1703797638501" TEXT="liefert f&#xfc;r jeden Level: (levelNr, &#x3a3;w, &#x3a3;n)"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1703801391911" ID="ID_1010028454" MODIFIED="1703807940482" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node COLOR="#5b280f" CREATED="1703801398285" ID="ID_1449254847" MODIFIED="1703804125235" TEXT="Iter-Explorer mit gruppierendem Processing-Layer">
<linktarget COLOR="#f53565" DESTINATION="ID_1449254847" ENDARROW="Default" ENDINCLINATION="-19;118;" ID="Arrow_ID_669204155" SOURCE="ID_1512834256" STARTARROW="None" STARTINCLINATION="-120;-17;"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1703801415915" ID="ID_1892218840" MODIFIED="1703801420014" TEXT="Invariante">
<node CREATED="1703801424674" ID="ID_1457989009" MODIFIED="1703801488351" TEXT="src-Layer-Schritt &#x2228; &#x27d8;"/>
<node CREATED="1703801507623" ID="ID_413470514" MODIFIED="1703801517722" TEXT="pull until Invariant"/>
</node>
<node CREATED="1703801542852" ID="ID_127003553" MODIFIED="1703801544885" TEXT="pull">
<node CREATED="1703801545889" ID="ID_1953619504" MODIFIED="1703801550915" TEXT="++src"/>
<node CREATED="1703801552233" ID="ID_1286030097" MODIFIED="1703801557069" TEXT="agg += src"/>
</node>
<node CREATED="1703801655483" ID="ID_227559315" MODIFIED="1703801660375" TEXT="iterNext">
<node CREATED="1703801661171" ID="ID_563654316" MODIFIED="1703801664182" TEXT="clear agg"/>
<node CREATED="1703801664794" ID="ID_1342884186" MODIFIED="1703801669582" TEXT="pull until Invariant"/>
</node>
<node CREATED="1703801678704" ID="ID_323139351" MODIFIED="1703801687139" TEXT="yield &#x27fc; agg"/>
<node CREATED="1703801688255" ID="ID_257969907" MODIFIED="1703801695530" TEXT="checkPoint &#x27fc; bool(src)"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1703803877948" HGAP="6" ID="ID_919959060" MODIFIED="1703804114668" TEXT="puh... schwer" VSHIFT="19">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1703803893711" ID="ID_97947084" MODIFIED="1703803912241" TEXT="so komplexer Code sollte in eine Hilfsklasse"/>
<node CREATED="1703803912765" ID="ID_225919235" MODIFIED="1703803921504" TEXT="die m&#xfc;&#xdf;te dann aber generisch sein"/>
<node CREATED="1703803922283" ID="ID_906230065" MODIFIED="1703803941407" TEXT="verwendet einen Group-Datentyp">
<icon BUILTIN="idea"/>
<node CREATED="1703803942969" ID="ID_1637691632" MODIFIED="1703803952707" TEXT="typischerweise ein dekoriertes Tupel"/>
<node CREATED="1703803953288" ID="ID_952253872" MODIFIED="1703803963778" TEXT="kann Gleichheit/Ungleichheit der Gruppe erkennen"/>
<node CREATED="1703803964294" ID="ID_464725472" MODIFIED="1703803972779" TEXT="kann sich aus der Quelle neu konstruieren"/>
</node>
<node CREATED="1703803975007" ID="ID_1305670151" MODIFIED="1703804083592">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
trickreich: brauche <i>schleppenden State</i>
</p>
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<ul>
<li>
wenn das erste Element nicht den Default-Wert des Gruppierungskriteriums hat &#10233; mu&#223; einmal pullen und neu aufsetzen
</li>
<li>
wenn quelle bereits hinter dem letzten Element steht &#10233; gibt noch das letzte gruppierte Element aus
</li>
<li>
danach mu&#223; noch genau eine Iteration erlaubt werden
</li>
</ul>
</body>
</html></richcontent>
</node>
<node COLOR="#5b280f" CREATED="1703804085223" ID="ID_1512834256" MODIFIED="1703804125235" TEXT="YAGNI">
<arrowlink COLOR="#f53565" DESTINATION="ID_1449254847" ENDARROW="Default" ENDINCLINATION="-19;118;" ID="Arrow_ID_669204155" STARTARROW="None" STARTINCLINATION="-120;-17;"/>
<icon BUILTIN="stop-sign"/>
<node CREATED="1703804127296" ID="ID_903201477" MODIFIED="1703804140570" TEXT="schreibe jetzt schon eine Bildschirmseite voll"/>
<node CREATED="1703804141118" ID="ID_1745716277" MODIFIED="1703804152600" TEXT="mu&#xdf; jetzt auch noch einen Gruppen-Typ definieren"/>
<node CREATED="1703804153155" ID="ID_1768805808" MODIFIED="1703804159399" TEXT="und das ganze generisch machen..."/>
<node CREATED="1703804159924" ID="ID_837632427" MODIFIED="1703804173357" TEXT="mit einer dedizierten For-Loop w&#xe4;re ich schon fertig"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1703804201974" ID="ID_1363214026" MODIFIED="1703807936511" TEXT="stattdessen: direkt einen Vektor aggregieren und zur&#xfc;ckgeben">
<icon BUILTIN="yes"/>
<node CREATED="1703806119013" ID="ID_848627487" MODIFIED="1703806130911" TEXT="For-Schleife mit schleppendem Aggregat"/>
<node CREATED="1703807871832" ID="ID_414635297" MODIFIED="1703807880606" TEXT="Gewichte pro Level aufsummieren"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702944922179" ID="ID_424913055" MODIFIED="1702944931701" TEXT="Fall2: concurrent-X">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1703794147800" ID="ID_875844018" MODIFIED="1703797733272" TEXT="schwierige Frage: wie die Last verteilen?">
<icon BUILTIN="help"/>
<node CREATED="1703794161470" ID="ID_1249728332" MODIFIED="1703794182703" TEXT="&#xbb;box stacking problem&#xab;">
<node CREATED="1703794185949" ID="ID_134134437" MODIFIED="1703794208947" TEXT="optimale L&#xf6;sung ist nichttrivial"/>
<node CREATED="1703794218994" ID="ID_360549860" MODIFIED="1703794248013" TEXT="Scheduler findet sicher nicht die optimale L&#xf6;sung"/>
<node CREATED="1703794248634" ID="ID_1922683146" MODIFIED="1703794249374" TEXT="(er sucht sie auch nicht)"/>
</node>
<node CREATED="1703794290357" ID="ID_1117519154" MODIFIED="1703794314309" TEXT="mu&#xdf; ehr fragen: was w&#xe4;re ein fairer Referenzwert?"/>
<node CREATED="1703796820215" ID="ID_1463293935" MODIFIED="1703796876018" TEXT="man k&#xf6;nnte die &#x2211;Last durch den theoretischen lokalen Beschleunigungsfaktor teilen">
<arrowlink DESTINATION="ID_726786929" ENDARROW="Default" ENDINCLINATION="158;7;" ID="Arrow_ID_134124822" STARTARROW="None" STARTINCLINATION="141;19;"/>
<node CREATED="1703796910931" ID="ID_327811012" MODIFIED="1703796920438" TEXT="das w&#xe4;re dann die theoretische Untergrenze"/>
<node CREATED="1703796921001" ID="ID_552560191" MODIFIED="1703796937755" TEXT="die ein reales &#xbb;box stacking&#xab; nicht erreichen kann"/>
<node CREATED="1703797666862" ID="ID_904711641" MODIFIED="1703797688398" TEXT="Ganz ensprechend dazu, da&#xdf; man auch keinen leer-Aufwand berechnet"/>
<node CREATED="1703797698137" ID="ID_1856874446" MODIFIED="1703797722175" TEXT="&#x27f9; eine reale Berechnung wird immer demgegen&#xfc;ber zur&#xfc;ckfallen"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1703794695013" ID="ID_599869061" MODIFIED="1703794819987" TEXT="theoretischer Concurrency-Faktor">
<linktarget COLOR="#497dbb" DESTINATION="ID_599869061" ENDARROW="Default" ENDINCLINATION="-146;-288;" ID="Arrow_ID_312816279" SOURCE="ID_1945693212" STARTARROW="None" STARTINCLINATION="523;22;"/>
<icon BUILTIN="idea"/>
<node CREATED="1702265262323" ID="ID_1908727445" MODIFIED="1703794715295" TEXT="prinzipiell m&#xf6;glich ... die Datenstruktur ist g&#xfc;nstig">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
und zwar der Umstand, da&#223; die Nodes <i>innerhalb eines Levels stets voneinander unabh&#228;ngig sind; </i>deshalb sind <i>zumindest</i>&#160;diese Nodes komplett parallelisierbar
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1702265418472" ID="ID_565310505" MODIFIED="1703794852295" TEXT="&#x2205; Beschleunigungsfaktor: &#x2205;w / floor(&#x2205;w/concurrency)">
<icon BUILTIN="forward"/>
</node>
<node CREATED="1703794853512" ID="ID_726786929" MODIFIED="1703796876018" TEXT="lokaler Beschleunigungsfaktor: w / (1+floor((w-1)/concurrency) )">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_726786929" ENDARROW="Default" ENDINCLINATION="158;7;" ID="Arrow_ID_134124822" SOURCE="ID_1463293935" STARTARROW="None" STARTINCLINATION="141;19;"/>
<icon BUILTIN="forward"/>
</node>
</node>
<node CREATED="1703797738652" ID="ID_956546780" MODIFIED="1703797835531" TEXT="l&#xe4;&#xdf;t sich also on-the-fly berechnen"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702945662283" ID="ID_557005311" MODIFIED="1702945685743" TEXT="M&#xf6;glichkeit f&#xfc;r hierauf abstellendes genaues Scheduling">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702945698917" ID="ID_617955437" MODIFIED="1702945713108" TEXT="ScheduleCtx stellt dieses Feature bereit">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1703797401009" ID="ID_1091284884" MODIFIED="1703797408236" TEXT="implementiert durch eine LUT"/>
<node CREATED="1703797437806" ID="ID_139711050" MODIFIED="1703797452286" TEXT="welche auch gleich die Integration (Gesamtzeit) mit beinhaltet"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702945713771" ID="ID_66050639" MODIFIED="1702945728105" TEXT="verwendet hierzu die Auswertung aus Chain-Load">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1703797265083" ID="ID_117426514" MODIFIED="1703797283385" TEXT="diese kann eine Iterations-Berechnung (one-pass) sein"/>
<node CREATED="1703797286217" ID="ID_1277790232" MODIFIED="1703797356569" TEXT="die Zahl der Level ist bekannt &#x2014; also kann man die in eine fixe Tabelle ziehen"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702945731584" ID="ID_572123244" MODIFIED="1702945745735" TEXT="stress-Faktor relativ zu diesem Schema">
<icon BUILTIN="flag-yellow"/>
@ -108718,7 +108778,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1703201359469" ID="ID_6793831" MODIFIED="1703201385133" TEXT="selbst mit 80&#xb5;s &#x27f6; 400&#xb5;s pro Job &#xfc;berholt er sich"/>
<node CREATED="1703201392097" ID="ID_892982026" MODIFIED="1703201398492" TEXT="mit kleineren Chunks arbeiten...."/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1703201400744" ID="ID_1792520072" MODIFIED="1703201429793" TEXT="f&#xfc;hrt in eine Kette von re-entrant-Calls sich selbst &#xfc;berholener Planer">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1703201400744" ID="ID_1792520072" MODIFIED="1703201429793" TEXT="f&#xfc;hrt in eine Kette von re-entrant-Calls sich selbst &#xfc;berholender Planer">
<icon BUILTIN="forward"/>
</node>
</node>
@ -110099,6 +110159,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1703798050746" ID="ID_339326725" MODIFIED="1703798059114" TEXT="Scheduler-Stre&#xdf;tests">
<icon BUILTIN="hourglass"/>
</node>
<node CREATED="1702954431054" ID="ID_669378388" MODIFIED="1702954436305" TEXT="offen/aufzukl&#xe4;ren">
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1702954476683" ID="ID_1030796415" MODIFIED="1702954846789" TEXT="Verhalten von Workern unter concurrency">
<richcontent TYPE="NOTE"><html>
@ -110384,16 +110447,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1703725087865" ID="ID_322192355" MODIFIED="1703725131032">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
denn im regul&#228;ren Betrieb <i>sollen </i>Jobs immer <i>aus einem Planungs-Job heraus</i>&#160;eingestellt werden
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1703548692756" ID="ID_236628457" MODIFIED="1703548745515" TEXT="aber postChain w&#xe4;re dann wirklich ungesch&#xfc;tzt, sollte es von Au&#xdf;en aufgerufen werden">
@ -110582,18 +110642,28 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703193198681" ID="ID_174434221" MODIFIED="1703193218302" TEXT="deshalb brauchen wir kein Commit / keine Synchronisation"/>
</node>
<node CREATED="1703193103239" ID="ID_980714261" MODIFIED="1703193118743" TEXT="wenn diese Vorrausetzungen gebochen werden...">
<node CREATED="1703193120539" ID="ID_1260909748" MODIFIED="1703193145924" TEXT="kann der Planer seine eigenen Jobs ausf&#xfc;hren, falls ihre Startzeit bereits &#xfc;berstrichen ist"/>
<node COLOR="#5b280f" CREATED="1703193120539" ID="ID_1260909748" MODIFIED="1703782848608" TEXT="kann der Planer seine eigenen Jobs ausf&#xfc;hren, falls ihre Startzeit bereits &#xfc;berstrichen ist">
<icon BUILTIN="button_cancel"/>
<node COLOR="#435e98" CREATED="1703782852225" HGAP="25" ID="ID_1376541438" LINK="#ID_451970697" MODIFIED="1703782874828" TEXT="das wurde nun unterbunden" VSHIFT="3">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1703193146561" ID="ID_1804622382" MODIFIED="1703193166936" TEXT="dann kann das Schedule unvollst&#xe4;ndig sein; es fehlt die Dependency-Information"/>
<node CREATED="1703193175750" ID="ID_101176217" MODIFIED="1703193194712" TEXT="die weitere Berechnung verzichtet aber auf alle expliziten Checks">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1703035577113" ID="ID_164864018" MODIFIED="1703035611065">
<node CREATED="1703782893872" ID="ID_1290886466" MODIFIED="1703782909770" TEXT="Planer ist (nur) dadurch gesch&#xfc;tzt, da&#xdf; er selber ein Job ist">
<node CREATED="1703782912301" ID="ID_1245390094" MODIFIED="1703782935351" TEXT="und zwar ein META-Job &#x2014; der exlusiv l&#xe4;uft (unter Grooming-Token)"/>
<node CREATED="1703782943545" ID="ID_993085138" MODIFIED="1703782956030" TEXT="der Planer hat eine Deadline, ist aber als &#xbb;compulsory&#xab; markiert"/>
<node CREATED="1703782956827" ID="ID_1908286139" LINK="#ID_748059800" MODIFIED="1703783036224" TEXT="wird seine Deadline &#xfc;berfahren, so l&#xf6;st das eine &#xbb;Scheduler-Emergency&#xab; aus"/>
</node>
<node CREATED="1703035577113" ID="ID_164864018" MODIFIED="1703782767767">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
&#10233; <b>Forderung</b>: ein echer Planer mu&#223; das erkennen und abbrechen
&#10233; <b>Forderung</b>: ein realer Planer mu&#223; das erkennen und abbrechen
</p>
</body>
</html></richcontent>
@ -111309,7 +111379,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1698433228231" HGAP="32" ID="ID_1931146744" MODIFIED="1698433423425" TEXT="denn wenn ein Task mal im Scheuler ist &#x2014; hat er Chancen, Kapazit&#xe4;t zu erlangen" VSHIFT="-1">
<icon BUILTIN="full-2"/>
</node>
<node CREATED="1698433311382" HGAP="24" ID="ID_788626614" MODIFIED="1698433453837" TEXT="allerdings erforder Kapazit&#xe4;ts-Steuerung eine Priorisierung &#x2014; und zwar segmentweise">
<node CREATED="1698433311382" HGAP="24" ID="ID_788626614" MODIFIED="1698433453837" TEXT="allerdings erfordert Kapazit&#xe4;ts-Steuerung eine Priorisierung &#x2014; und zwar segmentweise">
<icon BUILTIN="full-3"/>
</node>
<node CREATED="1698433349337" ID="ID_773792225" MODIFIED="1698433434845" TEXT="also kann man mit Tasks auch segmentweise &#x201e;schraffieren&#x201c;">