You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let a user annotate the cost of a function to decide if it makes sense spawn or not.
Example:
var m =createMaster()
procspm(): auto {.opUS:100.} =discard## expect it takes ~0010 nsprocbaz(): auto {.opUS:050.} =discard## expect it takes ~0020 nsprocbar(): auto {.opUS:010.} =discard## expect it takes ~0100 nsprocfoo(): auto {.opUS:001.} =discard## expect it takes ~1000 ns
m.awaitAll:
for i in0..1_000_000:
m.spawnspm()
m.spawnbaz()
m.spawnbar()
m.spawnfoo()
import std / macros
templateopUS(i:int=1) {.pragma.} # operations / microsecondtypeMaster*=object## Masters can spawn new tasks inside an `awaitAll` block....
budget: Atomic[int]
constThreadBudget*{.intdefine.} =1000## 1us avg time in nanoseconds we loose to scheduling a taskmacrogetOpUs(fn: typed; cp: typed{nkSym}): int=for p in fn[0].getImpl().pragma:
if p.len >0and p[0].kind == nnkSym and p[0] == cp:
return p[1]
returnnewLit(1)
funcfnCost(opUs: int): int=1000div opUs
templatespawnImplNoRes(master: varMaster; fn: typed) =let cost =getOpUS(fn, opUS).fnCost
let budget = master.budget.fetchSub(cost) - cost
if budget >0orstillHaveTime(master):
if budget <0andshouldSend(master):
master.budget.store(ThreadBudget)
taskCreated master
sendPoolTask(m: addr(master), t: toTask(fn), result: nil)
else:
fn
The idea is developer specifying the cost, not change the ThreadBudget. But for benchmarking, compile it with -d:ThreadBudget:1 (1ns) to have more spawns, -d:ThreadBudget:1000 (1000ns) to have less spawns.
My local results:
-d:ThreadBudget:00001 ~ 1.400sec (spawn after burn 001ns of our budget)
-d:ThreadBudget:00010 ~ 0.700sec (spawn after burn 010ns of our budget)
-d:ThreadBudget:00100 ~ 0.100sec (spawn after burn 100ns of our budget)
-d:ThreadBudget:01000 ~ 0.030sec (spawn after burn 001us of our budget)
-d:ThreadBudget:10000 ~ 0.010sec (spawn after burn 010us of our budget)
TODO:
budget should be per MasterHandle not per master, README dfs as example.
The operation per micro second (opUS) is confusing
Review the stillHaveTime logic.
Sane defaults (according to old local test spawn takes ~1us)
Alternative:
The initial idea was to use the effect system to track 'IO', and only spawn if function does IO...
Or use the effect system to sum up the costs (have no idea if it is possible)
The text was updated successfully, but these errors were encountered:
Let a user annotate the cost of a function to decide if it makes sense spawn or not.
Example:
POC:
malebolgia.nim (full file)
The idea is developer specifying the cost, not change the ThreadBudget. But for benchmarking, compile it with
-d:ThreadBudget:1
(1ns) to have more spawns,-d:ThreadBudget:1000
(1000ns) to have less spawns.My local results:
-d:ThreadBudget:00001
~ 1.400sec (spawn after burn 001ns of our budget)-d:ThreadBudget:00010
~ 0.700sec (spawn after burn 010ns of our budget)-d:ThreadBudget:00100
~ 0.100sec (spawn after burn 100ns of our budget)-d:ThreadBudget:01000
~ 0.030sec (spawn after burn 001us of our budget)-d:ThreadBudget:10000
~ 0.010sec (spawn after burn 010us of our budget)TODO:
dfs
as example.opUS
) is confusingstillHaveTime
logic.Alternative:
The initial idea was to use the effect system to track 'IO', and only spawn if function does IO...
Or use the effect system to sum up the costs (have no idea if it is possible)
The text was updated successfully, but these errors were encountered: