26 Parallel Algorithms
26 Parallel Algorithms
Algorithms
1
Changing our assumptions
• So far most or all of your study of computer science has assumed
that only one thing happens at a time in a given program.
sequential programming: Each statement executes in sequence.
2
Brief arch. history
• CPU: Central Processing Unit. The brain of a computer.
From ~1980-2005, CPU speed (GHz) got exponentially faster.
Roughly doubled every 1.5 years ("Moore's Law").
Thread1
Unshared: Shared:
locals, global objects,
call stack static fields
…
Thread2 Thread3
…
…
5
Parallel vs. concurrent
• parallel: Using multiple processing resources
work
(CPUs, cores) at once to solve a problem faster.
Example: A sorting algorithm that has several
threads each sort part of the array. CPUs/cores
6
Algorithm example
• Write a method named sum that computes the total sum of all
elements in an array of integers.
For now, just write a normal solution that doesn't use parallelism.
index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
value 22 18 12 -4 27 30 36 50 7 68 91 56 2 85 42 98
index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
value 22 18 12 -4 27 30 36 50 7 68 91 56 2 85 42 98
9
Runnable partial sum
• Now write a runnable class that can sum a partial array:
11
More than 2 threads
public static int sum(int[] a) { // many threads version
int threadCount = 5; // what number is best?
int len = (int) Math.ceil(1.0 * a.length / threadCount);
Summer[] summers = new Summer[threadCount];
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
summers[i] = new Summer(a, i*len, (i+1)*len);
threads[i] = new Thread(summers[i]);
threads[i].start();
}
try {
for (Thread t : threads) {
t.join();
}
} catch (InterruptedException ie) {}
int total = 0;
for (Summer summer : summers) {
total += summer.getSum();
}
return total;
}
12
How many threads to use?
• You can find out how many cores/CPUs your machine has:
int cores =
Runtime.getRuntime().availableProcessors();
22 18 12 -4 58 7 31 42
sort -4 12 18 22 sort 7 31 42 58
merge
-4 7 12 18 22 31 42 58
Idea:
• Split array in half.
• Recursively sort each half in its own thread.
• Merge.
14
Runnable merge sort
• Write a runnable class that can merge sort an array:
public MergeSortRunner(int[] a) {
this.a = a;
}
15
Merge sort w/ threads
• Now modify the merge sort method to sort in threads:
// Parallel version (two threads)
public static void parallelMergeSort(int[] a) {
if (a.length < 2) { return; }
// split array in half
int[] left = Arrays.copyOfRange(a, 0, a.length / 2);
int[] right = Arrays.copyOfRange(a, a.length/2, a.length);
// sort each half (in parallel)
Thread lThread = new Thread(new MergeSortRunner(left));
Thread rThread = new Thread(new MergeSortRunner(right));
lThread.start();
rThread.start();
try {
lThread.join();
rThread.join();
} catch (InterruptedException ie) {}
// merge them back together
merge(left, right, a);
}
16
More than 2 threads?
• If we want to use more than 2 threads, it is tricky to code.
Have to keep an array of threads/runnables.
Tough to merge all the partial results together when done.
17
Modified Runnable
• Modify the runnable class to accept a level:
Level 0 : base case; just do a sequential merge sort.
Level K : spawn two threads at level K-1 to sort each half.
20
Map/Reduce
• map/reduce: A strategy for implementing parallel algorithms.
map: A master worker takes the problem input, divides it into smaller
sub-problems, and distributes the sub-problems to workers (threads).
reduce: The master worker collects sub-solutions from the workers and
combines them in some way to produce the overall answer.
• Our multi-threaded merge sort is an example of such an algorithm.
22
Thread static methods
Static method name Description
activeCount() number of currently runnable/active threads
dumpStack() causes current thread to print a stack trace
getAllStackTraces() returns stack trace data for all currently running threads
getCurrentThread() returns the current code's active thread
holdsLock(obj) returns true if current thread has locked the given
object
sleep(ms) causes the current thread to wait for at least the given
number of ms before continuing
yield() temporarily pauses the current thread to let others run
23
Sleeping a thread
try {
Thread.sleep(ms);
} catch (InterruptedException ie) {}