Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric005.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/numeric005.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 of the type32* double[][]. Elements of the matrix A are initiated with random numbers,33* so that optimizing compiler could not eliminate any essential portion34* of calculations.35* Calculation of the product A*A is iterated three times, and result of36* the 1st iteration is compared to result of the 3rd iteration. HotSpot37* releases 1.0 and 1.3 seem to fail to adjust itself for better performance38* in 1st iteration, while 3rd iteration usually runs much faster. So, the39* 1st iteration is probably executed by HotSpot interpreter, and HotSpot40* compiler is probably involved to execute the 3rd iteration. The test41* just tries to check if HotSpot compiler produces the same results as the42* HotSpot interpreter.43* By the way, the test checks JVM performance. The test is treated failed44* due to poor performance, if 1st iteration is essentially slower than the45* 3rd iteration. The calculations algorithm is encoded as compact 3-levels46* cycle like:47* for (int line=0; line<N; line++)48* for (int column=0; column<N; column++) {49* double sum = 0;50* for (int k=0; k<N; k++)51* sum += A[line][k] * A[k][column];52* AA[line][column] = sum;53* }54* In this test, N=300, so that A is 300x300 matrix; and multiplication55* A[line][k]*A[k][column] is executed 300**3=27 millions times in each56* execution of this cycle. I believe, that this is HotSpot bug to do not57* adjust itself for best performance during such a huge series of executions58* of the same portion of program code.59* COMMENTS60* See the bug-report:61* #4242172 (P3/S5) 2.0: poor performance in matrix calculations62*63* @library /test/lib64* @run main/othervm nsk.stress.numeric.numeric005.numeric005 300 365*/6667package nsk.stress.numeric.numeric005;6869import java.io.PrintStream;70import java.util.Random;71import jdk.test.lib.Utils;7273/**74* This test calculates the product <code>A<sup>.</sup>A</code> for75* a square matrix <code>A</code> of the type <code>double[][]</code>.76* Elements of the matrix <code>A</code> are initiated with random numbers,77* so that optimizing compiler could not eliminate any essential portion78* of calculations.79* <p>80* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three81* times, and result of the 1<sup>st</sup> iteration is compared to result of82* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust83* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>84* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably85* executed by HotSpot interpreter, and HotSpot compiler is probably involved to86* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot87* compiler produces the same results as the HotSpot interpreter.88* <p>89* <p>By the way, the test checks JVM performance. The test is treated failed90* due to poor performance, if 1<sup>st</sup> iteration is essentially slower91* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded92* as compact ``canonical'' 3-levels cycle like:93* <pre>94* for (int line=0; line<N; line++)95* for (int column=0; column<N; column++) {96* double sum = 0;97* for (int k=0; k<N; k++)98* sum += A[line][k] * A[k][column];99* AA[line][column] = sum;100* }101* </pre>102* <p>103* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;104* and multiplication <code>A[line][k]*A[k][column]</code> is executed105* 300<sup>3</sup>=27 millions times in each iteration of execution of this106* cycle. I believe, that this is HotSpot bug to do not adjust itself for best107* performance during such a huge series of executions of the same portion of108* program code.109* <p>110* <p>See the bug-report:111* <br> 112* #4242172 (P3/S5) 2.0: poor performance in matrix calculations113*/114public class numeric005 {115private static final Random RNG = Utils.getRandomInstance();116/**117* When testing performance, single thread calculation is allowed to118* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>119* is assigned to 10 now).120*/121public static final double TOLERANCE = 100; // 10;122123/**124* Re-assign this value to <code>true</code> for better125* diagnostics.126*127* @see #print(Object)128* @see #println(Object)129*/130private static boolean verbose = false;131132/**133* Stream to print execution trace and/or error messages.134* This stream usually equals to <code>System.out</code>135*/136private static PrintStream out = null;137138/**139* Print error-message.140*141* @see #out142*/143private static void complain(Object x) {144out.println("# " + x);145}146147/**148* Print to execution trace, if mode is <code>verbose</code>.149*150* @see #verbose151* @see #out152*/153private static void print(Object x) {154if (verbose)155out.print(x);156}157158/**159* Print line to execution trace, if mode is <code>verbose</code>.160*161* @see #verbose162* @see #out163*/164private static void println(Object x) {165print(x + "\n");166}167168/**169* Re-invoke <code>run(args,out)</code> in order to simulate170* JCK-like test interface.171*/172public static void main(String args[]) {173int exitCode = run(args, System.out);174System.exit(exitCode + 95);175// JCK-like exit status176}177178/**179* Parse command-line parameters stored in <code>args[]</code> and run180* the test.181* <p>182* <p>Command-line parameters are:183* <br> 184* <code>java numeric005 [-verbose] [-performance] <i>matrixSize</i>185* <i>iterations</i></code>186* <p>187* <p>Here:188* <br> <code>-verbose</code> -189* keyword, which alows to print execution trace190* <br> <code>-performance</code> -191* keyword, which alows performance testing192* <br> <code><i>matrixSize</i></code> -193* number of rows (and columns) in square matrix <code>A</code>194* <br> <code><i>iterations</i></code> -195* compute <code>A*A</code> several times196*197* @param args strings array containing command-line parameters198* @param out the test log, usually <code>System.out</code>199*/200public static int run(String args[], PrintStream out) {201numeric005.out = out;202203boolean testPerformance = false;204int numberOfCPU = 1;205206// Parse parameters starting with "-" (like: "-verbose"):207208int argsShift = 0;209for (; argsShift < args.length; argsShift++) {210String argument = args[argsShift];211212if (!argument.startsWith("-"))213break;214215if (argument.equals("-performance")) {216testPerformance = true;217continue;218}219220if (argument.equals("-verbose")) {221verbose = true;222continue;223}224225complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);226return 2; // failure227}228229if (args.length != argsShift + 2) {230complain("Illegal arguments. Execute:");231complain(232" java numeric005 [-verbose] [-performance] [-CPU:number] " +233"matrixSize iterations");234return 2; // failure235}236237int size = Integer.parseInt(args[argsShift]);238if ((size < 100) || (size > 10000)) {239complain("Matrix size should be 100 to 1000 lines & columns.");240return 2; // failure241}242243int iterations = Integer.parseInt(args[argsShift + 1]);244if ((iterations < 1) || (iterations > 100)) {245complain("Iterations number should be 1 to 100.");246return 2; // failure247}248249print("Preparing A[" + size + "," + size + "]:");250double[][] A = newMatrix(size);251double[][] A1 = new double[size][size];252double[][] Ai = new double[size][size];253println(" done.");254255println("Should try " + iterations + " iteration(s):");256println("==========================" +257((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));258println("");259260double overallTime = 0;261double firstTime = 0;262double lastTime = 0;263264for (int i = 1; i <= iterations; i++) {265double seconds;266267if (i == 1) {268seconds = elapsedTime(i, A, A1);269firstTime = seconds;270} else {271seconds = elapsedTime(i, A, Ai);272lastTime = seconds;273}274275overallTime += seconds;276}277278double averageTime = overallTime / iterations;279double averagePerformance = size * size * (size + size) / averageTime / 1e6;280281println("");282println("=======================" +283((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));284println("Overall iteration(s): " + iterations);285println("Overall elapsed time: " + overallTime + " seconds.");286println("Average elapsed time: " + averageTime + " seconds.");287println("Average performance: " + averagePerformance + " MFLOPS");288289println("========================");290print("Checking accuracy:");291for (int line = 0; line < size; line++)292for (int column = 0; column < size; column++)293if (A1[line][column] != Ai[line][column]) {294println("");295complain("Test failed:");296complain("Different results in 1st and last iterations:");297complain(" line=" + line + ", column=" + column);298return 2; // FAILED299}300println(" done.");301302if (testPerformance) {303print("Checking performance: ");304if (firstTime > lastTime * (1 + TOLERANCE / 100)) {305println("");306complain("Test failed:");307complain("1st iterartion is essentially slower:");308complain("Calculation time elapsed (seconds):");309complain(" 1-st iteration: " + firstTime);310complain(" last iteration: " + lastTime);311complain(" tolerance: " + TOLERANCE + "%");312return 2; // FAILED313}314println("done.");315}316317println("Test passed.");318return 0; // PASSED319}320321private static double elapsedTime(int i, double[][] A, double[][] AA) {322int size = A.length;323324if (i > 1)325println("");326println("Iteration #" + i + ":");327328print("Computing A*A:");329long mark1 = System.currentTimeMillis();330setSquare(A, AA);331long mark2 = System.currentTimeMillis();332println(" done.");333334double sec = (mark2 - mark1) / 1000.0;335double perf = size * size * (size + size) / sec;336println("Elapsed time: " + sec + " seconds");337println("Performance: " + perf / 1e6 + " MFLOPS");338339return sec;340}341342/**343* Compute <code>A*A</code> for the given square matrix <code>A</code>.344*/345private static void setSquare(double[][] A, double[][] AA) {346if (A.length != A[0].length)347throw new IllegalArgumentException(348"the argument matrix A should be square matrix");349if (AA.length != AA[0].length)350throw new IllegalArgumentException(351"the resulting matrix AA should be square matrix");352if (A.length != AA.length)353throw new IllegalArgumentException(354"the matrices A and AA should have equal size");355356int size = A.length;357358for (int line = 0; line < size; line++)359for (int column = 0; column < size; column++) {360double sum = 0;361for (int k = 0; k < size; k++)362sum += A[line][k] * A[k][line];363AA[line][column] = sum;364}365}366367/**368* Generate new square matrix of the given <code>size</code>369* and with elements initiated with random numbers.370*/371private static double[][] newMatrix(int size) {372if ((size < 1) || (size > 1000))373throw new IllegalArgumentException(374"matrix size should be 1 to 1000");375376double[][] A = new double[size][size];377378for (int line = 0; line < size; line++)379for (int column = 0; column < size; column++)380A[line][column] = (1 - 2 * RNG.nextDouble()) * size;381382return A;383}384385}386387388