6 Replies Latest reply on Mar 12, 2011 10:38 AM by kena

    Could somebody run this code for me? I got weird results.

    junghyun

      #include <stdio.h>

       

      int main(void)
      {
        int i;
        int wrong_count = 0;
        const double denom=16.0;
        const int ARRAY_MAX=1024;

        double dbl_array[ARRAY_MAX];
        double value;
        double comparison;

        for( i = 0; i < ARRAY_MAX; ++i )
        {
          dbl_array[i] = ((double)i / denom);
        }

        for( i = 0; i < ARRAY_MAX; ++i )
        {
          dbl_array[i] *= 123.456;
        }

        for( i = 0; i < ARRAY_MAX; ++i )
        {
          value = dbl_array[i];
          comparison = (i/denom)*123.456;
          if( value != comparison )
          {
            if( wrong_count++ < 4 )
            {
              printf("dbl_array[%d] = %lf, %lf, %lf\n",
                  i, dbl_array[i],
                  value, comparison);
            }
          }
        }
        printf("wrong_count = %d\n", wrong_count);

       

        return 0;
      }

       

       

      This is a simple code running on SCC linux.

       

      In my SCC(marc016), it shows wrong_count more than zero.

       

      However, in my desktop, wrong_count=0.

       

      Could you run this code on your SCC for me?

       

      Please tell me what is the value of wrong_count.

       

      Thank you in advance.

        • 1. Re: Could somebody run this code for me? I got weird results.
          junghyun

          I got some results.

           

          First of all, it looks like a compiler bug.

           

          I compiled the code like below.

           

          gcc -O2 -DCOPPERRIDGE -static helloSCC.c -o helloSCC

          icpc -DCOPPERRIDGE -static -mcpu=pentium -gcc-version=340 helloSCC.c -o helloSCC

           

          The two executables got wrong result.

           

          However,

           

          gcc -DCOPPERRIDGE -static helloSCC.c -o helloSCC

           

          This is got a right result.

           

          So, I think this is a bug of the compilers.

           

          Any comments?

          • 2. Re: Could somebody run this code for me? I got weird results.
            kena

            I think that your test program is wrong. Namely, your program should not test for equality using C's "==" operator, but rather check for some minimal difference, i.e. fabs(value - comparison) < EPSILON.

             

            (for some value of EPSILON meaningful for your computation)

             

            What would be more interesting as a benchmark is the following:

             

            #include <stdio.h>

             

            int main(void)
            {
              int i;
              int wrong_count = 0;
              const double denom=16.0;
              const int ARRAY_MAX=1024;

              double dbl_array[ARRAY_MAX];
              double value;
              double comparison;

              double maxdiff = 0;

              double t;

              for( i = 0; i < ARRAY_MAX; ++i )
              {
                dbl_array[i] = ((double)i / denom);
              }

              for( i = 0; i < ARRAY_MAX; ++i )
              {
                dbl_array[i] *= 123.456;
              }

              for( i = 0; i < ARRAY_MAX; ++i )
              {
                value = dbl_array[i];
                comparison = (i/denom)*123.456;

             

                t = fabs(value - comparison);

                if (t > maxdiff) maxdiff = t;

              }
              printf("maximum difference = %lf\n", maxdiff);

             

              return 0;
            }

             

             

            What does this program print?

             

             

            Also check this paper from Goldberg: http://cr.yp.to/2005-590/goldberg.pdf

            It is essential to keep this knowledge in mind when evaluating FP "accuracy".

            • 3. Re: Could somebody run this code for me? I got weird results.
              junghyun

              Thank you for your reply.

               

              I didn't read that paper yet(It's very long!). However, how can you explain this?

               

              1. without -O option, it prints "wrong_count=0"

              2. with -O option, it prints "wrong_count=1013"

               

              This is sequential program and always produce same result.

              • 4. Re: Could somebody run this code for me? I got weird results.
                kena

                The reason why your floating point behavior differs is that without -O, the result of the operation in the 3rd loop are forced in and out of memory before the comparison for equality to set the precision. Since the Intel micro-arch uses more precision bits internally (80 or 96?) than in the memory format (64 bits), this effectively changes the values from what is present in the FP registers. Therefore the result is equal to what was precomputed in the array. (the array values were also stored in memory by loop 2  and re-loaded in loop 3)

                 

                With -O, loop 1 and 2 still store the FP values to memory, but loop 3 does not. In loop 3 the computation of "comparison" happens with FP regs and is directly followed by the compare operation without going to memory. This means that "comparison" was not truncated by a memory operation like "value" was. This is why "value" and "comparison" become different.

                 

                Again if you check out my program you should see this precision effect.

                • 5. Re: Could somebody run this code for me? I got weird results.
                  junghyun

                  Okay, thank you very much. I understand your words now.

                   

                  I tested it before, but I got only zeros.

                   

                  However, I increased the precision, it printed strange values.

                   

                  In conclusion, I should not compare two FP values directly. right?

                  • 6. Re: Could somebody run this code for me? I got weird results.
                    kena

                    As I said before the "reliable" way to compare floats is fabs(value - comparison) < EPSILON.

                    1 of 1 people found this helpful