מרצה: יהודה אפק מגיש: ערן שרגיאן. OutlineOutline Quick reminder of the...
-
Upload
joshua-conley -
Category
Documents
-
view
219 -
download
4
Transcript of מרצה: יהודה אפק מגיש: ערן שרגיאן. OutlineOutline Quick reminder of the...
מרצה: יהודה אפק
מגיש: ערן שרגיאן
OutlineOutlineOutlineOutlineQuick reminder of the Stack structure.
The Unbounded Lock-Free Stack.
The Elimination Backoff Stack.
Concurrent StackConcurrent StackConcurrent StackConcurrent Stack
The Stack<T> class is a collection of items (of type
T) that provides the following methods:
push(x)
pop()
Satisfying the Last-In-First-Out (LIFO) property:
The last item pushed is the first popped.
Empty StackEmpty StackEmpty StackEmpty Stack
Top
PushPushPushPush
Top
PushPushPushPush
TopCAS
PushPushPushPush
Top
PushPushPushPush
Top
PushPushPushPush
Top
PushPushPushPush
TopCAS
PushPushPushPush
Top
PopPopPopPop
Top
PopPopPopPop
TopCAS
PopPopPopPop
TopCAS
mine!
PopPopPopPop
TopCAS
PopPopPopPop
Top
The LockfreeStack classThe LockfreeStack classThe LockfreeStack classThe LockfreeStack class
The lock-free stack is a linked list, where the top
field points to the first node (or null if the stack is
empty).
A pop() call uses compareAndSet() to try to remove
the first node from the stack.
A push() call uses compareAndSet() to try to insert a
new node into the top of the stack.
public class LockFreeStack { private AtomicReference top = new AtomicReference(null); static final int MIN_DELAY = …; static final int MAX_DELAY = …; Backoff backoff = new Backoff(MIN_DELAY, MAX_DELAY);
public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff(); }}
public boolean tryPop() throws EmptyException { Node oldTop = top.get(); if (oldTop == null) { throw new EmptyException(); } Node newTop = oldTop.next; if (top.compareAndSet(oldTop, newTop)) { return oldTop; } else { return null; } } public T pop() throws EmptyException { while (true) { Node returnNode = tryPop(); if (returnNode != null) { return returnNode.value; } else backoff.backoff(); }
Lock-free StackLock-free StackLock-free StackLock-free StackGood
No locking
Bad
huge contention at top
No parallelism
Elimination-Backoff Elimination-Backoff StackStackElimination-Backoff Elimination-Backoff StackStack
Ways to solve it :
exponential backoff (reduces contention but does not solve the
bottleneck problem).
elimination backoff
The LockFreeStack implementation scales poorly, not so
much because the stack’s top field is a source of contention,
but primarily because it is a sequential bottleneck.
ObservationObservationObservationObservation
Push( )
Pop()
linearizable stack
After an equal number of pushes and pops, stack stays the same
Yes!
Idea: Elimination ArrayIdea: Elimination ArrayIdea: Elimination ArrayIdea: Elimination Array
Push( )
Pop()
stack
Pick at random
Pick at random
Elimination Array
Push Collides With PopPush Collides With PopPush Collides With PopPush Collides With Pop
Push( )
Pop()
stack
continue
continue
No need to access stack
Yes!
No CollisionNo CollisionNo CollisionNo Collision
Push( )
Pop()
stack
If no collision, access stack
If pushes collide or pops collide access stack
Elimination-Backoff Elimination-Backoff StackStackElimination-Backoff Elimination-Backoff StackStack
A union of the LockFreeStack class with the
elimination array
Access Lock-free stack,
If uncontended, apply operation
if contended, back off to elimination array and attempt elimination
Elimination-Backoff Elimination-Backoff StackStackElimination-Backoff Elimination-Backoff StackStack
Push( )
Pop()TopCAS
If CAS fails, back off
Dynamic Range and Dynamic Range and DelayDelayDynamic Range and Dynamic Range and DelayDelay
Push( )
Pick random range and max time to wait for collision based on level ofcontention encountered
LinearizabilityLinearizabilityLinearizabilityLinearizabilityThe combined data structure, array, and shared
stack, is linearizable because the shared stack is
linearizable, and the eliminated calls can be ordered
as if they happened at the point in which they
exchanged values.
Un-eliminated calls
linearized as before
Eliminated calls:
linearize pop() immediately after matching push()
Combination is a linearizable stack
Un-Eliminated Un-Eliminated LinearizabilityLinearizabilityUn-Eliminated Un-Eliminated LinearizabilityLinearizability
push(v1)
timetime
linearizable
push(v1)
pop(v1)pop(v1)
Eliminated LinearizabilityEliminated LinearizabilityEliminated LinearizabilityEliminated Linearizability
pop(v2)push(v1)
push(v2)
timetime
push(v2)
linearizable
pop(v2)push(v1)
pop(v1)pop(v1)
Collision Point
Red calls are eliminated
Backoff Has Dual EffectBackoff Has Dual EffectBackoff Has Dual EffectBackoff Has Dual EffectElimination introduces parallelism
Backoff onto array cuts contention on lock-free
stack
Elimination in array cuts down total number of
threads ever accessing lock-free stack
public class EliminationArray { private static final int duration = ...; private static final int timeUnit = ...; Exchanger<T>[] exchanger; public EliminationArray(int capacity) { exchanger = new Exchanger[capacity]; for (int i = 0; i < capacity; i++) exchanger[i] = new Exchanger<T>(); … } …}
Elimination ArrayElimination ArrayElimination ArrayElimination Array
public class Exchanger<T> { AtomicStampedReference<T> slot = new AtomicStampedReference<T>(null, 0);
A Lock-Free ExchangerA Lock-Free ExchangerA Lock-Free ExchangerA Lock-Free Exchanger
Atomic Stamped Atomic Stamped ReferenceReferenceAtomic Stamped Atomic Stamped ReferenceReference
address S
Stamp
Reference
Exchanger StatusExchanger StatusExchanger StatusExchanger Status
enum Status {EMPTY, WAITING, BUSY};
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
EMPTY
EMPTY
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
CAS
WAITING
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
In search of partner …
WAITING
WAITING
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
Slot
Still waiting …
Try to exchange
item and set state to BUSY
CAS
BUSY
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
Slot
Partner showed up, take item and reset to
EMPTY
item stamp/state
EMPTYBUSY
Lock-free ExchangerLock-free ExchangerLock-free ExchangerLock-free Exchanger
Slot
item stamp/state
Partner showed up, take item and reset to
EMPTY
The Exchanger Slot The Exchanger Slot The Exchanger Slot The Exchanger Slot Exchanger is lock-free
Because the only way an exchange can fail is if
others repeatedly succeeded or no-one showed up
public class EliminationArray {…public T visit(T value, int Range) throws TimeoutException { int slot = random.nextInt(Range); int nanodur = convertToNanos(duration, timeUnit)); return (exchanger[slot].exchange(value, nanodur) }}
Elimination ArrayElimination ArrayElimination ArrayElimination Array
public void push(T value) {... while (true) { if (tryPush(node)) { return; } else try { T otherValue = eliminationArray.visit(value,policy.Range); if (otherValue == null) { return; }}
Elimination Stack PushElimination Stack PushElimination Stack PushElimination Stack Push
public T pop() { ... while (true) { if (tryPop()) { return returnNode.value; } else try { T otherValue = eliminationArray.visit(null,policy.Range); if (otherValue != null) { return otherValue; } }}}
Elimination Stack PopElimination Stack PopElimination Stack PopElimination Stack Pop
SummarySummarySummarySummary
Quick reminder of the Stack structure.
The Unbounded Lock-Free Stack.
The Elimination Backoff Stack.
תודה רבה על ההקשבה