n - KTH

advertisement
SUMMARY
Christian Schulte
cschulte@kth.se
Software and Computer Systems
School of Information and Communication Technology
KTH – Royal Institute of Technology
Stockholm, Sweden
ID1218 Lecture 12
2009-12-07
Overview
2


Only functional programming summary
C++ summary and example questions, see Lecture
10
ID1218, Christian Schulte
L12 2009-12-07
Functional Programming
3

Evaluate functions returning results
 executed

by MiniErlang machine
Techniques
 recursion
with last-call-optimization
 pattern matching
 list processing
 higher-order programming
 accumulators
ID1218, Christian Schulte
L12 2009-12-07
4
MiniErlang Machine
ID1218, Christian Schulte
L12 2009-12-07
MiniErlang: Values, Expressions,
Instructions
5


MiniErlang values
V := int | [] | [ V1 | V2 ]
MiniErlang expressions
E := int | [] | [ E1 | E2 ]
| X | F(E1,…, En)
 where

X stands for a variable
MiniErlang instructions
CONS, CALL
ID1218, Christian Schulte
L12 2009-12-07
MiniErlang Machine
6

MiniErlang machine
Es ; Vs → Es’ ; Vs’
transforms a pair (separated by ;) of

expression stack Es and value stack Vs
into a new pair of


according to topmost element of Es
Initial configuration:


expression stack Es’ and value stack Vs’
expression we want to evaluate on expression stack
Final configuration:

single value as result on value stack
ID1218, Christian Schulte
L12 2009-12-07
MiniErlang: Expressions
7

Evaluate values
V  Er ; Vs
 provided


→
Er ; V  Vs
V is a value
Evaluate list expression
[E1|E2]Er ; Vs
→ E1E2CONSEr ; Vs
Evaluate function call
F(E1, …, En)Er ; Vs
→ E1…EnCALL(F/n)Er ; Vs
ID1218, Christian Schulte
L12 2009-12-07
MiniErlang: Instructions
8


CONS instruction
CONSEr ; V1V2Vs
→ Er ; [V2|V1]Vs
CALL instruction
CALL(F/n)Er ; V1…VnVs
→ s(E)Er ; Vs
 F(P1,
…, Pn) -> E first clause of F/n such that
[P1, …, Pn] matches [Vn, …,V1] with substitution s
ID1218, Christian Schulte
L12 2009-12-07
MiniErlang Pattern Matching
9


Patterns
P :=
int
match(P,V)
|
[]
|
[ P1 | P2 ]
|
s:=try(P,V)
if errors or XV1, XV2 s withV1≠V2 then no else s
where
try(i,i)
try([],[])
try([P1|P2],[V1|V2])
try(X,V)
otherwise
=
=
= try(P1,V1)try(P2,V2)
= {XV}
= {error}
ID1218, Christian Schulte
L12 2009-12-07
X
Substitution
10

Defined over structure of expressions
s(i)
s([])
s([E1|E2])
s(F(E1, …, En))
s(X)
= i
= []
= [s(E1)|s(E2)]
= F(s(E1), …, s(En))
= if XV  s then V else X
ID1218, Christian Schulte
L12 2009-12-07
11
Iterative Computations
ID1218, Christian Schulte
L12 2009-12-07
A Better Length?
12
l([]) -> 0;
l([_|Xr]) -> 1+l(Xr).
l([],N) -> N;
l([_|Xr],N) -> l(Xr,N+1).


Two different functions: l/1 and l/2
Which one is better?
ID1218, Christian Schulte
L12 2009-12-07
Running l/1
13
l([1,2,3]) ; 
→
[1,2,3]CALL(l/1) ; 
→
CALL(l/1) ; [1,2,3]
→
1+l([2,3]) ; 
→
1l([2,3])ADD ; 
→
l([2,3])ADD ; 1
→
[2,3]CALL(l/1)ADD ; 1
→
CALL(l/1)ADD ; [2,3]1
→
1+l([3])ADD ; 1
→
1l([3])ADDADD ; 1
→
l([3])ADDADD ; 11
→
…
 requires stack space in the length of list
ID1218, Christian Schulte
L12 2009-12-07
Running l/2
14
l([1,2,3],0) ; 
→
[1,2,3]0 CALL(l/2) ; 
→
0 CALL(l/2) ; [1,2,3]
→
CALL(l/2) ; 0[1,2,3]
→
l([2,3],0+1) ; 
→
[2,3]0+1 CALL(l/2) ; 
→
0+1 CALL(l/2) ; [2,3]
→
01ADDCALL(l/2) ; [2,3]
→
1ADDCALL(l/2) ; 0[2,3]
→
ADDCALL(l/2) ; 10[2,3]
→
CALL(l/2) ; 1[2,3]
→
l([3],1+1) ; 
→
…
 requires constant stack space!
