Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric009.java
41159 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @key stress randomness26*27* @summary converted from VM testbase nsk/stress/numeric/numeric009.28* VM testbase keywords: [stress, slow, nonconcurrent, quick]29* VM testbase readme:30* DESCRIPTION31* This test calculates the product A*A for a square matrix A, and checks32* if such product is calculated correctly. Elements of the matrix A are33* initiated with integer numbers, so that A*A must be the same if calculated34* with double, float, long, or int precision. The test just checks, if35* double, float, long, and int variants of the product calculation result36* in the same A*A matrix.37* Calculation of the product A*A is iterated two times, because HotSpot38* releases 1.0 and 1.3 seem to do not adjust JVM for better performance39* in 1st iteration, while 2nd iteration usually runs much faster. I guess,40* that the 1st iteration is probably executed by HotSpot interpreter, and41* HotSpot compiler is probably involved to execute the 2nd iteration. So,42* the test apparently checks accuracy of A*A calculation in both compilation43* and interpretation modes.44* By the way, the test checks JVM performance. The test is treated failed45* due to poor performance, if 1st iteration is essentially slower than the46* 2nd iteration. The calculations algorithm is encoded as rather compact47* 3-levels cycle like:48* for (int line=0; line<N; line++)49* for (int column=0; column<N; column++) {50* float sum = 0;51* for (int k=0; k<N; k++)52* sum += A[line][k] * A[k][column];53* AA[line][column] = sum;54* }55* In this test, N=200, so that A is 200x200 matrix; and multiplication56* A[line][k]*A[k][column] is executed 200**3=8 millions times in each57* iteration of execution of this cycle. I believe, that this is HotSpot58* bug to do not adjust JVM for best performance during such a huge series59* of executions of the rather compact portion of program code.60* COMMENTS61* See the bug-report:62* #4242172 (P3/S5) 2.0: poor performance in matrix calculations63*64* @library /test/lib65* @run main/othervm nsk.stress.numeric.numeric009.numeric009 200 266*/6768package nsk.stress.numeric.numeric009;6970import java.io.PrintStream;71import java.util.Random;72import jdk.test.lib.Utils;7374/**75* This test calculates the product <code>A<sup>.</sup>A</code> for a square76* matrix <code>A</code>, and checks if such product is calculated correctly.77* Elements of the matrix <code>A</code> are initiated with integer numbers,78* so that <code>A<sup>.</sup>A</code> must be the same if calculated with79* <code>double</code>, <code>float</code>, <code>long</code>, or80* <code>int</code> precision. The test just checks, if <code>double</code>,81* <code>float</code>, <code>long</code>, and <code>int</code> variants of82* the product calculation result in the same <code>A<sup>.</sup>A</code>83* matrix.84* <p>85* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated two86* times, because HotSpot releases 1.0 and 1.3 seem to do not adjust JVM for87* better performance in 1<sup>st</sup> iteration, while 2<sup>nd</sup>88* iteration usually runs much faster. I guess, that the 1<sup>st</sup> iteration89* is probably executed by HotSpot interpreter, and HotSpot compiler is probably90* involved to execute the 2<sup>nd</sup> iteration. So, the test apparently91* checks accuracy of <code>A<sup>.</sup>A</code> calculation in both compilation92* and interpretation modes.93* <p>94* <p>By the way, the test checks JVM performance. The test is treated failed95* due to poor performance, if 1<sup>st</sup> iteration is essentially slower96* than the 2<sup>nd</sup> iteration. The calculations algorithm is encoded97* as compact ``canonical'' 3-levels cycle like:98* <pre>99* for (int line=0; line<N; line++)100* for (int column=0; column<N; column++) {101* float sum = 0;102* for (int k=0; k<N; k++)103* sum += A[line][k] * A[k][column];104* AA[line][column] = sum;105* }106* </pre>107* <p>108* In this test, <code>N</code>=200, so that <code>A</code> is 200x200 matrix;109* and multiplication <code>A[line][k]*A[k][column]</code> is executed110* 200<sup>3</sup>=8 millions times in each iteration of execution of this111* cycle. I believe, that this is HotSpot bug to do not adjust JVM for best112* performance during such a huge series of executions of the rather compact113* portion of program code.114* <p>115* <p>See the bug-report:116* <br> 117* #4242172 (P3/S5) 2.0: poor performance in matrix calculations118*/119public class numeric009 {120private static final Random RNG = Utils.getRandomInstance();121/**122* When testing performance, 1st iteration is allowed to be 10% slower123* than 2nd iteration (<code>tolerance</code> is assigned to 10 now).124*/125public static double tolerance = 100; // 10;126127/**128* Re-assign this value to <code>true</code> for better129* diagnostics.130*131* @see #print(Object)132* @see #println(Object)133*/134private static boolean verbose = false;135136/**137* Stream to print execution trace and/or error messages.138* This stream usually equals to <code>System.out</code>139*/140private static PrintStream out = null;141142/**143* Print error-message.144*145* @see #out146*/147private static void complain(Object x) {148out.println("# " + x);149}150151/**152* Print to execution trace, if mode is <code>verbose</code>.153*154* @see #verbose155* @see #out156*/157private static void print(Object x) {158if (verbose)159out.print(x);160}161162/**163* Print line to execution trace, if mode is <code>verbose</code>.164*165* @see #verbose166* @see #out167*/168private static void println(Object x) {169print(x + "\n");170}171172/**173* Re-invoke <code>run(args,out)</code> in order to simulate174* JCK-like test interface.175*/176public static void main(String args[]) {177int exitCode = run(args, System.out);178System.exit(exitCode + 95);179// JCK-like exit status180}181182/**183* Parse command-line parameters stored in <code>args[]</code> and run184* the test.185* <p>186* <p>Command-line parameters are:187* <br> 188* <code>java numeric009 [-verbose] [-performance]189* [-tolerance:<i>percents</i>]190* <i>matrixSize</i> <i>iterations</i></code>191* <p>192* <p>Here:193* <br> <code>-verbose</code> -194* keyword alowing to print execution trace195* <br> <code>-performance</code> -196* keyword turning on performance testing197* <br> <code>-tolerance</code> -198* setup tolerance of performance checking199* <br> <code><i>percents</i></code> -200* 1<sup>st</sup> iteration is allowed to be201* <code><i>percents</i></code>% slower202* <br> <code><i>matrixSize</i></code> -203* number of rows (and columns) in square matrix <code>A</code>204* <br> <code><i>iterations</i></code> -205* how many times to execute the test for stronger checking206*207* @param args strings array containing command-line parameters208* @param out the test log, usually <code>System.out</code>209*/210public static int run(String args[], PrintStream out) {211numeric009.out = out;212213boolean testPerformance = false;214int numberOfCPU = 1;215216// Parse parameters starting with "-" (like: "-verbose"):217218int argsShift = 0;219for (; argsShift < args.length; argsShift++) {220String argument = args[argsShift];221222if (!argument.startsWith("-"))223break;224225if (argument.equals("-performance")) {226testPerformance = true;227continue;228}229230if (argument.equals("-verbose")) {231verbose = true;232continue;233}234235if (argument.startsWith("-tolerance:")) {236String percents =237argument.substring("-tolerance:".length(), argument.length());238tolerance = Integer.parseInt(percents);239if ((tolerance < 0) || (tolerance > 100)) {240complain("Tolerance should be 0 to 100%: " + argument);241return 2; // failure242}243continue;244}245246complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);247return 2; // failure248}249250if (args.length != argsShift + 2) {251complain("Illegal arguments. Execute:");252complain(253" java numeric009 [-verbose] [-performance] " +254"[-tolerance:percents] matrixSize iterations");255return 2; // failure256}257258int size = Integer.parseInt(args[argsShift]);259if ((size < 100) || (size > 10000)) {260complain("Matrix size should be 100 to 1000 lines & columns.");261return 2; // failure262}263264int iterations = Integer.parseInt(args[argsShift + 1]);265if ((iterations < 1) || (iterations > 100)) {266complain("Iterations number should be 1 to 100.");267return 2; // failure268}269270print("Preparing A[" + size + "," + size + "]:");271int[][] intA = newIntegerMatrix(size);272int[][] intAA = new int[size][size];273long[][] longA = newLongMatrix(intA);274long[][] longAA = new long[size][size];275double[][] doubleA = newDoubleMatrix(intA);276double[][] doubleAA = new double[size][size];277float[][] floatA = newFloatMatrix(intA);278float[][] floatAA = new float[size][size];279println(" done.");280281println("Should try " + iterations + " iteration(s):");282println("==========================" +283((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));284println("");285286double overallTime = 0;287double firstTime = 0;288double lastTime = 0;289290for (int i = 1; i <= iterations; i++) {291double seconds = elapsedTime(i,292intA, intAA, longA, longAA, floatA, floatAA, doubleA, doubleAA);293294if (i == 1)295firstTime = seconds;296else297lastTime = seconds;298overallTime += seconds;299300print("Checking accuracy:");301for (int line = 0; line < size; line++)302for (int column = 0; column < size; column++) {303if (intAA[line][column] != longAA[line][column]) {304println("");305complain("Test failed:");306complain("Integer and Long results differ at:");307complain(" line=" + line + ", column=" + column);308return 2; // FAILED309}310if (intAA[line][column] != floatAA[line][column]) {311println("");312complain("Test failed:");313complain("Integer and Float results differ at:");314complain(" line=" + line + ", column=" + column);315return 2; // FAILED316}317if (intAA[line][column] != doubleAA[line][column]) {318println("");319complain("Test failed:");320complain("Integer and Double results differ at:");321complain(" line=" + line + ", column=" + column);322return 2; // FAILED323}324}325println(" done.");326}327328double averageTime = overallTime / iterations / 4;329double averagePerformance = size * size * (size + size) / averageTime / 1e6;330331println("");332println("=======================" +333((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));334println("Overall iteration(s): " + iterations);335println("Overall elapsed time: " + overallTime + " seconds.");336println("Average elapsed time: " + averageTime + " seconds.");337println("Average performance: " + averagePerformance + " MFLOPS");338339if (testPerformance) {340print("Checking performance: ");341if (firstTime > lastTime * (1 + tolerance / 100)) {342println("");343complain("Test failed:");344complain("1st iterartion is essentially slower:");345complain("Calculation time elapsed (seconds):");346complain(" 1-st iteration: " + firstTime);347complain(" last iteration: " + lastTime);348complain(" tolerance: " + tolerance + "%");349return 2; // FAILED350}351println("done.");352}353354println("Test passed.");355return 0; // PASSED356}357358/**359* Return time (in seconds) elapsed for calculation of matrix360* product <code>A*A</code> with <code>int</code>, <code>long</code>,361* <code>float</code>, and <code>double</code> representations.362*/363private static double elapsedTime(int i,364int[][] intA, int[][] intAA,365long[][] longA, long[][] longAA,366float[][] floatA, float[][] floatAA,367double[][] doubleA, double[][] doubleAA) {368369int size = intA.length;370371if (i > 1)372println("");373println("Iteration #" + i + ":");374375print("Computing int, long, float, and double A*A:");376long mark1 = System.currentTimeMillis();377setSquare(intA, intAA);378setSquare(longA, longAA);379setSquare(floatA, floatAA);380setSquare(doubleA, doubleAA);381long mark2 = System.currentTimeMillis();382println(" done.");383384double sec = (mark2 - mark1) / 1000.0;385double perf = size * size * (size + size) / (sec / 4);386println("Elapsed time: " + sec + " seconds");387println("Performance: " + perf / 1e6 + " MOPS");388389return sec;390}391392/**393* Compute <code>A*A</code> for the given square matrix <code>A</code>.394*/395private static void setSquare(int[][] A, int[][] AA) {396if (A.length != A[0].length)397throw new IllegalArgumentException(398"the argument matrix A should be square matrix");399if (AA.length != AA[0].length)400throw new IllegalArgumentException(401"the resulting matrix AA should be square matrix");402if (A.length != AA.length)403throw new IllegalArgumentException(404"the matrices A and AA should have equal size");405406int size = A.length;407408for (int line = 0; line < size; line++)409for (int column = 0; column < size; column++) {410int sum = 0;411for (int k = 0; k < size; k++)412sum += A[line][k] * A[k][line];413AA[line][column] = sum;414}415}416417/**418* Compute <code>A*A</code> for the given square matrix <code>A</code>.419*/420private static void setSquare(long[][] A, long[][] AA) {421if (A.length != A[0].length)422throw new IllegalArgumentException(423"the argument matrix A should be square matrix");424if (AA.length != AA[0].length)425throw new IllegalArgumentException(426"the resulting matrix AA should be square matrix");427if (A.length != AA.length)428throw new IllegalArgumentException(429"the matrices A and AA should have equal size");430431int size = A.length;432433for (int line = 0; line < size; line++)434for (int column = 0; column < size; column++) {435long sum = 0;436for (int k = 0; k < size; k++)437sum += A[line][k] * A[k][line];438AA[line][column] = sum;439}440}441442/**443* Compute <code>A*A</code> for the given square matrix <code>A</code>.444*/445private static void setSquare(float[][] A, float[][] AA) {446if (A.length != A[0].length)447throw new IllegalArgumentException(448"the argument matrix A should be square matrix");449if (AA.length != AA[0].length)450throw new IllegalArgumentException(451"the resulting matrix AA should be square matrix");452if (A.length != AA.length)453throw new IllegalArgumentException(454"the matrices A and AA should have equal size");455456int size = A.length;457458for (int line = 0; line < size; line++)459for (int column = 0; column < size; column++) {460float sum = 0;461for (int k = 0; k < size; k++)462sum += A[line][k] * A[k][line];463AA[line][column] = sum;464}465}466467/**468* Compute <code>A*A</code> for the given square matrix <code>A</code>.469*/470private static void setSquare(double[][] A, double[][] AA) {471if (A.length != A[0].length)472throw new IllegalArgumentException(473"the argument matrix A should be square matrix");474if (AA.length != AA[0].length)475throw new IllegalArgumentException(476"the resulting matrix AA should be square matrix");477if (A.length != AA.length)478throw new IllegalArgumentException(479"the matrices A and AA should have equal size");480481int size = A.length;482483for (int line = 0; line < size; line++)484for (int column = 0; column < size; column++) {485double sum = 0;486for (int k = 0; k < size; k++)487sum += A[line][k] * A[k][line];488AA[line][column] = sum;489}490}491492/**493* Generate new square matrix of the given <code>size</code>494* and with elements initiated with random numbers.495*/496private static int[][] newIntegerMatrix(int size) {497if ((size < 1) || (size > 1000))498throw new IllegalArgumentException(499"matrix size should be 1 to 1000");500501int[][] A = new int[size][size];502503for (int line = 0; line < size; line++)504for (int column = 0; column < size; column++)505A[line][column] =506Math.round((float) ((1 - 2 * RNG.nextDouble()) * size));507508return A;509}510511/**512* Generate new square matrix with <code>long</code> elements,513* and initiate them with the same values as in the given matrix514* <code>intA</code>.515*/516private static long[][] newLongMatrix(int[][] intA) {517if (intA.length != intA[0].length)518throw new IllegalArgumentException(519"need square argument matrix");520521int size = intA.length;522long[][] longA = new long[size][size];523524for (int line = 0; line < size; line++)525for (int column = 0; column < size; column++)526longA[line][column] = intA[line][column];527528return longA;529}530531/**532* Generate new square matrix with <code>double</code> elements,533* and initiate them with the same values as in the given matrix534* <code>intA</code>.535*/536private static double[][] newDoubleMatrix(int[][] intA) {537if (intA.length != intA[0].length)538throw new IllegalArgumentException(539"need square argument matrix");540541int size = intA.length;542double[][] doubleA = new double[size][size];543544for (int line = 0; line < size; line++)545for (int column = 0; column < size; column++)546doubleA[line][column] = intA[line][column];547548return doubleA;549}550551/**552* Generate new square matrix with <code>float</code> elements,553* and initiate them with the same values as in the given matrix554* <code>intA</code>.555*/556private static float[][] newFloatMatrix(int[][] intA) {557if (intA.length != intA[0].length)558throw new IllegalArgumentException(559"need square argument matrix");560561int size = intA.length;562float[][] floatA = new float[size][size];563564for (int line = 0; line < size; line++)565for (int column = 0; column < size; column++)566floatA[line][column] = intA[line][column];567568return floatA;569}570571}572573574