AutoSynch An Automatic-Signal Monitor Based on Predicate Tagging Vijay K. Garg Wei-Lun Hung garg@ece.utexas.edu wlhung@utexas.edu Parallel and Distributed Systems Laboratory Department of Electrical & Computer Engineering PLDI 2013
Outline Introduction 1 Our Approach 2 Evaluate Predicate: Closure Avoid signalAll Calls: Relay Signaling Rule Reduce Predicate Evaluations: Predicate Tagging Results 3 Conclusions and Future Work 4 PLDI 2013 1 / 31
Bounded Buffer public class BoundedBuffer { Object[] buff; int putPtr, takePtr, count; // for mutual exclusion and synchronization Lock mutex = new ReentrantLock(); Condition full = mutex.newCondition(); Condition empty = mutex.newCondition(); public BoundedBuffer(int n) { buff = new Object[n]; putPtr = takePtr = count = 0; } } takePtr count = 4 putPtr PLDI 2013 2 / 31
Bounded Buffer public Object take() { // lock before operations mutex.lock(); // wait if the buffer is empty while (count == 0) { empty.await(); } Object ret = buff[takePtr++]; takePtr %= buff.length; count--; // signal other threads when the buffer // is no longer full if (count == buff.length - 1) { full.signalAll(); } // unlock after operations mutex.unlock(); } PLDI 2013 3 / 31
Bounded Buffer public Object take() { // lock before operations mutex.lock(); // wait if the buffer is empty while (count == 0) { empty.await(); } Object ret = buff[takePtr++]; takePtr %= buff.length; count--; // signal other threads when the buffer // is no longer full if (count == buff.length - 1) { full.signalAll(); } // unlock after operations mutex.unlock(); } PLDI 2013 3 / 31
Bounded Buffer: Common Bugs public Object take() { mutex.lock(); if (count == 0) { empty.await(); } Object ret = buff[takePtr++]; takePtr %= buff.length; count--; if (count == buff.length - 1) { full.signal(); } mutex.unlock(); } PLDI 2013 4 / 31
Bounded Buffer: Common Bugs public Object take() { mutex.lock(); if while (count == 0) { empty.await(); } Object ret = buff[takePtr++]; takePtr %= buff.length; count--; if (count == buff.length - 1) { full.signal(); } mutex.unlock(); } PLDI 2013 5 / 31
Bounded Buffer: Common Bugs public Object take() { mutex.lock(); while (count == 0) { empty.await(); } Object ret = buff[takePtr++]; takePtr %= buff.length; count--; if (count == buff.length - 1) { full.signal() full.signalAll() ; } mutex.unlock(); } PLDI 2013 6 / 31
AutoSynch Bounded Buffer public AutoSynch class BoundedBuffer { Object[] buff; int putPtr, takePtr, count; public BoundedBuffer(int n) { buff = new Object[n]; putPtr = takePtr = count = 0 ; } } PLDI 2013 7 / 31
AutoSynch Bounded Buffer public Object take() { waituntil (count > 0); Object ret = buff[takePtr++]; takePtr %= buff.length; count--; } PLDI 2013 8 / 31
AutoSynch vs. Explicit Signaling 1 public class BoundedBuffer { 2 Object[] buff; 3 int putPtr, takePtr, count; 4 Lock mutex = new ReentrantLock(); 5 Condition full = mutex.newCondition(); 1 public AutoSynch class BoundedBuffer { 6 Condition empty = mutex.newCondition(); 2 Object[] buff; 7 public BoundedBuffer(int n) { 3 int putPtr, takePtr, count; 8 buff = new Object[n]; 4 public BoundedBuffer(int n) { 9 putPtr = takePtr = count = 0; 5 buff = new Object[n]; 10 } 6 putPtr = takePtr = count = 0 ; 11 public Object take() { 7 } 12 mutex.lock(); 8 public Object take() { 13 while (count == 0) { 9 waituntil (count > 0); 14 empty.await(); 10 Object ret = buff[takePtr++]; 15 } 11 takePtr %= buff.length; 16 Object ret = buff[takePtr++]; 12 count--; 17 takePtr %= buff.length; 13 } 18 count--; 14 } 19 if (count == buff.length - 1) { 20 full.signalAll(); 21 } mutex.unlock(); 22 } 23 24 } PLDI 2013 9 / 31
Related Work The idea of automatic signaling was suggested by Hoare in [Hoa74], but rejected due to efficiency considerations The common belief: automatic signaling is extremely inefficient compared to explicit signaling [BFC95][BH05] PLDI 2013 10 / 31
Design Principles Reduce number of context switches and predicate evaluations Predicate evaluation Is essential in automatic signaling to decide which thread should be signaled Context switches Avoid signalAll calls Introduces redundant context switches Is required in explicit signaling PLDI 2013 11 / 31
Parameterized Bounded Buffer C 2 C 1 local variable num2 = 40 shared variable num1 = 32 condition waiting queue buff.length = 64 count = 24 waituntil (count >= num i ) C 4 C 3 P 0 waituntil (items i .length + count <= buff.length) items 0 .length = 18 A producer puts a bunch of items into the buffer A consumer takes a number of items out of the buffer PLDI 2013 12 / 31
Parameterized Bounded Buffer public Object[] take( int num ) { mutex.lock(); while (count < num) { insufficientItem.await(); } Object[] ret = new Object[num]; for (int i = 0; i < num; i++) { ret[i] = buff[takePtr++]; takePtr %= buff.length; } count -= num; insufficientSpace.signalAll(); mutex.unlock(); return ret; } PLDI 2013 13 / 31
Parameterized Bounded Buffer public Object[] take(int num) { mutex.lock(); while (count < num) { insufficientItem.await(); } Object[] ret = new Object[num]; for (int i = 0; i < num; i++) { ret[i] = buff[takePtr++]; takePtr %= buff.length; } count -= num; insufficientSpace.signalAll(); mutex.unlock(); return ret; } PLDI 2013 13 / 31
Parameterized Bounded Buffer public Object[] take(int num) { mutex.lock(); while (count < num) { insufficientItem.await(); } Object[] ret = new Object[num]; for (int i = 0; i < num; i++) { ret[i] = buff[takePtr++]; takePtr %= buff.length; } count -= num; insufficientSpace.signalAll(); mutex.unlock(); return ret; } PLDI 2013 13 / 31
AutoSynch Framework AutoSynch Java Library AutoSynch Java AutoSynch Standard Java Java Code Code Bytecode Preprocessor Compiler PLDI 2013 14 / 31
Outline Introduction 1 Our Approach 2 Evaluate Predicate: Closure Avoid signalAll Calls: Relay Signaling Rule Reduce Predicate Evaluations: Predicate Tagging Results 3 Conclusions and Future Work 4 PLDI 2013 15 / 31
Closure C 2 C 1 num2 = 40 num1 = 32 buff.length = 64 count = 24 waituntil (count >= num i ) C 4 C 3 P 0 waituntil (items i .length + count <= buff.length) items 0 .length = 18 PLDI 2013 16 / 31
Closure C 2 C 1 Replace local variables with the values at runtime buff.length = 64 count = 24 waituntil (count >= num1 ) C 4 C 3 P 0 items 0 .length = 18 waituntil (count >= num2 ) PLDI 2013 16 / 31
Closure C 2 C 1 Replace local variables with the values at runtime buff.length = 64 count = 24 waituntil (count >= 32) C 4 C 3 P 0 items 0 .length = 18 waituntil (count >= 40) PLDI 2013 16 / 31
Closure C 2 The thread (P 0 ) owning a monitor C 1 performs predicate evaluations for other threads (C 1 and C 2 ) before leaving buff.length = 64 count = 42 waituntil (count >= 32) C 4 Put 18 items C 3 P 0 waituntil (count >= 40) PLDI 2013 16 / 31
Outline Introduction 1 Our Approach 2 Evaluate Predicate: Closure Avoid signalAll Calls: Relay Signaling Rule Reduce Predicate Evaluations: Predicate Tagging Results 3 Conclusions and Future Work 4 PLDI 2013 17 / 31
Relay Signaling Rule C 2 C 1 buff.length = 64 count = 42 waituntil (count >= 32) C 4 C 3 P 0 waituntil (count >= 40) PLDI 2013 18 / 31
Relay Signaling Rule C 2 C 1 buff.length = 64 count = 42 waituntil (count >= 32) C 4 C 3 P 0 waituntil (count >= 40) PLDI 2013 18 / 31
Relay Signaling Rule buff.length = 64 count = 10 C 4 Take 32 items C 3 C 1 C 2 PLDI 2013 18 / 31
Relay Signaling Rule buff.length = 64 count = 10 C 4 C 3 C 2 count < 40 PLDI 2013 18 / 31
Relay Signaling Rule C 2 buff.length = 64 count = 10 C 4 C 3 waituntil (count >= 40) PLDI 2013 18 / 31
Relay Signaling Rule Before exiting a monitor Signal at most one thread waiting on a condition that has become true PLDI 2013 19 / 31
Relay Signaling Rule Before exiting a monitor Signal at most one thread waiting on a condition that has become true PLDI 2013 19 / 31
Outline Introduction 1 Our Approach 2 Evaluate Predicate: Closure Avoid signalAll Calls: Relay Signaling Rule Reduce Predicate Evaluations: Predicate Tagging Results 3 Conclusions and Future Work 4 PLDI 2013 20 / 31
Predicate Tagging Three types of predicates: Equivalence predicate: x = 5 , y = a 1 Threshold predicate: x > 8 , y < b , z ≥ c + 3 2 None of above: x � = 3 , assertion . isTrue () 3 PLDI 2013 21 / 31
Predicate Tagging Three types of tags: equivalence, threshold, and none Convert every predicate into disjunctive normal form (DNF) Assign a tag to every conjunction Assignment order: equivalence > threshold > none e.g. (( x < 5 ) ∧ ( y = 3 )) ∨ (( x > 5 ) ∧ foo 1 ()) ∨ foo 2 () ◮ (( x < 5 ) ∧ ( y = 3 )) ◮ (( x > 5 ) ∧ foo 1 ()) ◮ foo 2 () PLDI 2013 22 / 31
Predicate Tagging x = 5 x = 8 x ≥ 6 x < 10 x = 9 x > 11 x ≤ 4 x ≤ 7 x = 3 x > 6 PLDI 2013 23 / 31
Predicate Tagging x = 5 5 x = 8 8 x ≥ 6 9 x < 10 3 x = 9 x > 11 x ≤ 4 x ≤ 7 Hashtable for the equivalence tag with shared expression x x = 3 x > 6 PLDI 2013 23 / 31
Recommend
More recommend