ID1218, Christian Schulte
L12 2009-12-07
Iterative Computations
15


Iterative computations run with
constant stack space
Make use of last optimization call
 correspond

to loops essentially
Tail recursive functions computed by iterative
computations
ID1218, Christian Schulte
L12 2009-12-07
16
Making Computations Iterative
Accumulators
ID1218, Christian Schulte
L12 2009-12-07
Recursive Function
17
pow(_,0) -> 1;
pow(X,N) -> X*pow(X,N-1).

Is not tail-recursive
 not
an iterative function
 uses stack space in order of N
ID1218, Christian Schulte
L12 2009-12-07
Using Accumulators
18


Accumulator stores intermediate result
Finding an accumulator amounts to finding an
invariant
 recursion
maintains invariant
 invariant must hold initially
 result must be obtainable from invariant
ID1218, Christian Schulte
L12 2009-12-07
State Invariant for pow/2
19


The invariant is
XN = pow(X,N-i) * Xi
where i is the current iteration
Capture invariant with accumulator for Xi
 initially
(i=0)
 finally (i=N)
1=X0
XN
ID1218, Christian Schulte
L12 2009-12-07
The pow/3 Function
20
pow(_,0,A) -> A;
pow(X,N,A) -> pow(X,N-1,X*A).
pow(X,N) -> pow(X,N,1).
ID1218, Christian Schulte
L12 2009-12-07
Naïve Reverse Function
21
rev([]) -> [];
rev([X|Xr]) -> app(rev(Xr),[X]).

Some abbreviations
 r(Xs)
 Xs
++ Ys
for rev(Xs)
for app(Xs,Ys)
ID1218, Christian Schulte
L12 2009-12-07
Invariant for rev
22

Now it is easy to see that
rev([x1, …, xn])
=
rev([xi+1, …, xn]) ++ [xi, …, x1]
as we go along
ID1218, Christian Schulte
L12 2009-12-07
rev Final
23
rev([],Ys) ->
Ys;
rev([X|Xr],Ys) ->
rev(Xr,[X|Ys]).

Is tail recursive now

Cost: n+1 calls for list with n elements
ID1218, Christian Schulte
L12 2009-12-07
24
Higher-Order Programming
ID1218, Christian Schulte
L12 2009-12-07
Generic Procedures
25

Sorting a list
 in
increasing or decreasing order
 by number or phone book order (maybe even a Swedish
phone book!)
 sorting algorithm + order

Mapping a list of numbers
 to
list of square numbers
 to list of inverted numbers
 to list of square roots
…
ID1218, Christian Schulte
L12 2009-12-07
Map
26
map(_,[]) -> [];
map(F,[X|Xr]) -> [F(X)|map(F,Xr)].
msq(Xs) -> map(fun (X) -> X*X end, Xs).


Use map/2 for any mapping function!
Syntax of fun like case
ID1218, Christian Schulte
L12 2009-12-07
Using Map
27

Mapping to square numbers
map(fun (X) -> X*X end,[1,2,3])

Mapping to negative numbers
map(fun (X) -> -X end,[1,2,3])
ID1218, Christian Schulte
L12 2009-12-07
Other Examples
28

filter(F,Xs)
returns all elements of Xs for which F returns true

any(F,Xs)
tests whether Xs has an element for which F returns true

all(F,Xs)
tests whether F returns true for all elements of Xs
ID1218, Christian Schulte
L12 2009-12-07
Folding Lists
29

Consider computing the sum of list elements
 …or
the product
 …or all elements appended to a list
 …or the maximum
…

What do they have in common?

Consider example: sl
ID1218, Christian Schulte
L12 2009-12-07
Left-Folding
30

Two values define “folding”
 initial
value
0 for sl
 binary function + for sl

Left-folding foldl(F,[x1 , …, xn],S)
F(… F(F(S,x1),x2) …,xn)
or
(…((S F x1) F x2) … F xn)
ID1218, Christian Schulte
L12 2009-12-07
foldl
31
foldl(_,[],S) ->
S;
foldl(F,[X|Xr],S) ->
foldl(F,Xr,F(S,X)).
ID1218, Christian Schulte
L12 2009-12-07
Right-Folding
32

Two values define “folding”
 initial
value
 binary function

