Lec13 ConcurrentDataStructures
Lec13 ConcurrentDataStructures
* Part of the slides adopted from the companion slides for "The Art of Multiprocessor Programming” by Maurice Herlihy and Nir Shavit
* Part of the slides adopted from “Introduction to Algorithms” by Cormen T., Leiserson C., Rivest R. and Stein C.
Review: Sorting
• Heapsort
• Merge Sort
• Quicksort
• Bucket Sort
• Radix Sort
• Stable Sort
Review: Heapsort
11
13 12
16 19 18 66
33 57 22 24 40 37
16 14 10 9 8
14 10 8 10 8 9 8 3 7 3
8 7 9 3 4 7 9 3 4 7 1 3 4 7 1 2 4 2 1 9
2 4 1 2 1 16 2 1416 10 1416 10 1416
7 4 3 2 1
4 3 2 3 2 1 1 3 2 3
1 2 8 9 1 7 8 9 4 7 8 9 4 7 8 9 4 7 8 9
10 1416 10 1416 10 1416 10 1416 10 1416
• a divide-and-conquer approach
• split the array into two roughly equal subarrays
• sort the subarrays by recursive applications of Mergesort
and merge the sorted subarrays
Review: Merge Sort
At the beginning, a “So complicated!!, I’ll
5 2 4 7 1 3 2 6
MergeSort is called split them and call other
to sort: MergeSorts to handle.”
Then the 8
MergeSorts return. All of them say
5 2 4 7 1 3 2 6 ‘This is easy. No
need to do anything.’
Review: Merge Sort
void merge(int x[ ], int lower_bound, int mid, int upper_bound)
-- merges 2 sorted sequences:
L: x[lower_bound], x[lower_bound+1], … , x[mid] L R
R: x[mid+1], x[mid+2] , …, x[upper_bound]
x = .. 2 4 5 7 1 2 3 6 ..
Step 1: Continuously copy the smallest x[lower_bound] x[upper_bound]
one from L and R to a result list x[mid]
until either L or R is finished.
idResult
idResult
idResult
idResult
idResult
idResult
idResult
idResult
Step 4: Copy the result list back to x.
Review: Quicksort
• A “partition-exchange” sorting method:
Partition an original array into: Eg. 25 10 57 48 37 12 92 86 33
(1) a subarray of small elements
=> 12 10 25 48 37 57 92 86 33
(2) a single value between (1) and (3) A possible arrangement:
simply use first element (ie.
(3) a subarray of large elements 25)
Then partition (1) and (3) independently for partitioning
down up
25 10 57 48 37 12 92 86 33
down up
25 10 12 48 37 57 92 86 33 Swap
up down
Continue repeat (*) until up
25 10 12 48 37 57 92 86 33 crosses down (ie. down >= up)
12 10 25 48 37 57 92 86 33 up is at right-most of smaller
partition, so swap a with x[up]
Review: Quicksort
Original 25 10 57 48 37 12 92 86 33
12 10 25 48 37 57 92 86 33
=> 12 10 25 48 37 57 92 86 33
10 12 25 33 37 48 92 86 57
=> 10 12 25 33 37 48 92 86 57
10 12 25 33 37 48 57 86 92
=> 10 12 25 33 37 48 57 86 92
10 12 25 33 37 48 57 86 92
=> 10 12 25 33 37 48 57 86 92
=> 10 12 25 33 37 48 57 86 92 Sorted
Review: Bucket Sort
• Comparison-based sorting algorithms
require Ω(nlogn) time
• But we can sort in O(n) time using more
powerful operations
– When elements are integers in {0,…, M-1},
bucket sort needs O(M+n) time and O(M)
space
– When M=O(n), bucket sort needs O(2n)=O(n)
time
• Note: Some books call this counting sort
Review: Bucket Sort (cont.)
• Idea: Require a counter (auxiliary) array C[0..M-1] to
count the number of occurrences of each integer in
{0,…,M-1}
• Algorithm:
– Step 1: initialize all entries in C[0..M-1] to 0
– Step 2: For i=0 to n-1
o Use A[i] as an array index and increase C[A[i]] by
one
– Step 3: For j=0 to M-1
o Write C[j] copies of value j into appropriate places
in A[0..n-1]
Review: Bucket Sort (Example)
• Input: 3, 4, 6, 9, 4, 3 where M=10
0 1 2 3 4 5 6 7 8 9
Counter array A:
• Step 1: Initialization
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0
• Step 2: Read 3
(A[3] = A[3] + 1) 0 1 2 3 4 5 6 7 8 9
0 0 0 1 0 0 0 0 0 0
• Read 4 0 1 2 3 4 5 6 7 8 9
(A[4] = A[4] + 1) 0 0 0 1 1 0 0 0 0 0
• Read 6 0 1 2 3 4 5 6 7 8 9
(A[6] = A[6] + 1) 0 0 0 1 1 0 1 0 0 0
• Read 9 0 1 2 3 4 5 6 7 8 9
(A[9] = A[9] + 1) 0 0 0 1 1 0 1 0 0 1
• Read 4 0 1 2 3 4 5 6 7 8 9
(A[4] = A[4] + 1) 0 0 0 1 2 0 1 0 0 1
• Read 3 0 1 2 3 4 5 6 7 8 9
(A[3] = A[3] + 1) 0 0 0 2 2 0 1 0 0 1
• Step 3: Print the result (from index 0 to 9)
• Result: 3, 3 0 1 2 3 4 5 6 7 8 9
0 0 0 2 2 0 1 0 0 1
• Result: 3, 3, 4, 4 0 1 2 3 4 5 6 7 8 9
0 0 0 0 2 0 1 0 0 1
• Result: 3, 3, 4, 4, 6 0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 1 0 0 1
• Result: 3, 3, 4, 4, 6, 9 0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 1
Review: Radix Sort
• Bucket sort is not efficient if M is large
• The idea of radix sort:
– Apply stable bucket sort on each digit (from
Least Significant Digit to Most Significant Digit)
• A complication:
– Just keeping the count is not enough
– Need to keep the actual elements
– Use a queue for each digit
Review: Radix Sort (Example) (1/3)
• Input: 170, 045, 075, 090, 002, 024, 802, 066
• The first pass
– Consider the least significant digits as keys and
move the keys into their buckets
0 170, 090
1
2 002, 802
3
4 024
5 045, 075
6 066
7
8
9
– Output: 170, 090, 002, 802, 024, 045, 075, 066
Review: Radix Sort (Example) (2/3)
• The second pass
• Input: 170, 090, 002, 802, 024, 045, 075, 066
– Consider the second least significant digits as
keys and move the keys into their buckets
0 002, 802
1
2 024
3
4 045
5
6 066
7 170, 075
8
9 090
– Output: 002, 802, 024, 045, 066, 170, 075, 090
Review: Radix Sort (Example) (3/3)
• The third pass
• Input: 002, 802, 024, 045, 066, 170, 075, 090
– Consider the third least significant digits as keys
and move the keys into their buckets
0 002, 024, 045, 066, 075, 090
1 170
2
3
4
5
6
7
8 802
9
– Output: 002, 024, 045, 066, 075, 090, 170, 802
(Sorted)
Review: Radix Sort Code (1/2)
// item is the type: {0,…,10d-1},
// i.e., the type of d-digit integers
void radixsort(item A[], int n, int d)
{
int i;
for (i=0; i<d; i++)
bucketsort(A, n, i);
}
Stable sort by
(2,5) (2,2) (3,2) (3,4) (9,3)
left attribute:
a. 1
b. 2
c. 3 or 4
d. 5 or 6
Exercise 2
Which sorting algorithms is most efficient to sort
string consisting of ASCII characters?
a. Quick sort
b. Heap sort
c. Merge sort
d. Bucket Sort
Exercise 3
The maximum number of comparisons needed to
sort 9 items using radix sort is (assume each item is
a 5-digit decimal number):
a. 0
b. 45
c. 72
d. 360
e. 450
Exercise 4
Applying a QuickSort Program to sort numbers in
ascending order using the first element as pivot.
Let t1 and t2 be the number of comparisons made
by the Quicksort program for the inputs {1, 2, 3, 4, 5}
and {4, 1, 5, 3, 2} respectively. Which one of the
following is true?
a. t1=5
b. t1<t2
c. t1>t2
d. t1=t2
Outlines
• Basics of Concurrency
– Concepts and Terminology
– Amdahl’s Law
• Concurrent Data Structures
Microprocessor Trend Data
Parallel/Concurrent Programs
unroll unroll
• Process
– has its own memory space and other resources.
– Difficult to communicate between processes:
Message Passing Communication
• Thread
– share all program features with that of their
parent process.
– Easy to communicate between threads:
Shared Memory Communication
Processes and Threads
• Parallelism
– Processes/threads that execute simultaneously
– Parallelism is usually applied to sections of a program
• Atomic action
– An action (instruction) that either completely happens without
interruption, or not at all
Concurrency and Parallelism
Sequential
• Liveliness
– Assures that progress continues
– Deadlock
Concurrent Example
• Let T1 and T2 be threads, X be a shared variable
between them
– X = 0; // initially
– T1::X++;
– T2::X++;
What’s the value of X?
T1 T2
Lock(X)
X++ Wait and Query
Unlock(X)
Lock(X)
X++
Unlock(X)
Mutual Exclusion and Locks (cont.)
• allows only one thread to run over the data structure at
a time
• It essentially "locks out' all other threads from accessing
the object, thus 'mutex' and 'lock' are typically used
synonymously
• Varying algorithms exist for implementation, differing in
robustness and performance
• High overhead compared to other techniques and Can
cause problems such as Deadlock, Livelock, etc.
Other Concurrent Algorithms
• Implemented by a hardware operation
– Atomically combines a load and a store, e.g., Compare-And-
Swap (CAS)
• Lock-free
– While a given thread might be blocked by other threads, all
threads can continue doing other useful work without stalls
• Wait-free
– In addition to all threads continuing to do useful work, no
computation can ever be blocked by another computation
Concurrent Queue: Lock-based
class LockBasedQueue<T> {
int front, rear;
T[] items;
std::recursive_mutex lock;
LockBasedQueue(int capacity) {
front = 0; rear = 0;
items = new T[capacity];
} }
T dequeue(){
lock.lock();
if (front != rear){
T x = items[front % items.length];
front++;
lock.unlock();
return x;
}}
2-Thread Queue: Lock-free
class WaitFreeQueue {
int front = 0, rear = 0;
items = new T[capacity];
void enqueue(T x) {
while (rear-front == capacity);
// busy-wait
items[rear % capacity] = x; rear++;
}
T dequeue() {
while (rear == front); // busy-wait
T x = items[head % capacity];
front++;
return x;
}
}
Concurrent Linked List
X X
Coarse-Grained Locking
• A simple solution is to lock the entire list for each
operation, e.g., by locking the head
Void List::RemoveNode(ListNode* q)
{
lock.lock();
ListNode* p=first;
while(p->next!=q)
p=p->next;
p->next=q->next;
lock.unlock();
}
X
Hand-Over-Hand Locking
• Assume two threads want to remove the nodes b and c
• One thread acquires the lock to a node, the other must
wait
• The same thread that acquired the lock can then lock the
next node
Void List::RemoveNode(ListNode* q)
{
ListNode* p1=first;
p1.lock();
ListNode* p2=p1->next;
p2.lock();
while(...){
… …
p1.unlock();
p1=p2;
p1.lock();
p2=p1->next;
p2.lock();
… …
}
p1.unlock();
p2.unlock();
}
Performance Analysis
• Speedup: ratio between sequential execution time and
concurrent execution time
sequential execution time
concurrent execution time
&(#)
• Let 𝑓 =
&(#) +!(#)
#
#"
" + $# ! " " ! !
Illustration of Amdahl Effect
Speedup
n = 10,000
n = 1,000
n = 100
Processors
• Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Example 1
(
$ ! #"!
'"'# + )( " '"'#& % $
Example 2
% %
)*+ = =!
! #" $#" + (% ! $#"' & ! $#"
Tree-1
• Definition and Terminology
• Binary Tree
– Operations
– Recursive functions
– Traversal
• Binary Search Tree
– Insertion, deletion
• Binary Representation of General Tree
Definition and Terminology in Tree
Terminology:
Parent and Siblings Each node is said to be the parent of the roots of its
subtrees, and the latter are said to be siblings;
they are children of their parent.
A Path from n1 to nk a sequence of nodes n1,n2,…nk such that ni is the parent
of ni+1 for 0<i<k. The length of this path is the number
of edges on the path
Ancestor and Descendant If there is a path from n1 to nk, we say nk is the
descendant of n1 and n1 is the ancestor of nk .
Level or Depth of node The length of the unique path from root to this node.
• If the tree is empty, root = NULL; otherwise from root you can find all nodes.
• root->left and root->right point to the left and right subtrees of the root, respectively.
Traversing Binary Tree
Traversing / Three principle ways:
walking through When the binary tree is empty, it is “traversed” by
doing nothing, otherwise:
A method of
examining the preorder traversal inorder traversal postorder traversal
nodes of the tree
systematically so Traverse the Traverse the
Visit the root
left subtree left subtree
that each node is
visited exactly
once. Traverse the Traverse the
Visit the root
left subtree right subtree
A
B C
D E F Traverse the Traverse the
Visit the root
right subtree right subtree
G H I
void Mytree::InorderTraversal()
{
InorderHelper(root);
}
Binary Search Tree
q Application: Find all duplicates in a list of numbers.
Method 2 - Use a special binary tree (Binary Search Tree), T:
• Read number by number. W
Binarye’ll discuss
• Each time compare the number with the contents of T. S
in a latearch Tree
• If it is found duplicated, then output, otherwise add it to T. er topi
c.
7 7 7 7 7 7 7 7
4 4 4 9 4 9 4 9 4 9 4 9
5 5 5 5 8 3 5 8 3 5 8
Binary Search Tree - Deletion
Delete a node in a BST: void Mytree::delete(TreeNode* node)
Case 3:
To delete a node that has 2 subtrees
8 8
3 11 3 12
• Replace its value by its inorder
successor: 1 5 9 14 1 5 9 14
6 101215 6 101215
The inorder successor is the 7 13 7 13
leftmost node of right subtree.
8 8
• Delete the successor in turn: 3 12 3 12
1 5 9 14 1 5 9 14
6 101215 6 101315
7 13 7
Tree-2
• Game Tree
– MiniMax Rule
– α-β pruning
– Evaluation functions
• Heap
– Heap-order
– Heap operations
– Applications
The Minimax Algorithm
• Designed to find the optimal strategy or just best first
move for MAX
• Brute-force
1. Generate the whole game tree to leaves
2. Apply utility (payoff) function to leaves
3. Back-up values from leaves toward the root:
• a Max node computes the max of its child values
• a Min node computes the min of its child values
4. When value reaches the root: choose max value and the
corresponding move.
• Minimax
Search the game-tree in a DFS manner to find the value of the root
Alpha Beta Procedure
• Idea
– Do depth first search to generate partial game tree,
– Give evaluation function to leaves,
– Compute bound on internal nodes.
• Update α-β bounds
– α value for max node means that max real value is at least α.
– β for min node means that min can guarantee a value no more
than β
• Prune whenever α ≥ β
– Prune below a Max node whose alpha value becomes greater
than or equal to the beta value of its ancestors.
– Prune below a Min node whose beta value becomes less than
or equal to the alpha value of its ancestors.
Heap
• Structure Property
– A complete binary tree
• Heap-order Property
– The data in the root is smaller than the data in all the
descendants of the root.
Or
– The data in a node is smaller than the data in its
children
ADT of Heap
Value:
#define TOTAL_SLOTS 100
A sequence of items that belong
class MyHeap
to some data type ITEM_TYPE
{
private:
Operations on heap h: int size;
1. void Insert(ITEM_TYPE e) int items[TOTAL_SLOTS];
public:
void Insert(int key);
2. /*return the value stored in the
root and then delete the root*/ int DeleteMin();
ITEM_TYPE DeleteMin() };
Heap: Insert
To insert an item Step 1: Put the item at the first empty slot in the array
Step 2: Adjust the heap to satisfy heap-order property (float up)
11 11
13 18 insert 12 13 18
16 19 37 66 16 19 37 66
33 57 22 24 40 33 57 22 24 40 12
Heap: Insert
To insert an item Step 1: Put the item at the first empty slot in the array
Step 2: Adjust the heap to satisfy heap-order property (float up)
11 11
13 18 13 18
Float up
16 19 37 66 16 19 12 66
33 57 22 24 40 12 33 57 22 24 40 37
11
13 12
16 19 18 66
33 57 22 24 40 37
Heap: DeleteMin
To delete the Min Step 1: Copy the last data to the root
Step 2: Adjust the heap to satisfy heap-order property (sink)
11 40
13 18 delete 11 13 18
16 19 37 66 16 19 37 66
33 57 22 24 40 33 57 22 24
Heap: DeleteMin
To delete the Min Step 1: Copy the last data to the root
Step 2: Adjust the heap to satisfy heap-order property (sink)
40 13
13 18 sink down 40 18
16 19 37 66 16 19 37 66
33 57 22 24 40 33 57 22 24
13 13
16 18 16 18
33 19 37 66 40 19 37 66
40 57 22 24 33 57 22 24
Tree-3
• AVL Tree
– Definition
– Rotations
• Splay tree
– Operations
AVL Trees
hL hR
L R
Insertion
• Consider insert(u): only nodes along the path from
root to the point of insertion may be unbalanced
• Suppose node v unbalanced, 4 cases:
– Cases 1 & 4 are mirror image symmetries with respect to v
– Cases 2 & 3 are mirror image symmetries with respect to v
The root of v’s left subtree v The root of v’s right subtree
x y
A B C D
Case 1 Case 2 Case 3 Case 4
Insertion
• In Case 1 (or Case 4), the insertion occurs on the
“outside” (i.e., left-left or right-right); it is fixed by a
single rotation
• In Case 2 (or Case 3), the insertion occurs on the
“inside” (i.e., left-right or right-left); it is handled by
double rotations
v
left right
x y
left right left right
A B C D
Case 1 Case 2 Case 3 Case 4
(Outside) (Inside) (Inside) (Outside)
Complexity
• Worst case time complexity of insertR(t, x):
– Local work requires constant time c
– At most 1 recursive call with tree height k-1 where k =
height of subtree pointed to by t
(Another approach)
– So, T(k) = T(k-1) + c
T(k)=T(k-1)+c
= T(k-2) + 2c
k equations
T(k-1)=T(k-2)+c
… T(k-2)=T(k-3)+c
= T(0) + kc …
= O(k) +) T(1)=T(0)+c
T(k)=T(0)+kc
• Worst case time complexity of insert(x)
= worst case time complexity of insertR(root, x)
= O(h)
where h = height of the whole tree
Theorem
• What is h (as a function of n)?
• Theorem: Every AVL-tree of height h has
≥ αh -1 nodes
– where α= (1+sqrt(5))/2 ≈1.618 (Golden ratio)
– Note: α2 = α+1
• Proof: (by induction on h)
Base Case (h=1)
– An AVL tree of height 1 has 1 node
– and 1 ≥ αh -1
Splay Trees
* Credits: https://courses.cs.washington.edu/courses/cse326/01au/lectures/SplayTrees.ppt
Splay Tree Idea
10
2 9
3
Splaying Cases
0 1 2 3 4 5 6 7 8 9
0 1 1 3 4 5 6 7 8 9
0 3 3 3 4 5 6 7 8 9
Disjoint Set (Tree Implementation)
• Theorem 1: Union-by-height
guarantees that all the trees have
depth at most O(log N), where N is
the total number of elements.
• Lemma 1. For any root x, size(x) ≥
2height(x), where size(x) is the number
of nodes of x’s tree, including x.
Maze Generation
While the entrance cell is not connected to the exit cell
Randomly pick a wall (two adjacent cells i and j)
If (Find(i)!=Find(j))
Union(i,j) //Break the wall
What is suffixes?
T = innovation
Given a string ( or text ) S[1]= innovation
T = t1 t2 t3 … tn-1 tn S[2]= nnovation
then it has n suffixes, S[3]= novation
they are S[4]= ovation
Suffix(T,i) = S[i] S[5]= vation
= ti ti+1 ti+2 … tn S[6]= ation
for S[7]= tion
1≤i≤n S[8]= ion
S[9]= on
S[10]= n
Exact Pattern Matching
• 3 standard representations
– Adjacency Matrix
– Adjacency List
Representations of graph
• Adjacency Matrix
– Use N*N 2D array to represent the weight (or T/F) of
one vertex to another
ABCD E FG
An undirected graph A 0010000
D B 0011000
F C 1101100
B
G D 0110010
E 0010011
C
A F 0001100
E
G 0000100
Representations of graph
• Adjacency Matrix
– For undirected graph, only half of the array is used
– Fast query on edge weight & connection
– Total memory used: N2 (what if num of vertex = 10K?)
– Waste memory if the graph is sparse
i.e. #Edge is much smaller than half of (#Vertex)2
a large proportion of the array will be zero
• TWO algorithms:
– DFS (Depth First Search)
– BFS (Breadth First Search)
DFS on Graphs
• Go as deep as you can
• Example DFS order (starting from 1):
– 1,2,4,6,8,5,3,7 2
– 1,5,7,3,2,8,4,6
• Using Stack to store nodes 1 3
– Put the starting node into the stack
4
– Repeat checking the top
• If top is unvisited
8
– Print this element
• If top has unvisited neighbors 5
Credits:
The CSE373 Web: © 1993-2022, Department of Computer Science and
Engineering, Univerity of Washington.
Minimum Spanning Trees
• Disjoint Set
– Equivalence relation
– Tree Implementation
– Union and Find operations
– Maze Generation
• Suffix Tree/Array
• Graph
– Adjacency matrix
– BFS and DFS
– Minimum spanning tree
– Shortest Path
Review
• Sorting
– Binary search tree + inorder traversal
– Heap sort
– Merge sort
– Quicksort
– Bucket Sort
– Radix Sort
…
From CS3334, Hope
• You can learn new data structures or modify the
data structures you learned for your needs by
yourself
– A lot of materials on the web
– A lot of references in books
– Your motivation is most important
Preorder sequence: A B D E C F H I G
Inorder Sequence: B E A H F I C G D
Postorder:?
Exercises 4
AVL tree
Showing the final result of inserting the following numbers
into an AVL tree.
{12, 28, 8, 36, 30, 17, 45}
Exercises 5
Sorting:
Given an unsorted input array
[170, 45, 75, 90, 802, 24, 2, 66],
you need to use radix sort to get the corresponding sorted
array in ascending order. Write down the resulted array in
each step (i.e., after running on a place).
Class Tree
{
public:
TreeNode* root;
int nonleaf();
...
}
Exercises 7
Coding:
return 1 + countNonLeafNodes(node->left) +
countNonLeafNodes(node->right);
}