Optional Homework Assignment #4 [0 pts]


How to turn in?

Assignments need to be turned in via Lamaku

What to turn in?

You must turn in a zip archive named ics332_hw4_xxx.zip, where “xxx” is your UH user name (e.g., for me, it would be ics332_hw4_henric.zip). The archive must contain a single top-level directory called ics332_hw4_xxx, where “xxx” is your UH user name (e.g., for me, it would be ics332_hw4_henric). In that directory you must have all the files named exactly as specified in the questions below.

Expected contents of the ics332_hw4_xxx directory:

Environment

This assignment can be done on any system provided Java (and Maven) is installed (that should be your own machine, regardless or you OS).


Exercise #1: Multi-threading for Interactivity

Overview

You are hired by a company where no developer has ever done any multi-threading of any kind before (this will NOT happen in real life). The project you are working on is a prototype for an upcoming product that displays animations synced up with music. This prototype doesn’t do any syncing yet. It has three buttons:

You are provided with the code of the prototype: AnimateWithMusicJavaFX.tar or AnimateWithMusicJavaFX.zip. These are archives of a Java project that uses Apache Maven. Maven must be installed on your system.

You can uncompress the .tar archive by double-clicking it or on the command line as follows:

% tar -xvf AnimateWithMusicJavaFX.tar

Similarly, you can uncompress the .zip archive by double-clicking it or on the command line as follows:

% unzip AnimateWithMusicJavaFX.zip

Once uncompressed, in your working directory you’ll find a directory named AnimateWithMusicJavaFX:

% cd AnimateWithMusicJavaFX
% ls
pom.xml  src/

The code is a single Java source file in src/main/java/animatewithmusicjavafx/AnimateWithMusicJavaFX.java.

You can run the prototype as follows:

% mvn javafx:run

This will show a simply GUI. You can click on buttons, but you’ll quickly note the following problems:

  1. When you click the “Play Animation” button, there is no animation
  2. When you click the “Play Animation” button, then the GUI is frozen (e.g., you can’t click the “Quit” button)
  3. When you play music, which works, then the GUI is frozen while the music is playing (e.g., you can’t click the “Quit” button)

These problems are because this application is in dire need of multi-threading.

Question #1: Making the animation work

The reason why the animation doesn’t work is a bit subtle, and goes as follows:

Modify AnimateWithMusicJavaFX.java so that the animation is played by a thread other than the JavaFX thread.

Question #2: Making the music work

For the same reason as in the previous question, while the JavaFX thread is playing music (in answer to a “Play Music” button click) the GUI appears frozen.

Modify AnimateWithMusicJavaFX.java so that music is played by a thread other than the JavaFX thread.

Now, the prototype should be able to play music and animation concurrently, and the user can quit at any time.


Exercise #2: Multi-threading for Performance

In this exercise we generate the frames of a simple animated movie, where each frame is rendered using ray tracing. You are given a sequential (i.e., not multi-threaded) program, and you have to make it multi-threaded. Your new program should run faster because you have a multi-core processor.

Implementing a ray tracer belongs in a computer graphics course. So instead of implementing one I give you this jar file, raytracer.jar, which defines the package raytracer.

I also provide you with a sequential program as a starting point, MakeMovieSequential.java, which is as follows:

import raytracer.ABunchOfSpheres;

import java.lang.ArrayIndexOutOfBoundsException;
import java.lang.NumberFormatException;

public class MakeMovie {

    public MakeMovie(int num_frames) {

        // Create a movie object
        ABunchOfSpheres movie = new ABunchOfSpheres();
        // Render the frames
        for (int count = 0; count < num_frames; count++) {
            movie.render_scene("./frame_" + String.format("%05d", count) + ".png", count);
        }
    }

    private static void abort(String message) {
        System.err.println(message);
        System.exit(1);
    }

    public static void main(String[] args) {
        int num_frames = 0;
        try {
             num_frames = Integer.parseInt(args[0]);
        } catch (NumberFormatException e) {
            abort("Invalid number of frames (should be an integer)");
        } catch (ArrayIndexOutOfBoundsException e) {
            abort("Usage: java MakeMovie <num of frames>");
        }
        if (num_frames < 0) {
            abort("Invalid number of frames (should be positive)");
        }
        new MakeMovie(num_frames);
    }
}

You can run this program from your IDE or the command line, but note that we’ll do all testing on the command line. On the command line, assuming you are in a directory in which you have put the .jar file and the .java file, you can compile and run the program as follows:

% ls
MakeMovie.java	raytracer.jar
% javac -cp ./raytracer.jar MakeMovie.java 
% ls
MakeMovie.class  MakeMovie.java  raytracer.jar
% java -cp .:./raytracer.jar  MakeMovie 
Usage: java MakeMovie <num of frames>
% java -cp .:./raytracer.jar  MakeMovie  5
[1] Rendering frame #0
[1] Rendering frame #1
[1] Rendering frame #2
[1] Rendering frame #3
[1] Rendering frame #4
% ls
MakeMovie.class  frame_00000.png  frame_00001.png
frame_00002.png  frame_00003.png  frame_00004.png  
raytracer.jar    MakeMovie.java	  

This program takes a single command-line argument, which is a number of frames. It will generate the frames as image files (PNG format) in the working directory, named frame_00000.png, frame_00001.png, etc.

You may then use any tool to assemble these frames into an actual movie, e.g., with the ffmpeg tool on Linux/MacOS:

ffmpeg -framerate 30 -pattern_type glob -i '*.png' -c:v libx264 -pix_fmt yuv420p movie.mp4

but this is not required for this assignment.

Question #1 : Measuring execution time

Augment MakeMovie.java so that it prints out the execution time in seconds.

Execute your program on your quiescent machine for 48 frames, and give the execution time in your README.txt report. This will take several minutes. For debugging purposes you can of course generate fewer frames.

Question #2: Using more than 1 threads

Augment your program so that it takes an optional second command-line argument to specify any number of threads that will be used to compute movie frames (you can assume that the number of frames is divisible by the number of threads). If no argument is provided, 1 thread is used.

Distribute the computation of frames evenly across the specified number of threads. Again, you can assume that the number of frames is divisible by 1, 2, 3, and 4.

Execute your program with 2, 3 and 4 threads for 48 frames and give the execution times in your report. Briefly answer the following questions in your report: