| /* |
| * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @key stress |
| * |
| * @summary converted from VM testbase nsk/stress/numeric/numeric010. |
| * VM testbase keywords: [stress, slow, nonconcurrent, quick] |
| * VM testbase readme: |
| * DESCRIPTION |
| * This test calculates the product A*A for a square matrix A, and checks |
| * if such product is calculated correctly. Elements of the matrix A are |
| * initiated with integer numbers, so that A*A must be the same if calculated |
| * with double, float, long, or int precision. The test just checks, if |
| * double, float, long, and int variants of the product calculation result |
| * in the same A*A matrix. |
| * The product A*A is calculated twice: in a single thread, and in N separate |
| * threads, where NxN is the size of square matrix A. When executing in N |
| * threads, each thread calculate distinct row of the resulting matrix. |
| * HotSpot releases 1.0 and 1.3 seem to do not adjust JVM for better |
| * performance in single-thread calculation, while milti-threads calculation |
| * usually runs much faster. I guess, that the 1-thread calculation is probably |
| * executed by HotSpot interpreter, and HotSpot compiler is probably involved |
| * to execute N-threads calculation. So, the test apparently checks accuracy |
| * of A*A calculation in both compilation and interpretation modes. |
| * By the way, the test checks JVM performance. The test is treated failed |
| * due to poor performance, if single-thread calculation is essentially |
| * slower than N-threads calculation (surely, the number of CPUs installed |
| * on the platform executing the test is taken into account for performance |
| * testing). The calculation algorithm is encoded with 3-levels cycle like: |
| * for (int line=0; line<N; line++) |
| * for (int column=0; column<N; column++) { |
| * float sum = 0; |
| * for (int k=0; k<N; k++) |
| * sum += A[line][k] A[k][column]; |
| * AA[line][column] = sum; |
| * } |
| * In this test, N=200, so that A is 200x200 matrix; and multiplication |
| * A[line][k]*A[k][column] is executed 200**3=8 millions times in this |
| * cycle. I believe, that this is HotSpot bug to do not adjust JVM for |
| * best performance during such a huge series of executions of the rather |
| * compact portion of program code. |
| * COMMENTS |
| * The bug was filed referencing to the same numeric algorithm, |
| * which is used by this test: |
| * 4242172 (P3/S5) 2.0: poor performance in matrix calculations |
| * Note, that despite HotSpot works faster in milti-thread calculations, |
| * it still remains essentially slower than classic VM with JIT on. |
| * |
| * @run main/othervm nsk.stress.numeric.numeric010.numeric010 200 200 |
| */ |
| |
| package nsk.stress.numeric.numeric010; |
| |
| import java.io.PrintStream; |
| |
| /** |
| * This test calculates the product <code>A<sup>.</sup>A</code> for a square |
| * matrix <code>A</code>, and checks if such product is calculated correctly. |
| * Elements of the matrix <code>A</code> are initiated with integer numbers, |
| * so that <code>A<sup>.</sup>A</code> must be the same if calculated with |
| * <code>double</code>, <code>float</code>, <code>long</code>, or |
| * <code>int</code> precision. The test just checks, if <code>double</code>, |
| * <code>float</code>, <code>long</code>, and <code>int</code> variants of |
| * the product calculation result in the same <code>A<sup>.</sup>A</code> |
| * matrix. |
| * <p> |
| * <p>The product <code>A<sup>.</sup>A</code> is calculated twice: in a single |
| * thread, and in <code>N</code> separate threads, where <code>NxN</code> is |
| * the size of square matrix <code>A</code>. When executing in <code>N</code> |
| * threads, each thread calculate distinct row of the resulting matrix. HotSpot |
| * releases 1.0 and 1.3 seem to do not adjust JVM for better performance in |
| * single-thread calculation, while milti-threads calculation usually runs much |
| * faster. I guess, that the 1-thread calculation is probably executed by HotSpot |
| * interpreter, and HotSpot compiler is probably involved to execute |
| * <code>N</code>-threads calculation. So, the test apparently checks accuracy |
| * of <code>A<sup>.</sup>A</code> calculation in both compilation and |
| * interpretation modes. |
| * <p> |
| * <p>By the way, the test checks JVM performance. The test is treated failed |
| * due to poor performance, if single-thread calculation is essentially |
| * slower than <code>N</code>-threads calculation (surely, the number of CPUs |
| * installed on the platform executing the test is taken into account for |
| * performance testing). The calculation algorithm is encoded with 3-levels |
| * cycle like: |
| * <pre> |
| * for (int line=0; line<N; line++) |
| * for (int column=0; column<N; column++) { |
| * float sum = 0; |
| * for (int k=0; k<N; k++) |
| * sum += A[line][k] * A[k][column]; |
| * AA[line][column] = sum; |
| * } |
| * </pre> |
| * <p> |
| * In this test, <code>N</code>=200, so that <code>A</code> is 200x200 matrix; |
| * and multiplication <code>A[line][k]*A[k][column]</code> is executed |
| * 200<sup>3</sup>=8 millions times in this cycle. I believe, that this is HotSpot |
| * bug to do not adjust JVM for best performance during such a huge series of |
| * executions of the rather compact portion of program code. |
| * <p> |
| * <p>See the bug-report: |
| * <br> |
| * 4242172 (P3/S5) 2.0: poor performance in matrix calculations |
| */ |
| public class numeric010 { |
| /** |
| * When testing performance, 1-thread calculation is allowed to be 10% |
| * slower than multi-thread calculation (<code>tolerance</code> is |
| * assigned to 10 now). |
| */ |
| public static double tolerance = 100; // 10; |
| |
| /** |
| * Re-assign this value to <code>true</code> for better diagnostics. |
| * |
| * @see #print(Object) |
| * @see #println(Object) |
| */ |
| private static boolean verbose = false; |
| |
| /** |
| * Stream to print execution trace and/or error messages. |
| * This stream usually equals to <code>System.out</code> |
| */ |
| private static PrintStream out = null; |
| |
| /** |
| * Print error-message. |
| * |
| * @see #out |
| */ |
| private static void complain(Object x) { |
| out.println("# " + x); |
| } |
| |
| /** |
| * Print to execution trace, if mode is <code>verbose</code>. |
| * |
| * @see #verbose |
| * @see #out |
| */ |
| private static void print(Object x) { |
| if (verbose) |
| out.print(x); |
| } |
| |
| /** |
| * Print line to execution trace, if mode is <code>verbose</code>. |
| * |
| * @see #verbose |
| * @see #out |
| */ |
| private static void println(Object x) { |
| print(x + "\n"); |
| } |
| |
| /** |
| * Re-invoke <code>run(args,out)</code> in order to simulate |
| * JCK-like test interface. |
| */ |
| public static void main(String args[]) { |
| int exitCode = run(args, System.out); |
| System.exit(exitCode + 95); |
| // JCK-like exit status |
| } |
| |
| /** |
| * Parse command-line parameters stored in <code>args[]</code> and run |
| * the test. |
| * <p> |
| * <p>Command-line parameters are: |
| * <br> |
| * <code>java numeric010 [-verbose] [-performance] |
| * [-tolerance:<i>percents</i>] [-CPU:<i>number</i>] |
| * <i>matrixSize</i> [<i>threads</i>]</code> |
| * <p> |
| * <p>Here: |
| * <br> <code>-verbose</code> - |
| * keyword, which alows to print execution trace |
| * <br> <code>-performance</code> - |
| * keyword, which alows performance testing |
| * <br> <code>-tolerance</code> - |
| * setup tolerance of performance checking |
| * <br> <code><i>percents</i></code> - |
| * 1-thread calculation is allowed to be |
| * <code><i>percents</i></code>% slower |
| * <br> <code><i>number</i></code> - |
| * number of CPU installed on the computer just executing the test |
| * <br> <code><i>matrixSize</i></code> - |
| * number of rows (and columns) in square matrix to be tested |
| * <br> <code><i>threads</i></code> - |
| * for multi-thread calculation |
| * (default: <code><i>matrixSize</i></code>) |
| * |
| * @param args strings array containing command-line parameters |
| * @param out the test log, usually <code>System.out</code> |
| */ |
| public static int run(String args[], PrintStream out) { |
| numeric010.out = out; |
| |
| boolean testPerformance = false; |
| int numberOfCPU = 1; |
| |
| int argsShift = 0; |
| for (; argsShift < args.length; argsShift++) { |
| String argument = args[argsShift]; |
| |
| if (!argument.startsWith("-")) |
| break; |
| |
| if (argument.equals("-performance")) { |
| testPerformance = true; |
| continue; |
| } |
| |
| if (argument.equals("-verbose")) { |
| verbose = true; |
| continue; |
| } |
| |
| if (argument.startsWith("-tolerance:")) { |
| String percents = |
| argument.substring("-tolerance:".length(), argument.length()); |
| tolerance = Integer.parseInt(percents); |
| |
| if ((tolerance < 0) || (tolerance > 100)) { |
| complain("Tolerance should be 0 to 100%: " + argument); |
| return 2; // failure |
| } |
| continue; |
| } |
| |
| if (argument.startsWith("-CPU:")) { |
| String value = |
| argument.substring("-CPU:".length(), argument.length()); |
| numberOfCPU = Integer.parseInt(value); |
| |
| if (numberOfCPU < 1) { |
| complain("Illegal number of CPU: " + argument); |
| return 2; // failure |
| } |
| continue; |
| } |
| |
| complain("Cannot recognize argument: args[" + argsShift + "]: " + argument); |
| return 2; // failure |
| } |
| |
| if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) { |
| complain("Illegal argument(s). Execute:"); |
| complain( |
| " java numeric010 [-verbose] [-performance] " + |
| "[-tolerance:percents] [-CPU:number] matrixSize [threads]"); |
| return 2; // failure |
| } |
| |
| int size = Integer.parseInt(args[argsShift]); |
| if ((size < 100) || (size > 10000)) { |
| complain("Matrix size should be 100 to 1000 lines & columns."); |
| return 2; // failure |
| } |
| |
| int threads = size; |
| if (args.length >= argsShift + 2) |
| threads = Integer.parseInt(args[argsShift + 1]); |
| if ((threads < 1) || (threads > size)) { |
| complain("Threads number should be 1 to matrix size."); |
| return 2; // failure |
| } |
| if ((size % threads) != 0) { |
| complain("Threads number should evenly divide matrix size."); |
| return 2; // failure |
| } |
| |
| print("Preparing A[" + size + "," + size + "]:"); |
| IntegerMatrix intA = new IntegerMatrix(size); |
| IntegerMatrix intAA = new IntegerMatrix(size); |
| LongMatrix longA = new LongMatrix(intA); |
| LongMatrix longAA = new LongMatrix(intA); |
| FloatMatrix floatA = new FloatMatrix(intA); |
| FloatMatrix floatAA = new FloatMatrix(intA); |
| DoubleMatrix doubleA = new DoubleMatrix(intA); |
| DoubleMatrix doubleAA = new DoubleMatrix(intA); |
| println(" done."); |
| |
| double elapsed[] = {0, 0}; |
| |
| for (int i = 0; i < 2; i++) { |
| double seconds = |
| elapsedTime((i == 0 ? 1 : threads), |
| intA, intAA, |
| longA, longAA, |
| floatA, floatAA, |
| doubleA, doubleAA); |
| elapsed[i] = seconds; |
| |
| print("Checking accuracy:"); |
| for (int line = 0; line < size; line++) |
| for (int column = 0; column < size; column++) { |
| if (intAA.value[line][column] != longAA.value[line][column]) { |
| println(""); |
| complain("Test failed:"); |
| complain("Integer and Long results differ at:"); |
| complain(" line=" + line + ", column=" + column); |
| complain(" intAA.value[line][column]=" + intAA.value[line][column]); |
| complain("longAA.value[line][column]=" + longAA.value[line][column]); |
| return 2; // FAILED |
| } |
| if (intAA.value[line][column] != floatAA.value[line][column]) { |
| println(""); |
| complain("Test failed:"); |
| complain("Integer and Float results differ at:"); |
| complain(" line=" + line + ", column=" + column); |
| complain(" intAA.value[line][column]=" + intAA.value[line][column]); |
| complain("floatAA.value[line][column]=" + floatAA.value[line][column]); |
| return 2; // FAILED |
| } |
| if (intAA.value[line][column] != doubleAA.value[line][column]) { |
| println(""); |
| complain("Test failed:"); |
| complain("Integer and Double results differ at:"); |
| complain(" line=" + line + ", column=" + column); |
| complain(" intAA.value[line][column]=" + intAA.value[line][column]); |
| complain("doubleAA.value[line][column]=" + doubleAA.value[line][column]); |
| return 2; // FAILED |
| } |
| } |
| println(" done."); |
| } |
| |
| double overallTime = elapsed[0] + elapsed[1]; |
| double averageTime = overallTime / 2; // 2 excutions |
| double averagePerformance = 4 * size * size * (size + size) / averageTime / 1e6; |
| println(""); |
| println("Overall elapsed time: " + overallTime + " seconds."); |
| println("Average elapsed time: " + averageTime + " seconds."); |
| println("Average performance: " + averagePerformance + " MOPS"); |
| |
| if (testPerformance) { |
| println(""); |
| print("Checking performance: "); |
| double elapsed1 = elapsed[0]; |
| double elapsedM = elapsed[1] * numberOfCPU; |
| if (elapsed1 > elapsedM * (1 + tolerance / 100)) { |
| println(""); |
| complain("Test failed:"); |
| complain("Single-thread calculation is essentially slower:"); |
| complain("Calculation time elapsed (seconds):"); |
| complain(" single thread: " + elapsed[0]); |
| complain(" multi-threads: " + elapsed[1]); |
| complain(" number of CPU: " + numberOfCPU); |
| complain(" tolerance: " + tolerance + "%"); |
| return 2; // FAILED |
| } |
| println("done."); |
| } |
| |
| println("Test passed."); |
| return 0; // PASSED |
| } |
| |
| /** |
| * Return time (in seconds) elapsed for calculation of matrix |
| * product <code>A*A</code> with <code>int</code>, <code>long</code>, |
| * <code>float</code>, and <code>double</code> representations. |
| */ |
| private static double elapsedTime(int threads, |
| IntegerMatrix intA, IntegerMatrix intAA, |
| LongMatrix longA, LongMatrix longAA, |
| FloatMatrix floatA, FloatMatrix floatAA, |
| DoubleMatrix doubleA, DoubleMatrix doubleAA) { |
| |
| println(""); |
| print("Computing A*A with " + threads + " thread(s):"); |
| long mark1 = System.currentTimeMillis(); |
| intAA.setSquareOf(intA, threads); |
| longAA.setSquareOf(longA, threads); |
| floatAA.setSquareOf(floatA, threads); |
| doubleAA.setSquareOf(doubleA, threads); |
| long mark2 = System.currentTimeMillis(); |
| println(" done."); |
| |
| int size = intA.size(); |
| double sec = (mark2 - mark1) / 1000.0; |
| double perf = 4 * size * size * (size + size) / sec; |
| println("Elapsed time: " + sec + " seconds"); |
| println("Performance: " + perf / 1e6 + " MOPS"); |
| |
| return sec; |
| } |
| |
| /** |
| * Compute <code>A*A</code> for <code>int</code> matrix <code>A</code>. |
| */ |
| private static class IntegerMatrix { |
| volatile int value[][]; |
| |
| /** |
| * Number of lines and columns in <code>this</code> square matrix. |
| */ |
| public int size() { |
| return value.length; |
| } |
| |
| /** |
| * New square matrix with random elements. |
| */ |
| public IntegerMatrix(int size) { |
| value = new int[size][size]; |
| for (int line = 0; line < size; line++) |
| for (int column = 0; column < size; column++) |
| value[line][column] = |
| Math.round((float) ((1 - 2 * Math.random()) * size)); |
| } |
| |
| /** |
| * Assign <code>this</code> matrix with <code>A*A</code>. |
| * |
| * @param threads Split computation into the given number of threads. |
| */ |
| public void setSquareOf(IntegerMatrix A, int threads) { |
| if (this.size() != A.size()) |
| throw new IllegalArgumentException( |
| "this.size() != A.size()"); |
| |
| if ((size() % threads) != 0) |
| throw new IllegalArgumentException("size()%threads != 0"); |
| int bunch = size() / threads; |
| |
| Thread task[] = new Thread[threads]; |
| for (int t = 0; t < threads; t++) { |
| int line0 = bunch * t; |
| MatrixComputer computer = |
| new MatrixComputer(value, A.value, line0, bunch); |
| task[t] = new Thread(computer); |
| } |
| |
| for (int t = 0; t < threads; t++) |
| task[t].start(); |
| |
| for (int t = 0; t < threads; t++) |
| if (task[t].isAlive()) |
| try { |
| task[t].join(); |
| } catch (InterruptedException exception) { |
| throw new RuntimeException(exception.toString()); |
| } |
| } |
| |
| /** |
| * Thread to compute a bunch of lines of matrix square. |
| */ |
| private static class MatrixComputer implements Runnable { |
| private int result[][]; |
| private int source[][]; |
| private int line0; |
| private int bunch; |
| |
| /** |
| * Register a task for matrix multiplication. |
| */ |
| public MatrixComputer( |
| int result[][], int source[][], int line0, int bunch) { |
| |
| this.result = result; // reference to resulting matrix value |
| this.source = source; // reference to matrix to be squared |
| this.line0 = line0; // compute lines from line0 to ... |
| this.bunch = bunch; // number of resulting lines to compute |
| } |
| |
| /** |
| * Do execute the task just registered for <code>this</code> thread. |
| */ |
| public void run() { |
| int line1 = line0 + bunch; |
| int size = result.length; |
| for (int line = line0; line < line1; line++) |
| for (int column = 0; column < size; column++) { |
| int sum = 0; |
| for (int i = 0; i < size; i++) |
| sum += source[line][i] * source[i][column]; |
| result[line][column] = sum; |
| } |
| } |
| |
| } |
| |
| } |
| |
| /** |
| * Compute <code>A*A</code> for <code>long</code> matrix <code>A</code>. |
| */ |
| private static class LongMatrix { |
| volatile long value[][]; |
| |
| /** |
| * Number of lines and columns in <code>this</code> square matrix. |
| */ |
| public int size() { |
| return value.length; |
| } |
| |
| |
| /** |
| * New square matrix with the given integer elements. |
| */ |
| public LongMatrix(IntegerMatrix A) { |
| int size = A.size(); |
| value = new long[size][size]; |
| for (int line = 0; line < size; line++) |
| for (int column = 0; column < size; column++) |
| value[line][column] = A.value[line][column]; |
| } |
| |
| /** |
| * Assign <code>this</code> matrix with <code>A*A</code>. |
| * |
| * @param threads Split computation into the given number of threads. |
| */ |
| public void setSquareOf(LongMatrix A, int threads) { |
| if (this.size() != A.size()) |
| throw new IllegalArgumentException( |
| "this.size() != A.size()"); |
| |
| if ((size() % threads) != 0) |
| throw new IllegalArgumentException("size()%threads != 0"); |
| int bunch = size() / threads; |
| |
| Thread task[] = new Thread[threads]; |
| for (int t = 0; t < threads; t++) { |
| int line0 = bunch * t; |
| MatrixComputer computer = |
| new MatrixComputer(value, A.value, line0, bunch); |
| task[t] = new Thread(computer); |
| } |
| |
| for (int t = 0; t < threads; t++) |
| task[t].start(); |
| |
| for (int t = 0; t < threads; t++) |
| if (task[t].isAlive()) |
| try { |
| task[t].join(); |
| } catch (InterruptedException exception) { |
| throw new RuntimeException(exception.toString()); |
| } |
| } |
| |
| /** |
| * Thread to compute a bunch of lines of matrix square. |
| */ |
| private static class MatrixComputer implements Runnable { |
| private long result[][]; |
| private long source[][]; |
| private int line0; |
| private int bunch; |
| |
| /** |
| * Register a task for matrix multiplication. |
| */ |
| public MatrixComputer( |
| long result[][], long source[][], int line0, int bunch) { |
| |
| this.result = result; // reference to resulting matrix value |
| this.source = source; // reference to matrix to be squared |
| this.line0 = line0; // compute lines from line0 to ... |
| this.bunch = bunch; // number of resulting lines to compute |
| } |
| |
| /** |
| * Do execute the task just registered for <code>this</code> thread. |
| */ |
| public void run() { |
| int line1 = line0 + bunch; |
| int size = result.length; |
| for (int line = line0; line < line1; line++) |
| for (int column = 0; column < size; column++) { |
| long sum = 0; |
| for (int i = 0; i < size; i++) |
| sum += source[line][i] * source[i][column]; |
| result[line][column] = sum; |
| } |
| } |
| |
| } |
| |
| } |
| |
| /** |
| * Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>. |
| */ |
| private static class FloatMatrix { |
| volatile float value[][]; |
| |
| /** |
| * Number of lines and columns in <code>this</code> square matrix. |
| */ |
| public int size() { |
| return value.length; |
| } |
| |
| |
| /** |
| * New square matrix with the given integer elements. |
| */ |
| public FloatMatrix(IntegerMatrix A) { |
| int size = A.size(); |
| value = new float[size][size]; |
| for (int line = 0; line < size; line++) |
| for (int column = 0; column < size; column++) |
| value[line][column] = A.value[line][column]; |
| } |
| |
| /** |
| * Assign <code>this</code> matrix with <code>A*A</code>. |
| * |
| * @param threads Split computation into the given number of threads. |
| */ |
| public void setSquareOf(FloatMatrix A, int threads) { |
| if (this.size() != A.size()) |
| throw new IllegalArgumentException( |
| "this.size() != A.size()"); |
| |
| if ((size() % threads) != 0) |
| throw new IllegalArgumentException("size()%threads != 0"); |
| int bunch = size() / threads; |
| |
| Thread task[] = new Thread[threads]; |
| for (int t = 0; t < threads; t++) { |
| int line0 = bunch * t; |
| MatrixComputer computer = |
| new MatrixComputer(value, A.value, line0, bunch); |
| task[t] = new Thread(computer); |
| } |
| |
| for (int t = 0; t < threads; t++) |
| task[t].start(); |
| |
| for (int t = 0; t < threads; t++) |
| if (task[t].isAlive()) |
| try { |
| task[t].join(); |
| } catch (InterruptedException exception) { |
| throw new RuntimeException(exception.toString()); |
| } |
| } |
| |
| /** |
| * Thread to compute a bunch of lines of matrix square. |
| */ |
| private static class MatrixComputer implements Runnable { |
| private float result[][]; |
| private float source[][]; |
| private int line0; |
| private int bunch; |
| |
| /** |
| * Register a task for matrix multiplication. |
| */ |
| public MatrixComputer( |
| float result[][], float source[][], int line0, int bunch) { |
| |
| this.result = result; // reference to resulting matrix value |
| this.source = source; // reference to matrix to be squared |
| this.line0 = line0; // compute lines from line0 to ... |
| this.bunch = bunch; // number of resulting lines to compute |
| } |
| |
| /** |
| * Do execute the task just registered for <code>this</code> thread. |
| */ |
| public void run() { |
| int line1 = line0 + bunch; |
| int size = result.length; |
| for (int line = line0; line < line1; line++) |
| for (int column = 0; column < size; column++) { |
| float sum = 0; |
| for (int i = 0; i < size; i++) |
| sum += source[line][i] * source[i][column]; |
| result[line][column] = sum; |
| } |
| } |
| |
| } |
| |
| } |
| |
| /** |
| * Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>. |
| */ |
| private static class DoubleMatrix { |
| volatile double value[][]; |
| |
| /** |
| * Number of lines and columns in <code>this</code> square matrix. |
| */ |
| public int size() { |
| return value.length; |
| } |
| |
| |
| /** |
| * New square matrix with the given integer elements. |
| */ |
| public DoubleMatrix(IntegerMatrix A) { |
| int size = A.size(); |
| value = new double[size][size]; |
| for (int line = 0; line < size; line++) |
| for (int column = 0; column < size; column++) |
| value[line][column] = A.value[line][column]; |
| } |
| |
| /** |
| * Assign <code>this</code> matrix with <code>A*A</code>. |
| * |
| * @param threads Split computation into the given number of threads. |
| */ |
| public void setSquareOf(DoubleMatrix A, int threads) { |
| if (this.size() != A.size()) |
| throw new IllegalArgumentException( |
| "this.size() != A.size()"); |
| |
| if ((size() % threads) != 0) |
| throw new IllegalArgumentException("size()%threads != 0"); |
| int bunch = size() / threads; |
| |
| Thread task[] = new Thread[threads]; |
| for (int t = 0; t < threads; t++) { |
| int line0 = bunch * t; |
| MatrixComputer computer = |
| new MatrixComputer(value, A.value, line0, bunch); |
| task[t] = new Thread(computer); |
| } |
| |
| for (int t = 0; t < threads; t++) |
| task[t].start(); |
| |
| for (int t = 0; t < threads; t++) |
| if (task[t].isAlive()) |
| try { |
| task[t].join(); |
| } catch (InterruptedException exception) { |
| throw new RuntimeException(exception.toString()); |
| } |
| } |
| |
| /** |
| * Thread to compute a bunch of lines of matrix square. |
| */ |
| private static class MatrixComputer implements Runnable { |
| private double result[][]; |
| private double source[][]; |
| private int line0; |
| private int bunch; |
| |
| /** |
| * Register a task for matrix multiplication. |
| */ |
| public MatrixComputer( |
| double result[][], double source[][], int line0, int bunch) { |
| |
| this.result = result; // reference to resulting matrix value |
| this.source = source; // reference to matrix to be squared |
| this.line0 = line0; // compute lines from line0 to ... |
| this.bunch = bunch; // number of resulting lines to compute |
| } |
| |
| /** |
| * Do execute the task just registered for <code>this</code> thread. |
| */ |
| public void run() { |
| int line1 = line0 + bunch; |
| int size = result.length; |
| for (int line = line0; line < line1; line++) |
| for (int column = 0; column < size; column++) { |
| double sum = 0; |
| for (int i = 0; i < size; i++) |
| sum += source[line][i] * source[i][column]; |
| result[line][column] = sum; |
| } |
| } |
| |
| } |
| |
| } |
| |
| } |