Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir...

30
Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    214
  • download

    0

Transcript of Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir...

Page 1: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

Obstruction-free synchronization

Article by: Maurice Herlihy, Victor Luchangco,

Mark Moir

Double-Ended Queues as an example

Presentation : Or Peri

Page 2: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

Today’s Agenda• Two obstruction-free, CAS-based implementations

of Double-ended queues.

o Linear array

o Circular array

Page 3: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

Why Obstruction-Free?

• Avoid locks.

• Non-blocking data sharing between threads.

• Greater flexibility in design compared with Lock-

freedom and wait-freedom implementations.

• In practice, should provide the benefits of wait-

free and lock-free programming.

Page 4: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

What’s wrong with Locks?

• Deadlocks

• Low liveness

• Fault-handling

• Scalability

Page 5: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Obstruction-freedom ensures No thread can be

blocked by delays or failures of other threads.

• Obstruction-free algorithms are simpler, and can

be applied to complex structures.

• It does not guarantee progress when two (or

more) conflicting threads execute concurrently.

• To improve progress one might add a contention

reducing mechanism (“back-off reflex”).

Pros & cons

Page 6: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• lock-free and wait-free implementations use

such mechanisms, but in a way that imposes a

large overhead, even without contention.

• In scenarios with low contention, programming an

Obstruction-free algorithm with some contention-

manager, there’s the benefit from the simple and

efficient design.

Pros & cons

Page 7: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Double-ended queue- generalize FIFO queues

and LIFO stacks.

DEqueues

• Allows push\pop

operations in both

ends.

Page 8: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Remember “Job Stealing”?

• One application of DEqueues is as processors’ jobs queues.

• Each processor pops tasks from it’s own Dequeue’s

head.

DEqueues- what for?

Job

Job

Job

Job

Job

Job

Job

Page 9: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Upon fork(), it pushes tasks to it’s DEqueue‘s head.

• If a processor’s queue is empty, it can “steal”

tasks from another processor’s DEqueue‘s tail.

DEqueues- what for?

Job

Job

Job

Job

Job

Job

Job

Job

Page 10: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• First we’ll see the simpler, linear, array-

based DEqueue.

• Second stage will extend the first one to “wrap

around” itself.

Implementation

Page 11: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Two special “null” values: LN and RN

• Array A[0,…,MAX+1] holds state.

• MAX is the queue’s maximal capacity.

• INVARIANT: the state will hold: LN+ values* RN+

• An Oracle() function:o Parameter: left/right

o Returns: an array index

• When Oracle(right) is invoked, the returned

index is the leftmost RN value in A.

Implementation – Intro

Page 12: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Each element i in A has:o A value: i.val

o A version counter: i.ctr

• Version numbers are updated at every CAS

operation.

• Linearization point: point of changing a value in A.

Implementation – Intro

Page 13: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• The Idea: o rightpush(v) will change the leftmost RN to v.

o rightpop() will change the rightmost data to RN (and

return it)

o rightpush(v) returns “full” if there’s a non-RN value at

A[MAX]

o rightpop() returns “empty” if there are neighboring

RN,LN

• Right/left push/pop are symmetric, so we only

show one side.

Implementation – Intro

Page 14: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

1) Rightpush(v){2) While(true){3) k := oracle(right);4) prev := A[k-1];5) cur := A[k];6) if(prev.val != RN and cur.val = RN){7) if(k = MAX+1) return “full”;8) if( CAS(&A[k-1], prev,

<prev.val,prev.ctr+1>) )9) if( CAS(&A[k], cur, <v,cur.ctr+1>) )10) return “ok”;11) } //end “if”12) } //end “while”13) } //end func

Implementation – right push

Page 15: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

1) Rightpop(){2) While(true){3) k := oracle(right);4) cur := A[k-1];5) next := A[k];6) if(cur.val != RN and next.val = RN){7) if(cur.val = LN and A[k-1] = cur) 8) return “empty”;9) if( CAS(&A[k], next, <RN, next.ctr+1>) )10) if( CAS(&A[k-1], cur, <RN,cur.ctr+1>)

)11) return cur.val;12) } //end “if”13) } //end “while”14) } //end func

Implementation – right pop

Page 16: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Relies on three claims: o In a rightpush(v) operation, at the moment we “CAS“

A[k].val from an RN value to v, A[k-1].val is not RN.

o In a rightpop() operation, at the moment we “CAS” A[k-

1].val from some v to RN, A[k].val contains RN.

o If rightpop() returns “empty”, then at the moment it

performed next:=A[k] (and just after: cur:=A[k-1]),

these two values were LN and RN.

Linearizability

Page 17: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• The third claim:o If rightpop() returns “empty”, then at the moment it

performed next:=A[k] (and just after: cur:=A[k-1]),

these two values were LN and RN.

• holds since: 4) cur := A[k-1];5) next := A[k];6) if(cur.val != RN and next.val = RN){7) if(cur.val = LN and A[k-1] = cur) 8) return “empty”;

• A[k-1] didn’t change version number from line 4 to 7

• so did A[k] from line 5 to 6.