Right-folding foldr(F,[x1 … xn],S)
F(x1,F(x2, … F(xn,S)…))
or
x1F(x2 F( … (xn F S) … ))
ID1218, Christian Schulte
L12 2009-12-07
foldr
33
foldr(_,[],S)
-> S;
foldr(F,[X|Xr],S)
-> F(X,foldr(F,Xr,S)).
ID1218, Christian Schulte
L12 2009-12-07
34
Concurrency
ID1218, Christian Schulte
L12 2009-12-07
Erlang Concurrency Primitives
35

Creating processes
for function value F
 spawn(M,F,As) for function F in module M with
argument list As
 spawn(F)

Sending messages
 PID

! message
Receiving messages
 receive

… end with clauses
Who am I?
 self()
returns the PID of the current process
ID1218, Christian Schulte
L12 2009-12-07
Processes
36

Each process has a mailbox
incoming messages are stored in order of arrival
 sending puts message in mailbox


Processes are executed fairly
 if
a process can receive a message or compute…
…eventually, it will
 It will pretty soon…
 simple priorities available (low)
ID1218, Christian Schulte
L12 2009-12-07
Message Sending
37

Message sending P ! M is asynchronous
 the
sender does not wait until message has been processed
 continues execution immediately
 evaluates to M

When a process sends messages M1 and M2 to
same PID, they arrive in order in mailbox
 FIFO

ordering
When a process sends messages M1 and M2 to
different processes, order of arrival is undefined
ID1218, Christian Schulte
L12 2009-12-07
Message Receipt
38

Only receive inspects mailbox


Messages are processed in order of arrival


all messages are put into the mailbox
that is, receive processes mailbox in order
If the receive statement has a matching clause for the
first message
remove message and execute clause
 always choose the first matching clause



Otherwise, continue with next message
Unmatched messages are kept in original order
ID1218, Christian Schulte
L12 2009-12-07
39
Communication Patterns
ID1218, Christian Schulte
L12 2009-12-07
Broadcast
40
foreach(_,[]) -> void;
foreach(F,[X|Xr]) -> F(X),foreach(Xr).
broadcast(PIDs,M) ->
foreach(fun(PID) -> PID ! M end,PIDs).
ID1218, Christian Schulte
L12 2009-12-07
Broadcast With Ordered Reply
41
collect(PIDs,M) ->
map(fun (P) ->
P ! {self(),M},
receive
{P,Reply} -> Reply
end
end, PIDs).
 Collect a reply from all processes in order
ID1218, Christian Schulte
L12 2009-12-07
Low-latency Collect
42
collect(PIDs,M)
-> foreach(fun (P) ->
P ! M
end, PIDs),
map(fun (P) ->
receive {P,R} -> R end
end, PIDs).
 No order
ID1218, Christian Schulte
L12 2009-12-07
43
Coordination
ID1218, Christian Schulte
L12 2009-12-07
Protocols
44

Protocol: rules for sending and receiving messages
 programming

with processes
Examples
 broadcasting
messages to group of processes
 choosing a process

Important properties of protocols
 safety
 liveness
ID1218, Christian Schulte
L12 2009-12-07
Choosing a Process
45


Example: choosing the best lift, connection, …
More general: seeking agreement


coordinate execution
General idea:

Master




send message to all slaves containing reply PID
select one slave: accept
all other slaves: reject
Slaves


answer by replying to master PID
wait for decision from master
ID1218, Christian Schulte
L12 2009-12-07
Master: Blueprint
46
decide(SPs) ->
Rs=collect(SPs,propose),
{SP,SPr}=choose(SPs,Rs),
SP ! {self(),accept},
broadcast(SPr,reject}.
 Generic:
 collecting

and broadcasting
Specific:
 choose
single process from processes based on replies Rs
ID1218, Christian Schulte
L12 2009-12-07
Slave: Blueprint
47
slave() ->
receive
{M,propose} ->
R=…, M ! {self(),R},
receive
{M,accept} -> …;
{M,reject} -> …
end
end
ID1218, Christian Schulte
L12 2009-12-07
Avoiding Deadlock
48

Master can only proceed, after all slaves answered
 will
not process any more messages until then
 receiving messages in collect

Slave can only proceed, after master answered
 will

not process any more messages until then
What happens if multiple masters for same slaves?
ID1218, Christian Schulte
L12 2009-12-07
Avoiding Deadlock
49

Force all masters to send in order:
 First
A, then B, then C, …
 Guarantee: If A available, all others will be available
 difficult: what if dynamic addition and removal of lists
 does not work with low-latency collect



low-latency: messages can arrive in any order
high-latency: receipt imposes strict order
Use an adaptor
 access
to slaves through one single master
 slaves send message to single master
 problem: potential bottleneck
ID1218, Christian Schulte
L12 2009-12-07
Liveness Properties
50


