10.07.2015 Views

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

50 CHAPTER 5. PARTITIONING AND SYNCHRONIZATION DESIGNLock LLock RDEQ 0 DEQ 1DEQ 2DEQ 3DEQ LDEQ RLock 0Lock 1Lock 2Lock 3Figure 5.5: Compound <strong>Do</strong>uble-Ended Queuequeues are run in tandem, each protected by its ownlock. Thismeansthatelementsmustoccasionallybeshuttled from one of the double-ended queues to theother, in which case both locks must be held. A simplelockhierarchymaybeusedtoavoiddeadlock,forexample, always acquiring the left-hand lock beforeacquiring the right-hand lock. This will be muchsimpler than applying two locks to the same doubleendedqueue, as we can unconditionally left-enqueueelements to the left-hand queue and right-enqueueelements to the right-hand queue. The main complicationarises when dequeuing from an empty queue,in which case it is necessary to:1. <strong>If</strong> holding the right-hand lock, release it andacquire the left-hand lock, rechecking that thequeue is still empty.2. Acquire the right-hand lock.3. Rebalance the elements across the two queues.4. Remove the required element.5. Release both locks.Quick Quiz 5.3: Inthiscompounddouble-endedqueue implementation, what should be done if thequeue has become non-empty while releasing andreacquiring the lock?The rebalancing operation might well shuttlea given element back and forth between thetwo queues, wasting time and possibly requiringworkload-dependent heuristics to obtain optimalperformance. Although this might well be the bestapproach in some cases, it is interesting to try for analgorithm with greater determinism.5.1.2.3 Hashed <strong>Do</strong>uble-Ended QueueOne of the simplest and most effective ways to deterministicallypartition a data structure is to hash it.<strong>It</strong> is possible to trivially hash a double-ended queueby assigning each element a sequence number basedon its position in the list, so that the first elementleft-enqueued into an empty queue is numbered zeroand the first element right-enqueued into an emptyIndex LLock LIndex RLock RFigure 5.6: Hashed <strong>Do</strong>uble-Ended Queuequeue is numbered one. A series of elements leftenqueuedinto an otherwise-idle queue would be assigneddecreasing numbers (-1, -2, -3, ...), while aseries of elements right-enqueued into an otherwiseidlequeue would be assigned increasing numbers (2,3, 4, ...). A key point is that it is not necessary toactually represent a given element’s number, as thisnumber will be implied by its position in the queue.Given this approach, we assign one lock to guardthe left-hand index, one to guard the right-hand index,and one lock for each hash chain. Figure 5.6shows the resulting data structure given four hashchains. Note that the lock domains do not overlap,and that deadlock is avoided by acquiring the indexlocks before the chain locks, and by never acquiringmore than one lock of each type (index or chain) ata time.Each hash chain is itself a double-ended queue,and in this example, each holds every fourth element.The uppermost portion of Figure 5.7 showsthe state after a single element (“R1”) has beenright-enqueued, with the right-hand index havingbeen incremented to reference hash chain 2. Themiddle portion of this same figure shows the stateafter three more elements have been right-enqueued.As you can see, the indexes are back to their initialstates, however, each hash chain is now non-empty.The lower portion of this figure shows the state afterthree additional elements have been left-enqueuedand an additional element has been right-enqueued.From the last state shown in Figure 5.7, a leftdequeueoperation would return element “L-2” andleft the left-hand index referencing hash chain 2,which would then contain only a single element(“R2”). In this state, a left-enqueue running concurrentlywith a right-enqueue would result in lockcontention, but the probability of such contentioncan be arbitrarily reduced by using a larger hashtable.Figure 5.8 shows how 12 elements would be organizedin a four-hash-bucket parallel double-endedqueue. Each underlying single-lock double-ended

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!