; lib/artdag/cost.sx — cost model for the scheduler: per-node weights, critical ; path (min makespan with unlimited parallelism), plan makespan under batching/cap, ; total serial work, and the resulting speedup. Costs come from an injected ; cost-fn (op params) -> number so media-op costs stay opaque. Depends on dag.sx. (define artdag/const-cost (fn (op params) 1)) (define artdag/op-cost (fn (table) (fn (op params) (if (has-key? table op) (get table op) 1)))) (define artdag/-node-cost (fn (dag cost-fn id) (let ((n (artdag/dag-get dag id))) (cost-fn (artdag/node-op n) (artdag/node-params n))))) (define artdag/-max (fn (xs) (reduce (fn (mx x) (if (> x mx) x mx)) 0 xs))) ; longest weighted path through the dag = makespan with unlimited workers. (define artdag/critical-path (fn (dag cost-fn) (let ((ft (reduce (fn (m id) (let ((maxdep (artdag/-max (map (fn (d) (get m d)) (artdag/node-inputs (artdag/dag-get dag id)))))) (assoc m id (+ (artdag/-node-cost dag cost-fn id) maxdep)))) {} (artdag/dag-order dag)))) (artdag/-max (map (fn (id) (get ft id)) (keys ft)))))) ; estimated wall-clock for a plan: each batch runs in parallel (costs its ; slowest node), batches run in sequence. (define artdag/makespan (fn (dag plan cost-fn) (reduce (fn (total batch) (+ total (artdag/-max (map (fn (id) (artdag/-node-cost dag cost-fn id)) batch)))) 0 plan))) ; total serial work = sum of all node costs. (define artdag/total-work (fn (dag cost-fn) (reduce (fn (s id) (+ s (artdag/-node-cost dag cost-fn id))) 0 (keys (artdag/dag-nodes dag))))) ; speedup of a plan vs running everything serially. (define artdag/speedup (fn (dag plan cost-fn) (/ (artdag/total-work dag cost-fn) (artdag/makespan dag plan cost-fn))))