Important property of concurrent programs
liveness
An event/activity might fail to be live
 other
activities consume all CPU power
 message box is flooded (denial of services)
 activities have deadlocked
…

Difficult: all possible interactions with other
processes must guarantee liveness
 reasoning
of all possible interactions
ID1218, Christian Schulte
L12 2009-12-07
51
Process State Reconsidered
ID1218, Christian Schulte
L12 2009-12-07
State and Concurrency
52



Difficult to guarantee that state is maintained
consistently in a concurrent setting
Typically needed: atomic execution of several
statements together
Processes guarantee atomic execution
ID1218, Christian Schulte
L12 2009-12-07
Locking Processes
53


Idea that is used most often in languages which rely
on state
Before state can be manipulated: lock must be
acquired
 for


example, one lock per object
If process has acquired lock: can perform
operations
If process is done, lock is released
ID1218, Christian Schulte
L12 2009-12-07
A Lockable Process
54
outside(F,InS) ->
receive
{acquire,PID} ->
PID ! {ok,self()},
inside(F,InS,PID)
end.
inside(F,InS,PID) ->
receive
{release,PID} -> outside(F,InS)
{PID,Msg} -> inside(F,F(Msg,InS));
end.
ID1218, Christian Schulte
L12 2009-12-07
Safety Properties
55

Maintain state of processes in consistent fashion
 do
not violate invariants
 to not compute incorrect results

Guarantee safety by
 atomic
execution
 exclusion of other processes ("mutual exclusion")
ID1218, Christian Schulte
L12 2009-12-07
56
Runtime Efficiency
ID1218, Christian Schulte
L12 2009-12-07
Approach
57





Take MiniErlang program
Take execution time for each expression
Give equations for runtime of functions
Solve equations
Determine asymptotic complexity
ID1218, Christian Schulte
L12 2009-12-07
Execution Times for Expressions
58


Give inductive definition based on function
definition and structure of expressions
Function definition
 pattern

Simple expression
 values

matching and guards
and list construction
More involved expression
 function
call
 recursive function call leads to recursive equation
 often called: recurrence equation
ID1218, Christian Schulte
L12 2009-12-07
Execution Time: T(E)
59



Value
T(V) = cvalue
List construction
T([E1|E2]) = ccons + T(E1) + T(E2)
Time T(E) needed for executing expression E
 how
MiniErlang machine executes E
ID1218, Christian Schulte
L12 2009-12-07
Function Call
60

For a function F define a function
TF(n)
for its runtime
and determine
 size
of input for call to F
 input for a function
ID1218, Christian Schulte
L12 2009-12-07
Function Call
61
T(F(E1, ..., Ek)) = ccall + T(E1) + ... + T(Ek)
+ TF(size(IF({1, ..., k})))
 input
 size
arguments
IF({1, ..., k})
input arguments for F
size(IF({1, ..., k}))
size of input for F
ID1218, Christian Schulte
L12 2009-12-07
Function Definition
62

Assume function F defined by clauses
H1 -> B1; …; Hk -> Bk.
TF(n) = cselect + max { T(B1), …, T(Bk) }
ID1218, Christian Schulte
L12 2009-12-07
Example: app/2
63
app([],Ys)
-> Ys;
app([X|Xr],Ys)
-> [X|app(Xr,Ys)].


What do we want to compute
Tapp(n)
Knowledge needed
input argument
 size function

first argument
length of list
ID1218, Christian Schulte
L12 2009-12-07
Append: Recurrence Equation
64



Analysis yields
Tapp(0)
= c1
Tapp(n)
= c2 + Tapp(n-1)
Solution to recurrence is
Tapp(n) = c1 + c2  n
Asymptotic complexity
Tapp(n) is of O(n)
“linear complexity”
ID1218, Christian Schulte
L12 2009-12-07
Recurrence Equations
65

Analysis in general yields a system
 T(n)
 T(0),

T(1), …
defined in terms of
T(m1), …, T(mk)
for m1, …, mk < n
values for certain n
Possibilities
 solve
recurrence equation (difficult in general)
 lookup asymptotic complexity for common case
ID1218, Christian Schulte
L12 2009-12-07
Common Recurrence Equations
T(n)
c + T(n–1)
Asymptotic Complexity
O(n)
c1 + c2n + T(n–1)
O(n2)
c + T(n/2)
O(log n)
c1 + c2n + T(n/2)
O(n)
c + 2T(n/2)
O(n)
c + 2T(n-1)
O(2n)
c1 + c2n + T(n/2)
O(n log n)
L12 2009-12-07
ID1218, Christian Schulte
66
67
That’s It!
ID1218, Christian Schulte
L12 2009-12-07
Download