Propagators Edward Kmett Yow! LambdaJam 2016
Semilattices • Commutative: a • Commutative: a ⋁ b = b ⋁ a • Associative: (a ⋁ b) ⋁ c = a ⋁ (b ⋁ c) • Associative: (a • Idempotent: a ⋁ a = a • Idempotent: a • Unital: a ⋁ ⟘ = ⟘ ⋁ a • Unital: a
Semilattices and Order • Ordering: a ⩽ b = ∃ c. a ⋁ c = b
Hasse Diagrams • Covering: a ⋖ b = a ⩽ b ⋏ ∄ c.a ⩽ c ⩽ b
Power Sets
Concept Lattices ⟙ boy man woman girl adult male child female ⟘
Monotonicity • Monotonicity: a ⩽ b implies f(a) ⩽ f(b) Every function in Haskell is monotone
What is a Propagator? A A propagator is a monotone function between join-semilattices. between join-semilattices. A A propagator network is a hypergraph with propagators for hyperedges, and join- propagators for hyperedges, and join- semilattices for nodes. semilattices for nodes. 10
Naïve Propagation • Whenever we a node gains information queue all propagators that lead out of that node to fire. • When a propagator fires, calculate its output and then join them with the values in the targets. • Repeat.
Why Propagate? • If every semilattice is finite, then naïve propagation terminates and yields a deterministic result , regardless of scheduling strategy, redundant firings, or evaluation order.
“Computer scientists commonly choose models which have bottoms, but prefer them topless.”
Ascending Chain Condition • Ascending Chain Condition (ACC): Given a 1 ⩽ a 2 ⩽ a 3 ⩽ … There exists n such that a n = a n +1 = a n +2 = … • Every strictly ascending sequence of elements terminates.
Why Propagate? • If every semilattice satisfies an ascending chain condition, then naïve propagation terminates and yields a deterministic result , regardless of scheduling strategy, redundant firings, or evaluation order.
Promises, Promises
Filters (Upward Closed Sets)
Threshold Reads
LVish Lets you: • fork :: Par a -> Par () • Create L-Vars • Write to Lattice Variables • Perform Threshold Reads
Inflationary Writes Suffice • Inflationary: f(x) ⩾ x
Building Propagators Par computations yield monotone effects
The Problem with I-Vars Problem: Par does not play nice. readIVar :: IVar s a -> Par s a but we we want readIVar :: IVar s a -> a Par doesn’t mix well with lazy IO or even laziness in general. Solution: Build Par with MVars, not a fancy work-stealing deque.
The Problem with M-Vars Problem: Too much overhead! Solution: We can build capability-local MVars by hacking up custom primitives and get most of the performance of the unthreaded runtime system while threaded.
The Problem with L-Vars Problem: Too many listeners get awoken upon every update! Solution: Decompose them into smaller LVars and finer-grained tasks.
Breaking Apart L-Vars • L-Vars are a sort of filtered channel, the lattice is the filter. • We an implement the interesting ones out of a very small set of core primitives and more threads, reducing contention: • Maps from keys to listeners or other lattices for fast publish-subscribe • CmRDT style bump-counters with an integer priority queue of listeners. • These suffice to implement all of the standard CRDTs!
Building the Primitives We just need to build a whole new class of wait-free (except for GC), population-oblivious, but capability- aware algorithms in order to execute these primitives efficiently as the number of cores rise! (Out of scope for this talk)
Decomposing Threshold Reads T F T F ⟘ ⟘ T F ⟘
Propagator Applications Promises SAT Solving Datalog CvRDTs Constraint Programming Unification Interval Arithmetic Integer Linear Programming Cone Programming Hybrid Constraint Linear Programming Functional Reactive Programming Probabilistic Programming Provenance Tracking Incremental Programming unamb …
Transferring Results Idea: Steal the features that make dedicated solvers for each of these specialized domains fast and apply them to the other domains!
SAT Solving • Since around 2001, most SAT Solvers use techniques evolved in zChaff and since honed in solvers such as miniSAT . • The techniques we want to steal are: • Conflict Directed Clause Learning • The Two Watched Literal Scheme
SAT Solving (x ⋁ ¬y ⋁ z) ⋀ (¬x ⋁ y ⋁ ¬z) ⋀ (x ⋁ ¬z ⋁ w) Unit Propagation: (x) implies x = True Empty Clauses: () implies we need to learn a clause and backtrack.
n-Watched Literal Wake-Up • Many Propagators do nothing until all but (n-1) of their inputs are non- ⊥ : p(…, ⊥ ,…) = ⊥ • Track only n known-to-be ⊥ arguments, only trigger the propagator when those arguments increase, not when any argument increases.
n-Watched Literal Collection When all of the inputs of a propagator are covered by top, the propagator can never fire again and can be removed from the network. p(x 1 ,x 2 ,…,x n ) ∀ n . x n ⋖ ⟙ • Covering: a ⋖ b = a ⩽ b ⋏ ∄ c.a ⩽ c ⩽ b
Constraint Programming • x ∈ {1..5} • y ∈ {1..5} • x <= y • Establish “arc consistency” • Guess and backtrack like SAT
AC-3 Input: A set of variables X A set of domains D(x) for each variable x in X. D(x) contains vx0, vx1... vxn, the possible values of x A set of unary constraints R1(x) on variable x that must be satisfied A set of binary constraints R2(x, y) on variables x and y that must be satisfied function ac3 (X, D, R1, R2) for each x in X D(x) := { x in D(x) | R1(x) } worklist := { (x, y) | there exists a relation R2(x, y) or a relation R2(y, x) } do select any arc (x, y) from worklist worklist := worklist - (x, y) if arc-reduce (x, y) if D(x) is empty return failure else worklist := worklist + { (z, x) | z != y and there exists a relation R2(x, z) or a relation R2(z, x) } while worklist not empty function arc-reduce (x, y) bool change = false for each vx in D(x) find a value vy in D(y) such that vx and vy satisfy the constraint R2(x, y) if there is no such vy { D(x) := D(x) - vx change := true } return change
Constraint Programming • The classic algorithm for establishing arc consistency (AC-3) is a form of propagation. • Unit propagation is a special case.
Datalog: Naïve Evaluation ancestor(X,Y) :- parent(X,Y) ancestor(X,Z) :- ancestor(X,Y), parent(X,Z) parent(bob, nancy). parent(nancy, drew). parent(dan, nancy).
Datalog: Seminaïve Evaluation 1 ancestor(X,Y) :- parent(X,Y) 2 ancestor(X,Z) :- ancestor(X,Y), parent(X,Z) Δ n-1 ancestor(X,Z) :- Δ n ancestor(X,Y), parent(X,Z) 1 parent 2 ancestor
Implementing Δ • We need to store a Δ since the last time we fired each outbound propagator. • If no obvious scheme is available, there is a universal construction good for cells with many outbound propagators. • Build a mutable tree of outbound propagators, tracking monoidal annotations in the tree. Δ is a prefix sum. Merge updates into the tree on the left. • Optimize this further to share leaves when there is no update in between.
Topological Ordering • Evaluating propagators in topological order maximizes the size of the Δ s used, reducing the number of times we join against full tables. • Adding propagators or nodes to the network requires us to be able to compute a dynamic topological ordering. This requires Θ ( √ n ) time per update to store perfectly, but we don’t need perfection. • I conjecture there is a k -optimal evaluation strategy, for a small k .
Stratification • Datalog can be extended with “stratified negation” or more generally with arbitrary “stratified aggregation” operations. • These special edges aren’t allowed to participate in a cycle in the graph. If they do, blow up the world. • These special “stratifying” propagators need not be monotone.
CALM Conjecture (Consistency and Logical Modularity) “A program has an eventually consistent, coordination-free execution strategy if and only if it is expressible in (monotonic) Datalog” — Joe Hellerstein
Datalog Lessons • Seminaïve Evaluation • Topological Ordering • Stratification • Different justification for global termination. • The CALM Conjecture
CRDTs • Convergent replicated data types can be viewed a living in a distributed propagator network. • Lindsey Kuper and Chris Meiklejohn (among others) have been exploring this design space.
Further Topics • Pure threshold reads let us rederive and generalize Conal Elliott’s work on unamb • We can build a form of lazy sequential computations that can make more computations demand driven, which also always build monotone propagators.
. ? Any Questions
Resources http://web.mit.edu/~axch/www/art.pdf • https://www.cs.indiana.edu/~lkuper/papers/lvars-fhpc13.pdf • https://lasp-lang.org/ • https://github.com/ekmett/propagators • https://github.com/ekmett/models • https://github.com/ekmett/concurrent • https://github.com/ekmett/promises • https://hackage.haskell.org/package/unamb •
Extra Slides
Recommend
More recommend