From Concurrent Constraint Programming to Concurrent Functional Programming with Transients Summer...
-
Upload
garey-pearson -
Category
Documents
-
view
248 -
download
0
Transcript of From Concurrent Constraint Programming to Concurrent Functional Programming with Transients Summer...
FromConcurrent Constraint Programming
to Concurrent Functional Programming
with Transients
Summer School of Constraints in Computational Logics Gif-sur-Yvette, France, 5-8 September 1999
Gert SmolkaUniversität des Saarlandes
Saarbrücken, Germany
2
What can LP and CCP contribute to the design of high-level, general-purpose
programming languages?
Background:
Development of Oz and Mozart (1991-1998)
LP : Logic Programming
CCP : Concurrent Constraint Programming
4
History of CCP
• Automated Theorem Proving• Logic Programming (1974)• Constraint Logic Programming (1982)• Concurrent Logic Programming (1983)• Concurrent Constraint Programming (1987)
5
Logic Programming
• Horn clauses as programming language (Kowalski 1974)• Simple, expressive, new• Operational semantics = declarative semantics• Don't know choice, logic variables, unification• Prolog (Colmerauer 1972)• Processing of natural language
6
Constraint Logic Programming
• Solve combinatorial problems• Built-in numbers• Constraint solving as generalization of unification• Constraint propagation• Prolog II (Colmerauer 1982), CHIP (1987)• CLP(X) (Jaffer/Lassez 1987)
• ILOG Solver (C++ Library)• Constraint programming as a research discipline
7
Concurrent Logic Programming
• Program operating systems (Jap. 5th Gen. Project)• Exploit massively parallel hardware• Concurrent Prolog (Shapiro 1983), GHC (Ueda 1986)
8
Concurrent Constraint Programming
• Unified theory – ALPS (Maher 1987)– CC (Saraswat 1989)– OPM (Smolka 1995)
• Unified programming languages– AKL (1992)– Oz (1994, 1997)
9
Constraints
• Set of values Value• Set of variables Var• Assignments are functions Var Value• Abstract constraint is a set of assignments• Concrete constraint is a syntactic object (e.g., x+y=z)
that denotes an abstract constraint• Constraint represents (possibly partial) information
about the values of variables• Constraint system: Values and concrete constraints
closed under intersection and existential quantification
10
Constraint Store
• Holds abstract constraint (satisfiable)• Operations
– New variable (i.e., unconstrained)– Tell constraint (success, failure)– Ask constraint (entailed, disentailed, undetermined)– Show information about variables
11
Computational Setup
• Transition system
C1 C2 C3 C4 . . .
• Configuration
(state of store, states of agents)• Termination with success or failure• Don't know choices
Actor . . . Actor
Constraint Store
12
Programs
• Actor statements a ::= new x in a
tell c
if c1a1 [] c2a2
a1 | a2
a1 + a2
p(x)
• Procedure definitions
p(x) :- a
13
CCP is Good Research Idealization
• Models essentials of constraint and concurrent LP• Valuable background for Constraint Programming• Potential for massive parallelism
14
From CC to OPM
• Constraint store unrealistic for numeric values– Propagators
• Communication based on logic streams unrealistic– State
• Primitive procedures– First-class procedures
• Don't know choices not encapsulated– Spaces
CC : Concurrent Constraints [Saraswat 89]OPM : Oz Programming Model [Smolka 95]
15
Still, CCP is not well-suited as a basis for
programming languagedue to
lack of explicit functional structure
• Input -> Output (monotone side effects)• Safe binding of variables (unsave tell)• Static typing with parametric
and subtype polymorphism
16
Programming Models versus Programming Languages
• A programming model is a research idealizationthat has nice properties (science)– functional programming, strict or lazy– logic programming, constraint or concurrent– concurrent calculi based on channels
• A programming language is a tool that should support several programming models (engineering)
18
ML + Threads + Transients
• ML (SML or Objective Caml)– Functional programming language, eager– Types and modules– State and exceptions
• SML has formal definition• Objective Caml has
– objects and classes– threads and channels
21
Values, Resources, Addresses
• Values are stateless entities– numbers, tuples, procedures, ...– can be replicated
• Resources are stateful entities– cells, channels, threads, file systems, ...– cannot be replicated (their states can)
• Addresses are values that identify resources
22
Pointers (Simple Resource)
type 'a ref
val ref : 'a -> 'a ref
val deref : 'a ref -> 'a
val assign : 'a ref * 'a -> unit
val exchange : 'a ref * 'a -> 'a
NB: exchange is atomic
23
Channels (Synchronizing Resource)
type 'a channel
val channel : unit -> 'a channel
val put : 'a channel * 'a -> unit
val get : 'a channel -> 'a
• Channel is queue with synchronization• Get operation blocks if channel is empty• Theoretically well-investigated: CCS, Pi-calculus
24
Threads (Active Resource)
type thread
val thread : (unit -> unit) -> thread
val suspend : thread -> unit
val resume : thread -> unit
val kill : thread -> unit
25
Concurrency Issues
• Threads perform atomic computation steps• Interleaving semantics• Operations on resources are atomic• Operations on resources may block• Nondeterminism (e.g., concurrent puts)• Fairness
– advance threads that can advance– serve competing gets fairly
26
Plan
1. FP + concurrency
2. Futures (Multilisp, Halstead 1985)
3. Promises
4. Streams
5. Channels
27
Concurrent Evaluation with Futures
conc exp
• Spawns new thread that evaluates exp• Returns future that acts a placeholder for result of exp• Operations block when applied to futures,
resume automatically• Provides for parallel execution and latency tolerance
30
Concurrent Evaluation with Futures
• Can evaluate e1 and e2 in parallel• Can start application before value of e2 is
obtained• With futures, sequential code can be run
concurrently with automatic "latest possible time" synchronization
let val x = conc e2
in e1 x ende1 e2
31
Explicit Synchronization
1. Evaluate e1 and e2 concurrently
2. Evaluate e3 after evaluation of e1 and e2 has finished
case
(conc(e1;()), conc(e2;()))
of
((),()) then e3
32
By-need Evaluation with Futures
byneed exp
• Same as conc exp, but slightly different control• Thread evaluating exp only starts once future is needed• Provides for lazy functional programming
34
0::1::2::3::4::5:: ...
future1::future1::2::future1::2::3::future1::2::3::4::future
Lazy Stream of Natural Numbers
36
Operational Semantics
• env, exp value pure functional , env, exp value, ' plus state , threads threads, ' plus threads , , threads threads, ', ' plus futures
37
Futures Formaly
• Assume set of futures (addresses of resources)• Closed values: values of functional language• Values = closed values + open values Future fin Value
• Open values can be updated wrt
38
Plan
1. FP + concurrency
2. Futures
3. Promises (typed substitute for logic variables)
4. Streams
5. Channels
39
Promises
type 'a promise
val promise : unit -> 'a promise
val fulfill : 'a promise * 'a -> unit
val future : 'a promise -> 'a
• Promise is a single assignment pointer• fulfill binds promise to value• future returns value of promise or its future• fulfill raises exception if promise is already bound
40
Concurrent Evaluation with Promises
conc : (unit -> 'a) -> 'a
fun conc f = let val p = promise() in thread fulfill(p,f()); future p end
41
Recursion with Promises
val rec x = 1::x
let val p = promise() val x = 1::future pin fulfill(p,x); xend
42
Difference Lists with Promises
type 'a dlist
val dlist : unit -> 'a dlist
val cons : 'a * 'a dlist -> 'a dlist
val append : 'a dlist * 'a dlist -> 'a dlist
val close : 'a dlist * 'a list -> 'a list
val export : 'a dlist -> 'a list
• All operations are constant time• Exactly one append or close per dlist
43
type 'a dlist = 'a list * 'a list promise
fun dlist() = let val p = promise() in (future p, p) end
fun cons(x,(xs,p)) = (x::xs,p)
fun append((xs,p),(ys,p')) = (fulfill(p,ys); (xs,p'))
fun close((xs,p),ys) = (fulfill(p,ys); xs)
fun export(xs,_) = xs
44
Promise Types are Invariant wrt Subtyping
fulfill: 'a promise * 'b -> unit ('b <:'a)
future : 'a promise -> 'b ('a <:'b)
• Typing of promises is exactly as typing of references• Must not have polymorphic promises (comes for free
due to value restriction on polymorphism and generator function)
45
Logic Variables are Inconsistent with Subtyping
val lvar : unit -> 'a
val bind : 'a * 'a -> unit
let val x:colorPoint = lvar()in bind(x:point, p:point); printColorPoint(x:colorPoint)end
46
Futures and Exceptions
• byneed exp• Futures have 3 states: undetermined, succeeded,failed• Failed future is associated with an exception• Access to failed future raises associated exception• If exp of byneed exp fails with an exception exn, the
by-need future is failed with exn
• Design trade-off between – implicit blocking– explicit error
47
Failed Promises
val fail : 'a promise * exn -> unit
• Failing a promise includes failing its associated future• Application of fail to a fulfilled or already failed
promise raises an exception
48
Plan
1. FP + concurrency
2. Futures
3. Promises
4. Streams (concurrent logic programming)
5. Channels
50
Concurrent Stream Transformer
fun newPlus(xs,ys) =
let
val p = promise()
in
thread plus(xs,ys,p);
future p
end
51
plus : 'a list * 'a list * 'a promise -> unit
fun plus(x::xr, y::yr, p) =
plus(xr, yr, next(p,x+y))
52
next : 'a promise * 'a -> 'a promise
fun next(p,x) = let val p' = promise() in fulfill(p, x::(future p')); p' end
54
Two possibilities
1. Pointers with exchange– Mailbox feeding output stream– One transfer loop for every input stream
2. Additional primitives for futures– Don't need pointers– Similar to how it is done in Concurrent Logic
Programming
55
Primitives for Nondeterministic Choice
val isFuture : 'a -> bool
val waitOne : 'a * 'b -> 'a
waitOne blocks until at least one argumentis a non-future
56
fun merge(xs, ys, p) =
if isFuture(waitOne(xs,ys))
then merge(xs, tl ys, next(p,hd ys))
else merge(ys, tl xs, next(p,hd xs))
57
Time-outs
timeout: ’a * int -> ’a option
alarm: int -> unit
fun timeout(x, t) = if isfuture(waitOne(x, alarm t)) then NONE else SOME x
58
Plan
1. FP + concurrency
2. Futures
3. Promises
4. Streams
5. Channels
NB: Fair channels can be done with blocking promises
59
Channels
type 'a channel
val channel : unit -> 'a channel
val put : 'a channel * 'a -> unit
val get : 'a channel -> 'a
• Channel is queue with synchronization• Get operation blocks if channel is empty• Blocked threads are served fairly (FIFO)
61
Mailboxes
type 'a mailbox
val mailbox : unit -> 'a mailbox * 'a list
val put : 'a mailbox * 'a -> unit
Provide for many-to-many communication
65
type 'a mailbox = 'a list promise ref
fun mailbox() = let val p = promise() in (ref p, future p) end
fun put(r,x) = let val p = promise() in fulfill(exchange(r,p), x::future p) end
66
Dispensers
type 'a dispenser
val dispenser : 'a list -> 'a dispenser
val get : 'a dispenser -> 'a
• Get operation blocks if next message is not yet available
• Blocked threads are served fairly (FIFO)
70
type 'a dispenser = 'a list ref
fun dispenser xs = ref xs
fun get r = let val p = promise() val x::xr = exchange(r, future p) in fulfill(p,xr); x end
71
Summary
• ML + threads + transients• Transients
– Futures with eager provider– Futures with lazy provider– Futures with promise as provider
• Provides for– Automatic "latest possible time" synchronization of
sequential code– Lazy evaluation– Top-down construction of values (e.g., streams)– Concurrent data structures (e.g., channels)
72
Performance Costs of Futures
• Not observable for emulating implementation (Mozart, OCaml)
• Low for compiling implementation provided static analysis is employed
• Futures are omnipresent• Analogous to lazy closures