Tutorial |
This tutorial gives a step by step narrative for creating an example application. The application built throughout this section is a pi calculator that uses the dartboard algorithm.
In this section the following is explained:
The very first step is defining a task. A task represents the code that will run. User defined tasks must derive from Task. The most important aspect of writing the Task class is overriding the execute() method. This Execute method is the entry point into the Task.
For this pi calculator, the Execute method of the task contains the logic of the dartboard algorithm. Here is the code:
public static class PiDartboardAlgorithmTask extends Task { private PiDartboardAlgorithmTask() {} private int dartsPerTask; public PiDartboardAlgorithmTask(int dartsPerTask) { this.dartsPerTask = dartsPerTask; } @Override public void execute() { Random random = new Random(System.currentTimeMillis()); int numDartsInCircle = 0; for (int i = 0; i < this.dartsPerTask; i++) { double x = (random.nextDouble() - 0.5) * 2; double y = (random.nextDouble() - 0.5) * 2; if ((x * x) + (y * y) <= 1.0) { numDartsInCircle++; } } this.setResult(numDartsInCircle); } }
Connecting to the Coordinator consists of one line. The hostname is the DNS name or IP address of the Coordinator. If the coordinator is not running on the default port (9090), also specify the port number. The connect() method must be called before any of the operations on the coordinator can be performed.
try (IJobScheduler scheduler = new ClusterJobScheduler("localhost")) { scheduler.connect();
After Connect is successfully called in a try-with-resources block, close() will be called automatically to clean up resources upon scope exit. Otherwise, unnecessary coordinator resources will be consumed and the application may not exit properly.
Note |
---|
If an exception is thrown at the Connect method and says something like "Cannot connect to Coordinator", the most likely reason is that the Coordinator is not running on the specified machine and port. Make sure coordinator is running on that machine and confirm a firewall is not blocking the port. |
After connecting to the coordinator, specify tasks to submit. First, create a Job using createJob(). Next, instantiate the Task(s) written above. Add the tasks to the Job using addTask(agi.parallel.infrastructure.Task).
For the pi calculator, add multiple tasks to the job to get more samples. When finished adding tasks, the submit() method will actually submit the job to the coordinator.
Note |
---|
The are also many options on the job that you could specify. For this tutorial, you will just use two of the options, Name and Description. |
The pi calculator submit code should look like this:
int numDartsPerTask = 1_000_000; int numTasks = 8; Job job = scheduler.createJob(); job.setName("PiJob"); job.setDescription("Computes digits of PI using dartboard algorithm."); for (int i = 0; i < numTasks; i++) { job.addTask(new PiDartboardAlgorithmTask(numDartsPerTask)); } job.submit();
Calling waitUntilDone() will block the current thread until all of the job's tasks are completed. Once the job is completed, the result of each task is sent back to the client. One of the results you can get from the task is from the Result property.
For the pi calculator, you want to sum up the task's result. The WaitUntilDone code will look like this:
job.waitUntilDone(); int sumOfDarts = 0; for (Task task : job.getTasks()) { sumOfDarts += (Integer) task.getResult(); } System.out.format("PI is approximately %.15s", (4.0 * sumOfDarts) / (numDartsPerTask * numTasks)); }
Here is the complete application after all the steps are applied:
package stkparallelcomputingserversdk; import agi.parallel.client.ClusterJobScheduler; import agi.parallel.client.IJobScheduler; import agi.parallel.client.Job; import agi.parallel.infrastructure.Task; import java.util.Random; public class PiCalculatorTutorial { public static void main(String[] args) { try (IJobScheduler scheduler = new ClusterJobScheduler("localhost")) { scheduler.connect(); int numDartsPerTask = 1_000_000; int numTasks = 8; Job job = scheduler.createJob(); job.setName("PiJob"); job.setDescription("Computes digits of PI using dartboard algorithm."); for (int i = 0; i < numTasks; i++) { job.addTask(new PiDartboardAlgorithmTask(numDartsPerTask)); } job.submit(); job.waitUntilDone(); int sumOfDarts = 0; for (Task task : job.getTasks()) { sumOfDarts += (Integer) task.getResult(); } System.out.format("PI is approximately %.15s", (4.0 * sumOfDarts) / (numDartsPerTask * numTasks)); } } public static class PiDartboardAlgorithmTask extends Task { private PiDartboardAlgorithmTask() {} private int dartsPerTask; public PiDartboardAlgorithmTask(int dartsPerTask) { this.dartsPerTask = dartsPerTask; } @Override public void execute() { Random random = new Random(System.currentTimeMillis()); int numDartsInCircle = 0; for (int i = 0; i < this.dartsPerTask; i++) { double x = (random.nextDouble() - 0.5) * 2; double y = (random.nextDouble() - 0.5) * 2; if ((x * x) + (y * y) <= 1.0) { numDartsInCircle++; } } this.setResult(numDartsInCircle); } } }
Set up the project in a directory where the complete example above has been saved as PiCalculatorTutorial.java:
mkdir lib mkdir classes
Copy agi.parallel.client-2.9.0.jar to the lib directory. For instance:
copy [PathToSTKParallelComputingServerApiJavaFolder]\Jars\agi.parallel.client-2.9.0.jar lib
Compile PiCalculatorTutorial.java:
javac -cp lib\agi.parallel.client-2.9.0.jar -d classes stkparallelcomputingserversdk\PiCalculatorTutorial.java
Create a JAR:
jar cvf PiCalculatorTutorial.jar -C classes/ .
Run the application:
java -cp "lib\agi.parallel.client-2.9.0.jar;PiCalculatorTutorial.jar" stkparallelcomputingserversdk.PiCalculatorTutorial
Output:
pi is approximately 3.1423015
With an example application completed, explore other concepts at Key concepts or review the Library Reference.
STK Parallel Computing Server 2.9 API for Java