Linearizability

Page 18: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• The first two claims hold similarly:o Since CAS operations check version numbers, only if no one

interfered with another push/pop, we can perform the operation

o In rightpush(v) for example:

4) prev := A[k-1];5) cur := A[k];6) if(prev.val != RN and cur.val = RN){7) if(k = MAX+1) return “full”;8) if( CAS(&A[k-1], prev, <prev.val,prev.ctr+1>) )9) if( CAS(&A[k], cur, <v,cur.ctr+1>) )

• Counter didn’t change (upon success) from line 5 to 9,

hence so did the value.

• Same holds for the neighbor (k-1) from line 4 to 8

Linearizability

Page 19: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Implementing the Oracle() function:o For linearizability, we only need oracle() to return an index at range.

o For Obstruction-freedom we have to show that it is eventually

accurate if invoked repeatedly without interference.

• Naïve approach is to simply go over the entire

array and look for the first RN.

• Another approach is to keep “hints” (last

position, for instance), and search around them.

• We can update these hints frequently or seldom

with respect to cache locations… but that’s off-topic

Linearizability

Page 20: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• The Idea: o A[0] is “immediately to the right” of A[MAX+1].

o All indices are calculated modulo MAX+2.

• Two main differences:o To return “full” we must be sure there are exactly two null entries.

o A rightpush operation may encounter a LN value we’ll convert them

into RN values (using another null character: DN).

Extension to circular array

Page 21: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• All null values are in a contiguous sequence in the

array.

• This sequence is of the form: RN* DN* LN*

• There are at least 2 different types of null values

in the sequence.

Circular array - Invariants

Page 22: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• We don’t invoke oracle(right) directly.

• Instead, we have rightCheckOracle() which

returns:

o K an array index

o Left A[k-1]’s last content

o Right A[k]’s last content

• This guarantees:

o right.val = RN

o Left.val != RN

Circular array - Implementation

Page 23: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

rightCheckedOracle()1) While(true){2) k := oracle(right);3) left := A[k-1];4) right := A[k];5) if(right.val = RN and left.val != RN)6) return k,left,right;7) if( right.val = DN and !(left.val in {RN,DN})

)8) if( CAS(&A[k-1], left, <left.val,

left.ctr+1>) )9) if( CAS(&A[k], right,

<RN,cur.ctr+1>) )10) return k,<left.val,left.ctr+1>, <RN,right.ctr+1>;11) } //end “while”

Page 24: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• The array is not “full” when A[k+1] is RN.

• this is since A[k] is RN and an Invariant holds

that “There are at least 2 different types of null

values in the sequence”.

• So, if A[k+1] = LN try converting it to DN

• If A[k+1] = DN try converting it to RN

• In this case, we need to check “nextnext”.

The major change – rightPush(v)

Page 25: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

rightPush(v)1) While(true){2) k,prev,cur := rightCheckedOracle();3) next := A[k+1];4) if( next.val = RN ) //change RN to v5) if( CAS(&A[k-1], prev,

<prev.val,prev.ctr+1> ) )6) if( CAS(&A[k], cur, <v,cur.ctr+1>) )7) return “ok”;8) if( next.val = LN ) //change LN to DN9) if( CAS(&A[k], cur, <RN, cur.ctr+1>) )10) if( CAS(&A[k+1], next,

<DN,next.ctr+1>) )11) if(next.val = DN)

Page 26: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

rightPush(v)11) if(next.val = DN){12) nextnext:= A[k+2];13) if( !(nextnext.val in {RN,LN,DN}) )14) if(A[k-1] = prev)15) if(A[k] = cur)16) return “full”;17) if( nextnext.val = LN) //DN to RN18) if( CAS(&A[k+2], nextnext, <nextnext.val,nextnext.ctr+1>) )19) CAS(&A[k+1], next,

<RN,next.ctr+1>);20) } //end “if”21)}//end “while”

Page 27: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

rightPop()1) While(true){2) k,cur,next := rightCheckedOracle();3) if( cur.val in {LN,DN} and A[k-1] = cur )4) return “empty”;5) if( CAS(&A[k], next, <RN, next.ctr+1>) )6) if( CAS(&A[k-1], cur,

<RN,cur.ctr+1>) )7) return cur.val;8) }//end “while”

Page 28: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• Is harder to prove in this case (there’s a whole

other article just to do so).

• The main difficulty: proving that when

rightPush(v) changes a value, it has an RN or an

DN to it’s right.

• There are 5 lines in the code (of the right side

functions) which may interrupt with this, but they

are all using CAS, and intuitively, the .ctr values

should assure correctness.

Linearizability

Page 29: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

• We’ve seen Two Obstruction-free implementations

of a Dequeue.

• As promised, they are pretty simple.

• Hopefully, I’ve managed to demonstrate the main

degradation, as well as an intuition as to why it’s

a good solution for relatively low contention

scenarios

To Sum up

Page 30: Obstruction-free synchronization Article by: Maurice Herlihy, Victor Luchangco, Mark Moir Double-Ended Queues as an example Presentation : Or Peri.

Questions?

?