Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric006.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/numeric006.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* float[][]. 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* float 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* @library /test/lib63* @run main/othervm nsk.stress.numeric.numeric006.numeric006 300 364*/6566package nsk.stress.numeric.numeric006;6768import java.io.PrintStream;69import java.util.Random;70import jdk.test.lib.Utils;7172/**73* This test calculates the product <code>A<sup>.</sup>A</code> for74* a square matrix <code>A</code> of the type <code>float[][]</code>.75* Elements of the matrix <code>A</code> are initiated with random numbers,76* so that optimizing compiler could not eliminate any essential portion77* of calculations.78* <p>79* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three80* times, and result of the 1<sup>st</sup> iteration is compared to result of81* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust82* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>83* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably84* executed by HotSpot interpreter, and HotSpot compiler is probably involved to85* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot86* compiler produces the same results as the HotSpot interpreter.87* <p>88* <p>By the way, the test checks JVM performance. The test is treated failed89* due to poor performance, if 1<sup>st</sup> iteration is essentially slower90* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded91* as compact ``canonical'' 3-levels cycle like:92* <pre>93* for (int line=0; line<N; line++)94* for (int column=0; column<N; column++) {95* float sum = 0;96* for (int k=0; k<N; k++)97* sum += A[line][k] * A[k][column];98* AA[line][column] = sum;99* }100* </pre>101* <p>102* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;103* and multiplication <code>A[line][k]*A[k][column]</code> is executed104* 300<sup>3</sup>=27 millions times in each iteration of execution of this105* cycle. I believe, that this is HotSpot bug to do not adjust itself for best106* performance during such a huge series of executions of the same portion of107* program code.108* <p>109* <p>See the bug-report:110* <br> 111* #4242172 (P3/S5) 2.0: poor performance in matrix calculations112*/113public class numeric006 {114private static final Random RNG = Utils.getRandomInstance();115/**116* When testing performance, single thread calculation is allowed to117* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>118* is assigned to 10 now).119*/120public static final double TOLERANCE = 100; // 10;121122/**123* Re-assign this value to <code>true</code> for better124* diagnostics.125*126* @see #print(Object)127* @see #println(Object)128*/129private static boolean verbose = false;130131/**132* Stream to print execution trace and/or error messages.133* This stream usually equals to <code>System.out</code>134*/135private static PrintStream out = null;136137/**138* Print error-message.139*140* @see #out141*/142private static void complain(Object x) {143out.println("# " + x);144}145146/**147* Print to execution trace, if mode is <code>verbose</code>.148*149* @see #verbose150* @see #out151*/152private static void print(Object x) {153if (verbose)154out.print(x);155}156157/**158* Print line to execution trace, if mode is <code>verbose</code>.159*160* @see #verbose161* @see #out162*/163private static void println(Object x) {164print(x + "\n");165}166167/**168* Re-invoke <code>run(args,out)</code> in order to simulate169* JCK-like test interface.170*/171public static void main(String args[]) {172int exitCode = run(args, System.out);173System.exit(exitCode + 95);174// JCK-like exit status175}176177/**178* Parse command-line parameters stored in <code>args[]</code> and run179* the test.180* <p>181* <p>Command-line parameters are:182* <br> 183* <code>java numeric006 [-verbose] [-performance] <i>matrixSize</i>184* <i>iterations</i></code>185* <p>186* <p>Here:187* <br> <code>-verbose</code> -188* keyword, which alows to print execution trace189* <br> <code>-performance</code> -190* keyword, which alows performance testing191* <br> <code><i>matrixSize</i></code> -192* number of rows (and columns) in square matrix <code>A</code>193* <br> <code><i>iterations</i></code> -194* compute <code>A*A</code> several times195*196* @param args strings array containing command-line parameters197* @param out the test log, usually <code>System.out</code>198*/199public static int run(String args[], PrintStream out) {200numeric006.out = out;201202boolean testPerformance = false;203int numberOfCPU = 1;204205// Parse parameters starting with "-" (like: "-verbose"):206207int argsShift = 0;208for (; argsShift < args.length; argsShift++) {209String argument = args[argsShift];210211if (!argument.startsWith("-"))212break;213214if (argument.equals("-performance")) {215testPerformance = true;216continue;217}218219if (argument.equals("-verbose")) {220verbose = true;221continue;222}223224complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);225return 2; // failure226}227228if (args.length != argsShift + 2) {229complain("Illegal arguments. Execute:");230complain(231" java numeric006 [-verbose] [-performance] [-CPU:number] " +232"matrixSize iterations");233return 2; // failure234}235236int size = Integer.parseInt(args[argsShift]);237if ((size < 100) || (size > 10000)) {238complain("Matrix size should be 100 to 1000 lines & columns.");239return 2; // failure240}241242int iterations = Integer.parseInt(args[argsShift + 1]);243if ((iterations < 1) || (iterations > 100)) {244complain("Iterations number should be 1 to 100.");245return 2; // failure246}247248print("Preparing A[" + size + "," + size + "]:");249float[][] A = newMatrix(size);250float[][] A1 = new float[size][size];251float[][] Ai = new float[size][size];252println(" done.");253254println("Should try " + iterations + " iteration(s):");255println("==========================" +256((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));257println("");258259double overallTime = 0;260double firstTime = 0;261double lastTime = 0;262263for (int i = 1; i <= iterations; i++) {264double seconds;265266if (i == 1) {267seconds = elapsedTime(i, A, A1);268firstTime = seconds;269} else {270seconds = elapsedTime(i, A, Ai);271lastTime = seconds;272}273274overallTime += seconds;275}276277double averageTime = overallTime / iterations;278double averagePerformance = size * size * (size + size) / averageTime / 1e6;279280println("");281println("=======================" +282((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));283println("Overall iteration(s): " + iterations);284println("Overall elapsed time: " + overallTime + " seconds.");285println("Average elapsed time: " + averageTime + " seconds.");286println("Average performance: " + averagePerformance + " MFLOPS");287288println("========================");289print("Checking accuracy:");290for (int line = 0; line < size; line++)291for (int column = 0; column < size; column++)292if (A1[line][column] != Ai[line][column]) {293println("");294complain("Test failed:");295complain("Different results in 1st and last iterations:");296complain(" line=" + line + ", column=" + column);297return 2; // FAILED298}299println(" done.");300301if (testPerformance) {302print("Checking performance: ");303if (firstTime > lastTime * (1 + TOLERANCE / 100)) {304println("");305complain("Test failed:");306complain("1st iterartion is essentially slower:");307complain("Calculation time elapsed (seconds):");308complain(" 1-st iteration: " + firstTime);309complain(" last iteration: " + lastTime);310complain(" tolerance: " + TOLERANCE + "%");311return 2; // FAILED312}313println("done.");314}315316println("Test passed.");317return 0; // PASSED318}319320private static double elapsedTime(int i, float[][] A, float[][] AA) {321int size = A.length;322323if (i > 1)324println("");325println("Iteration #" + i + ":");326327print("Computing A*A:");328long mark1 = System.currentTimeMillis();329setSquare(A, AA);330long mark2 = System.currentTimeMillis();331println(" done.");332333double sec = (mark2 - mark1) / 1000.0;334double perf = size * size * (size + size) / sec;335println("Elapsed time: " + sec + " seconds");336println("Performance: " + perf / 1e6 + " MFLOPS");337338return sec;339}340341/**342* Compute <code>A*A</code> for the given square matrix <code>A</code>.343*/344private static void setSquare(float[][] A, float[][] AA) {345if (A.length != A[0].length)346throw new IllegalArgumentException(347"the argument matrix A should be square matrix");348if (AA.length != AA[0].length)349throw new IllegalArgumentException(350"the resulting matrix AA should be square matrix");351if (A.length != AA.length)352throw new IllegalArgumentException(353"the matrices A and AA should have equal size");354355int size = A.length;356357for (int line = 0; line < size; line++)358for (int column = 0; column < size; column++) {359float sum = 0;360for (int k = 0; k < size; k++)361sum += A[line][k] * A[k][line];362AA[line][column] = sum;363}364}365366/**367* Generate new square matrix of the given <code>size</code>368* and with elements initiated with random numbers.369*/370private static float[][] newMatrix(int size) {371if ((size < 1) || (size > 1000))372throw new IllegalArgumentException(373"matrix size should be 1 to 1000");374375float[][] A = new float[size][size];376377for (int line = 0; line < size; line++)378for (int column = 0; column < size; column++)379A[line][column] = (float) ((1 - 2 * RNG.nextDouble()) * size);380381return A;382}383384}385386387