Assignment 2
Assignment 2
Overview
This week’s assignment is about simple multi-threaded programs in Java.
• Import the project in Eclipse: Click on File in the top-menu, then select Import. In the dialog, select
Existing Projects into Workspace under the General directory, then click on Next. In the new dialog,
select the radiobox in front of Select archive file to import a ZIP file. Then, click Browse on the right
side of the text-box to select the ZIP file you just downloaded on Moodle (assignment2.zip).
After that, you should see assignment2 as a project under Projects. Click Finish.
• If you have done everything correctly, you should now have a project named assignment2 in your
Package Explorer.
Description: Our goal in this exercise will be to parallelize the execution of the following loop defined
in computePrimeFactors method:
for (int i = 0; i < values.length; i++) {
factors[i] = numPrimeFactors(values[i]);
}
which computes the number of prime factors for each element in an given array. For example, for number
12 the number of prime factors is numPrimeFactors(12) = 3 since 12 = 2*2*3. The implementation
of numPrimeFactors is already provided for you in the assignment template and should not be changed.
Notice: Java libraries not included in the assignment project are not allowed. Do not rename any of the
provided methods in the assignment (you can create additional classes and methods).
Tasks
A) To start with, print to the console "Hello Thread!" from a new thread. How do you check that
the statement was indeed printed from a thread that is different to the main tread of your application?
Furthermore, ensure that your program (i.e., the execution of main thread) finishes only after the
thread execution finishes.
B) Run the method computePrimeFactors in a single thread other than the main thread. Measure the
execution time of sequential execution (on the main thread) and execution using a single thread. Is
there any noticeable difference?
C) Design and run an experiment that would measure the overhead of creating and executing a thread.
That is, the time it takes to create a thread object with empty runnable, calling the start method
and waiting for the thread to finish execution.
D) Before you parallelize the loop in task E), design how the work should be split between the threads
by implementing method PartitionData. Each thread should process roughly equal amount of
elements. Briefly describe your solution and discuss alternative ways to split the work.
E) Parallelize the loop execution in computePrimeFactors using a configurable number of threads.
F) Think of how would a plot that shows the execution speed-up of your implementation, for n = 1, 2,
4, 8, 16, 32, 64, 128 threads and the input array size of 100, 1000, 10000, 100000 look like.
G) Measure the execution time of your parallel implementation for n = 1, 2, 4, 8, 16, 32, 64, 128 threads
and the input array size of 100, 1000, 10000, 100000. Discuss the differences in the two plots from
task F) and G).
To understand your results, it may be a good idea to find out how many cores your system has available. In
Java, you can query the Runtime class to find this information:
int cores = Runtime.getRuntime().availableProcessors();
Java offers a couple of possibilities to create new threads. Below we briefly cover the most common
options. Regardless of the variant used to create the Thread object, we always call the start() method on
thread objects to actually run the associated threads.
The most compact option is to create the code that is run by a thread anonymously and inline:
// create thread
Thread t = new Thread(){
public void run(){
// code to execute in the thread
}
};
// start thread
t.start();
The second – and most flexible option – is to separate the task you want to accomplish and the execution of
said task. This can come in handy if you have a computation that relies on a lot of shared state but is at the
same time fairly complicated. In that scenario you want the class that implements your task to implement
Runnable. Using this method you can share a single task object between multiple threads:
2
public class MyOperation implements Runnable {
private final int initialValue;
We can then create a new thread using a new instance of our custom class:
// create thread
int initValue = 5;
Thread t = new MyThread(initValue);
// start thread
t.start();
Measuring Time
In Java you can measure time in nano-second increments using the snippet listed below.
long startTime = System.nanoTime();
3
Submission
You need to submit your code to the Git repository. You will find detailed instructions on how to install
and set-up Eclipse for use with Git in Exercise 1.
Once you have completed the skeleton, commit it to Git by following the steps described below. For the
questions that require written answers, please commit a PDF or a text file to the repository.