Since I'm a very new student in Computer Sciences MSc, I'm learning a lot of new stuff about programming and especially about Java and C threads this week. Today, one my programming teacher asked us to make a Java exercice about threads to understand how they could be useful for your CPU load.

The thing is to generate a matrix and calcultate it average using some trigonometric math' operations. The benchmark uses the main class and a threading class ; both classes include the calculating method.
The concept is to calculate the whole matrix average using the un-threaded calculator to obtain a reference test and next to this test, calculate the same matrix using a defined number of threaded calculators.

Let's see with the Java code now:

``````/**
* Main.java
* @author 33xiT
*/
public class Main {
/**
* Calculate an average sum with a trigonometric calcul simulation to "load" CPU
* @param matrix
* @param matrix_size
* @return
*/
public static double calculateAverage(double[][] matrix, int matrix_size) {
double sum = 0.;
for (int i = 0; i < matrix_size; i++) {
for (int j = 0; j < matrix_size; j++) {
sum += matrix[i][j] * Math.atan2(Math.sqrt(matrix[i][j]), Math.pow(matrix[i][j], 2.9));
}
}
return sum;
}

/**
* Main class method
* Two optional parameters: int matrix_size int part_number
* @param args
*/
public static void main(String[] args) {
try {
int matrix_size = 4000;
int part_number = 4;

if (args.length == 2) {
matrix_size = new Integer(args);
part_number = new Integer(args);
}

long tt1, tr1, test_time, result_time = 0;
int start, gain = 0;
int part_size = matrix_size / part_number;
double test, result = 0.;
double matrix[][] = new double[matrix_size][];

System.out.println("Matrix size: " + matrix_size + "\nPart number (thread number): " + part_number);
System.out.println("Matrix initialization...");

for (int i = 0; i < matrix_size; i++) {
matrix[i] = new double[matrix_size];
for (int j = 0; j < matrix_size; j++) {
matrix[i][j] = Math.random() * 10000;
}
}

System.out.println("Matrix initialized.");
System.out.println("Calculating matrix average w/o thread (test result)...");

tt1 = System.currentTimeMillis();
test = calculateAverage(matrix, matrix_size);
test_time = System.currentTimeMillis() - tt1;

System.out.println("Average w/o threading = " + test + " in " + test_time + " ms");

tr1 = System.currentTimeMillis();

for (int i = 0; i < part_number; i++) {
start = i * part_size;

if (i == part_number - 1 && (start + part_size) < matrix_size) {
part_size = matrix_size - start;
}

calculators[i] = new ThreadedMatrixCalculator(matrix, start, part_size);
calculators[i].start();
// System.out.println(calculators[i]);
}

for (int i = 0; i < part_number; i++) {
calculators[i].join();
result += calculators[i].getSum();
}

result_time = System.currentTimeMillis() - tr1;
gain = (int) (100 - ((result_time * 100) / test_time));

System.out.println("Average w/ threading = " + result + " in " + result_time + " ms");
System.out.println("Threaded calculting gain: ≈ +" + gain + "%");

} catch (OutOfMemoryError e) {
System.gc();
System.out.println("Error: " + e);
} catch (InterruptedException e) {
System.out.println("Error: " + e);
}
}
}
``````

``````/**
* @author 33xiT
*/

protected double _sum = 0.;
protected double[][] _tab;
protected int _offset, _length;

/**
* Class constructor
* @param tab
* @param offset
* @param length
*/
public ThreadedMatrixCalculator(double[][] tab, int offset, int length) {
this._tab = tab;
this._offset = offset;
this._length = length;
}

/**
*/
public void run() {
this.calculateAverage();
}

/**
* Sum getter
* @return
*/
public double getSum() {
return this._sum;
}

/**
* Calculate an average sum with a trigonometric calcul simulation to "load" CPU
*/
public void calculateAverage() {
for (int i = this._offset; i < (this._offset + this._length); i++) {
for (int j = 0; j < this._tab.length; j++) {
this._sum += this._tab[i][j] * Math.atan2(Math.sqrt(this._tab[i][j]), Math.pow(this._tab[i][j], 2.9));
}
}
}

/**
* @return
*/
public String toString() {
return new String(this + "@ [offset=" + this._offset + ",length=" + this._length + "]");
}
}
``````

You can run it using an IDE or why not directly in your console:

``````% javac *.java
% java Main
Matrix size: 4000
Matrix initialization...
Matrix initialized.
Calculating matrix average w/o thread (test result)...
Average w/o threading = 4771.371926919315 in 5336 ms
Average w/ threading = 4771.371926918524 in 2878 ms
%
``````

You can try with customized parameters, we want a matrix size of 2873 and we want 20 threads to calculate it average:

``````% java Main 2873 20
Matrix size: 2873
Matrix initialization...
Matrix initialized.
Calculating matrix average w/o thread (test result)...
Average w/o threading = 2454.1397977533056 in 2755 ms