Programming Language Semantics Axiomatic Semantics of Parallel Programs
description
Transcript of Programming Language Semantics Axiomatic Semantics of Parallel Programs
Programming Language Semantics
Axiomatic Semantics of Parallel Programs
Tentative Schedule
• 15/6 Parallel Programs
• 22/6 Rely/Guarantee Reasoning– Assignment 2
• 29/6 Separation Logic
• 6, 3/7 Type Inference– Assignment 3
Plan
• More on Hoare Proof Rules
• Proof Rules for Concurrent Programs
Hoare Proof Rules for Partial Correctness
{A} skip {A}
{B[a/X]} X:=a {B} (Assignment Rule)
{P} c0 {C} {C} c1 {Q}
{P} c0;c1{Q}
{Pb} c0 {Q} {P b} c1 {Q}
{P} if b then c0 else c1{Q}
{Ib} c {I}
{I} while b do c{Ib}
P P’ {P’} c {Q’} Q’ Q
{P} c {Q}
(Composition Rule)
(Conditional Rule)
(Loop Rule)
(Consequence Rule)
Potential Language Extensions
• Blocks
• Procedures– Procedures as parameters
• Abstract data types
• Non-determinism
• Parallelism
• Arrays, Pointers, and Dynamic allocations
More Rules
{P1} c {Q1} {P2} c {Q2}
{P1 P2} c {Q1 Q2}(Conjunction Rule)
{P} c {P} where Mod(c)Var(P) = (Invariance Rule)
Underlying Principles of Hoare Rules
• Commands are predicate transformers• Different behaviors for different
preconditions• Commands can be partial
– Resource restriction– Implementation restriction
• In {P} comm {Q}– P and Q are contracts with the clients of comm
An Axiomatic Proof Technique for Parallel Programs
Owicky & Gries
Verification of Sequential and Concurrent Programs
Apt & Oldrog
Chapters 4-6
IMP+ Parallel Constructs
• Abstract syntaxcom::= X := a | skip | com1 ; com2 | if b then com1 else com2 | while b do com| cobegin com1 || com2 … || comk coend
• All the interleavings of are executed• Example
– cobegin X := 1 || (X :=2 ; X := X+2) coend
A First Attempt
{P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk}
{P1 P2 … Pk} cobegin c1 || c2 || …|| cn coend {Q1 Q2 … Qk}(Parallel Rule)
Simple Examples
{true} X := 1 { X >0 } {true} Y:= 1 {Y>0}
{true} cobegin X :=1 || Y := 1 coend{X>0 Y >0}
{true} X := 1 { X >0 } {true} X:=2 ; X := X+2 {X>0}
{true} cobegin X :=1 || X:=2 ; X := X+2 coend{X>0 }
Unsoundness
{Y=1} X := 0 { Y=1 } {true} Y:=0 {true}
{Y=1} cobegin X :=0 || Y:=0 coend {Y=1 }
Modified Parallel Rule
{P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk}
{P1 P2 … Pk} cobegin c1 || c2 || …|| ck coend {Q1 Q2 … Qk}
Mod(cj)Var(Pi) =
Mod(cj)Var(Qi) =
ij
Unsoundness from sharing
{true} X := 1 { X >0 } {true} X:=2 ; X := X+2 {X>3}
{true} cobegin X :=1 || X:=2 ; X := X+2 coend {X>3 }
Handling Shared Variables
• Carefully design the proofs of every thread to make them local
• Show that the code of other threads do not interfere with the proofs of other threads
Interference
• A command T with a precondition pre(T) does not interfere with the proof of {P} C {Q} if:– {Q pre(T) } T {Q}– For any command C’ inside C with a precondition
pre(C’)• {pre(C’) pre(T) } T {pre(C’)}
• {P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk} are interference free if for every i j and for every assignment in T in ci does not interfere with {Pj} cj {Qj}
Modified Parallel Rule
{P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk}
{P1 P2 … Pk} cobegin c1 || c2 || …|| ck coend {Q1 Q2 … Qk}
{P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk} are interference free
No unsoundness from sharing
{true} X := 1 { X >0 } {true} X:=2 ; X := X+2 {X>3}
{true} cobegin X :=1 || X:=2 ; X := X+2 coend {X>3 }
A Realistic ExampleFindpos: begin
initialize: i :=2 ; j :=1; eventop = M+1 ; oddtop := M+1;
search: cobegin
Evensearch: while i < min(oddtop, eventop) do
if (x(i) > 0) then eventop := i
else i := i + 2;
|| Oddsearch: while j < min(oddtop, eventop) do if (x(j) > 0) then oddtop := j else j := j + 2;
coendk := min(eventop, oddtop)end {k M+1 (l: 1 l <k x(l) 0) (k M x(k)>0)}
ES=eventopM+1
even(i)
l: (even(l) 0<l<i) x(l)0
eventopM x(eventop)>0
OS=oddtopM+1
odd(j)
l: (odd(l) 0<l<j) x(l)0
oddtopM x(oddtop)>0
Incompleteness
• There exist correct programs which cannot be verified by the parallelization rule– {X = Y} cobegin X := X + 1 || Y := Y+1 coend {X=Y}
An Informal Proof of {X = Y} cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X = Z} X : = X + 1 { X = Z +1}
{Y = Z} Y : = Y + 1 { Y = Z +1}
{X = Z Y = Z} cobegin X := X + 1 || Y := Y+1 coend {X=Z+1 Y= Z+1}
{X = Z Y = Z} cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X = Y} Z : = X { X = Y Y = Z}
{X =Y } Z : = X ; cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X =Y } cobegin X := X + 1 || Y := Y+1 coend {X=Y}
Auxiliary Variables
• Record history information
• A set of variables AV is auxiliary for a command S if each variable from AV only occurs in assignments of the form X := t where X AV
• Auxiliary variable elimination rule{P} S {Q}
{P} S’ {Q}
Where A is auxiliary for SFV(Q) A =
FV(P) A =
S’ results from S by deleting all assignments in to variables in S
A Formal Proof of {X = Y} cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X = Z} X : = X + 1 { X = Z +1}
{Y = Z} Y : = Y + 1 { Y = Z +1}
{X = Z Y = Z} cobegin X := X + 1 || Y := Y+1 coend {X=Z+1 Y= Z+1}
{X = Z Y = Z} cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X = Y} Z : = X { X = Y Y = Z}
{X =Y } Z : = X ; cobegin X := X + 1 || Y := Y+1 coend {X=Y}
{X =Y } cobegin X := X + 1 || Y := Y+1 coend {X=Y}
(Assign-Rule)
(Assign-Rule)
(Par-Rule)
(Cons.-Rule)(Assign-Rule)
(Comp.-Rule)
(Aux.-Rule)
Synchronization Primitives
• Support for atomic sections and communication• A High Level Construct
await B then S– No parallelization in S– Blocked until B holds– If B is true then S is executed atomically
• Examples– await true then S– Await “some condition” then skip– Semaphore
• P(sem): await sem >0 then sem := sem – 1• V(sem): await true then sem := sem + 1
Interference (modified)
• A command T with a precondition pre(T) does not interfere with the proof of {P} C {Q} if:– {Q pre(T) } T {Q}– For any command C’ inside C but not within await with
a precondition pre(C’)• {pre(C’) pre(T) } T {pre(C’)}
• {P1} c1 {Q1} {P2} c2 {Q2}.. {Pk} ck {Qk} are interference free if for every i j and for every assignment not inside await or an await T in ci does not interfere with {Pj} cj {Qj}
An Inference Rule for Await
{P b} c {Q}
{P } await B then c {Q}
Producer-Consumer
• Two processes communicating via a shared bounded buffer• Consumer waits for the buffer to be filled• Producer waits for the buffer to be non-full and fills the buffer• buffer[0..N-1]• in – the number of elements added• out – the number of elements deleted• buffer[out mod N], … buffer[(out + in – out -1) mod N] elements
in := 0; out := 0 ;
cobegin
producer: …
await in-out < N then skip
add: buffer(in mod N) := next value;
markin: in := in +1;
…
|| consumer: … await in-out >0 then skip remove: this value := buffer(out mod N); markout: out := out +1; …coend
Producer/Consumer Code
in := 0; out := 0 ; i := 1; j :=1;
{M 0}
cobegin
producer: while i M do
begin x:= A[i];
await in-out <N then skip;
add: buffer[in mod N] := x ;
markin: in := in + 1;
i := i + 1
end
|| consumer: while j M do begin await in-out >0 then skip; remove: y := buffer[out mod N] ; markout: out := out + 1; B[j] := y; j := j + 1 endcoend {k: 1 k M B[k] = A[k]}
I= k: out < k M buffer[(k-1} mod N] = A[k]
0 in-out N
0 i M+1
0 j M+1
{I i = in+1=1 j=out+1=1}
cobegin
{I i = in+1=1}
producer: while i M do
begin x:= A[i];
await in-out <N then skip;
add: buffer[in mod N] := x ;
markin: in := in + 1;
i := i + 1
end {I i = in+1=M+1}
|| {I j = out+1=1} consumer: while j M do begin await in-out >0 then skip; remove: y := buffer[out mod N] ; markout: out := out + 1; B[j] := y; j := j + 1 end {I k: 1 k M B[k] = A[k]}}coend {k: 1 k M B[k] = A[k]}
I= k: out < k M buffer[(k-1} mod N] = A[k]
0 in-out N
0 i M+1
0 j M+1
Summary
• Reasoning about concurrent programs is difficult• Aweeki-Gries suggest to carefully design the
sequential proofs to simplify the proof procedure• The use of auxiliary variables can make proofs
difficult• Can have difficulties with fine-grained
concurrency– Benign dataraces
• Rely/Guarantee style can allow more elegant/general reasoning (next lesson)