Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6812207

Possible bug in a floating point (float) arithmetic in 32-bit server HotSpot

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 6u10
    • hotspot
    • x86
    • windows_vista

      FULL PRODUCT VERSION :
      java version "1.6.0_12"
      Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
      Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)

      FULL OS VERSION :
      Microsoft Windows [Version 6.0.6001]

      A DESCRIPTION OF THE PROBLEM :
      There might be a bug in a floating point (float) arithmetic in 32-bit server HotSpot. Incorrect results appear for 2-D, single precision, not power-of-two sizes, real input, Fast Fourier Transform (http://piotr.wendykier.googlepages.com/jtransforms).
      The error occurs only under the following conditions:
      - Sun JVM (32-bit)
      - "-server" flag
      - JIT enabled
      - single precision code

      Here is a link to the forum, where this problem has been discussed: http://forums.sun.com/thread.jspa?threadID=5368823&tstart=0

      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Download jtransforms-2.2.jar from http://piotr.wendykier.googlepages.com/jtransforms

      2. Compile the attached source code:

      javac -cp jtransforms-2.3.jar AccuracyCheckFloatFFT_2D.java

      3. Run the code in the client mode (there should be no error):

      java -cp .;jtransforms-2.3.jar AccuracyCheckFloatFFT_2D

      4. Run the code in the server mode (there should be a few errors):

      java -server -cp .;jtransforms-2.3.jar AccuracyCheckFloatFFT_2D


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected output from step 3:

      Checking accuracy of 2D, single precision, real input FFTs
      size = 2 x 2; OK
      size = 3 x 3; OK
      size = 4 x 4; OK
      size = 5 x 5; OK
      size = 6 x 6; OK
      size = 7 x 7; OK
      size = 8 x 8; OK
      size = 9 x 9; OK
      size = 10 x 10; OK
      size = 11 x 11; OK
      size = 12 x 12; OK
      size = 13 x 13; OK
      size = 16 x 16; OK
      size = 32 x 32; OK
      size = 64 x 64; OK
      size = 100 x 100; OK
      size = 120 x 120; OK
      size = 128 x 128; OK
      size = 256 x 256; OK
      size = 310 x 310; OK
      size = 511 x 511; OK

      Expected output from step 4:

      Checking accuracy of 2D, single precision, real input FFTs
      size = 2 x 2; OK
      size = 3 x 3; OK
      size = 4 x 4; OK
      size = 5 x 5; OK
      size = 6 x 6; OK
      size = 7 x 7; OK
      size = 8 x 8; OK
      size = 9 x 9; OK
      size = 10 x 10; OK
      size = 11 x 11; OK
      size = 12 x 12; OK
      size = 13 x 13; OK
      size = 16 x 16; OK
      size = 32 x 32; OK
      size = 64 x 64; OK
      size = 100 x 100; OK
      size = 120 x 120; error = 0.230260
      size = 128 x 128; OK
      size = 256 x 256; OK
      size = 310 x 310; error = 0.244690
      size = 511 x 511; OK

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.Random;

      import edu.emory.mathcs.jtransforms.fft.FloatFFT_2D;
      import edu.emory.mathcs.utils.ConcurrencyUtils;

      /**
       * This is the source code that demonstrates a possible bug in Sun JVM (32-bit
       * server HotSpot). To reproduce the error, 32-bit JVM has to be used with
       * "-server" flag and JIT compiler enabled.
       *
       * @author Piotr Wendykier (###@###.###)
       *
       */
      public class AccuracyCheckFloatFFT_2D {

          public static void main(String[] args) {
              int[] sizes = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, 64, 100, 120, 128, 256, 310, 511 };
              ConcurrencyUtils.setNumberOfThreads(1); //use only sequential code
              System.out.println("Checking accuracy of 2D, single precision, real input FFTs");
              for (int i = 0; i < sizes.length; i++) {
                  run(sizes[i], sizes[i]);
              }
          }

          /**
           * Checks the accuracy of 2D, single precision, real input FFTs
           *
           * @param rows
           * @param columns
           */
          private static void run(int rows, int columns) {
              float[][] a = new float[rows][2 * columns];
              Random rand = new Random(0);
              for (int r = 0; r < rows; r++) {
                  for (int c = 0; c < columns; c++) {
                      a[r][c] = rand.nextFloat();
                  }
              }
              float[][] b = new float[rows][2 * columns];
              for (int r = 0; r < rows; r++) {
                  for (int c = 0; c < columns; c++) {
                      b[r][2 * c] = a[r][c];
                  }
              }

              FloatFFT_2D fft = new FloatFFT_2D(rows, columns);
              fft.realForwardFull(a);
              fft.complexInverse(a, true);
              double err = computeRMSE(a, b);
              double eps = 1e-6;
              if (err > eps) {
                  System.out.println(String.format("size = %3d x %3d; error = %f", rows, columns, err));
              } else {
                  System.out.println(String.format("size = %3d x %3d; OK", rows, columns));
              }
          }

          /**
           * Computes the Root Mean Square Error of two arrays
           *
           * @param a
           * @param b
           * @return
           */
          private static double computeRMSE(float[][] a, float[][] b) {
              if (a.length != b.length || a[0].length != b[0].length) {
                  throw new IllegalArgumentException("Arrays are not of the same size.");
              }
              double rms = 0;
              double tmp;
              for (int r = 0; r < a.length; r++) {
                  for (int c = 0; c < a[0].length; c++) {
                      tmp = (a[r][c] - b[r][c]);
                      rms += tmp * tmp;
                  }
              }
              return Math.sqrt(rms / (a.length * a[0].length));
          }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I have not found one yet.

            cfang Changpeng Fang (Inactive)
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: