Skip to content

Example: Running a Java file

Java is one of the first languages that students in the computer science program learn. The cluster supports compiling and running Java code.

Building The Program

First, we need a java file to run. Here's a program which finds the first 100,000 prime numbers. (Note that this is a very basic implementation, finding prime numbers is an entire field of math which has complex and robust strategies)

We can copy this java program into MultiThreadedPrimeFinder.java

MultiThreadedPrimeFinder.java
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class MultiThreadedPrimeFinder {

    public static void main(String[] args) {
        int n = 100000; // Number of primes to find
        int threadCount = 32; // Number of threads

        // Shared atomic counter for the number of primes found
        AtomicInteger primesFound = new AtomicInteger(0);
        List<Integer> primes = new ArrayList<>();

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        System.out.println("Starting the process to find " + n + " prime numbers using " + threadCount + " threads.");

        int start = 2;
        while (primes.size() < n) {
            int finalStart = start;
            executorService.execute(() -> {
                if (isPrime(finalStart)) {
                    synchronized (primes) {
                        if (primesFound.get() < n) {
                            primes.add(finalStart);
                            int count = primesFound.incrementAndGet();
                            System.out.println("Prime found: " + finalStart + " (" + count + "/" + n + ")");
                        }
                    }
                }
            });
            start++;
        }

        executorService.shutdown();
        while (!executorService.isTerminated()) {
            // Wait for all tasks to complete
        }

        System.out.println("Primes: " + primes);
    }

    // Function to check if a number is prime
    private static boolean isPrime(int num) {
        if (num < 2) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

Building The Job Script

Now we need an sbatch script to run the program. We can save the following to find-primes.sh:

#!/bin/bash

#SBATCH --time=00-01:00:0
#SBATCH --ntasks=32

#SBATCH --error=error-%j.txt

module load jdk

javac MultiThreadedPrimeFinder.java
java MultiThreadedPrimeFinder

This sbatch script tells Slurm

  • The job should take 1 hour with --time
  • We need 32 CPU cores with --ntasks
  • All errors should be outputted to the file error-xxxxx.txt (where xxxxx is your job id) with --error

Then the script actually runs the program

  • module load jdk loads the Java Development Kit, the software which compiles our program
  • javac MultiThreadedPrimeFinder.java compiles the program
  • java MultiThreadedPrimeFinder runs the compiled program

Running The Job

We can start the job with sbatch find-primes.sh, you should see an output like

Submitted batch job xxxxx

This program should take around a minute to run, you can check up on its progress with myjobreport xxxxx, where xxxxx is the job id, which is given to you when you run the script with sbatch find-primes.sh

Seeing The Results

Now we can see the output of the program by reading the file slurm-xxxxx.out. You should see a block of numbers, those are all of the 100,000 prime numbers the program found.

Running this program with 32 threads (CPU cores) allows it to finish in just under one minute, if we ran it with one thread it would have taken about two minutes. Using the power of HPC we cut our compute time in half!

Using x32 the amount of CPU cores for a program usually would have sped it up significantly more, but this is a very simple example with little optimization.