cutComparef weird results TEST FAILED when outputs are the same (cpu vs gpu)

Hello,

im having a little trouble comparing float arrays , the CPU one vs the GPU one. using this struct (used in programming guide)

typedef struct {

	int width;

	int height;

	int stride;

	float* elements;

} Matrix;

im using the computeGold template and this is what i do:

CUTBoolean res = cutComparef( reference.elements, h_C.elements, h_C.width*h_C.height);

printf( "Test %s\n", (1 == res) ? "PASSED" : "FAILED");

the program receives sizes for Matrix A and Matrix B, then it generates random numbers for both, and finally computes A*B = C

when i print the result of CPU (Matrix reference)and GPU work (Matrix C), they are the same, this is my output when launching my program

(pd: Dont get confused on the GPU time result, here i used small data just for you to understand the problem with the outputs printed. on big matrix GPU times blow CPU 200x even more.)

neoideo@neoideo-desktop:~/Nvidia_SDK/C/bin/linux/debug$ ./simpleMatrixShared 4x4 4x4

A=>4x4

B=>4x4

C=>4x4

ANTES DE RELLENAR -------  ------- DESPUES DE RELLENAR

GPU multiplicacion --- START --- Processing time: 56.550999 (ms) --- END

CPU multiplicacion --- START --- Processing Time: 0.00095367432 (ms) ---  END

Test FAILED

-----IMPRIMIENDO MATRIZ-----A

 0.366790  0.437543  0.236515  0.894392 

 0.026073  0.813584  0.102234  0.098250 

 0.382419  0.049658  0.267055  0.855136 

 0.579588  0.750424  0.332670  0.865555 

-----IMPRIMIENDO MATRIZ-----B

 0.988612  0.575575  0.618203  0.785277 

 0.648654  0.058282  0.159358  0.189566 

 0.483458  0.537688  0.400861  0.363449 

 0.818858  0.980238  0.142091  0.185648 

-----IMPRIMIENDO MATRIZ-----C

 1.493152  1.240504  0.518371  0.622978 

 0.683389  0.213702  0.200711  0.230098 

 1.239619  1.204834  0.472884  0.565533 

 1.929352  1.404655  0.734231  0.878989 

-----IMPRIMIENDO MATRIZ-----referencia

 1.493152  1.240504  0.518371  0.622978 

 0.683389  0.213702  0.200711  0.230098 

 1.239619  1.204834  0.472884  0.565533 

 1.929352  1.404655  0.734231  0.878989 

-----COMPARANDO MATRIZ-----[Referencia] contra [h_C]

Referencia		h_C			Diferencia

1.493152		1.493152		0.000000

1.240504		1.240504		0.000000

0.518371		0.518371		0.000000

0.622978		0.622978		0.000000

0.683389		0.683389		0.000000

0.213702		0.213702		0.000000

0.200711		0.200711		0.000000

0.230098		0.230098		0.000000

1.239619		1.239619		0.000000

1.204834		1.204834		0.000000

0.472884		0.472884		0.000000

0.565533		0.565533		0.000000

1.929352		1.929352		0.000000

1.404655		1.404655		0.000000

0.734231		0.734231		0.000000

0.878989		0.878989		0.000000

Press ENTER to exit...

why does it report FAILED? i dont see the problem.

[quote name=‘neoideo’ post=‘585074’ date=‘Sep 3 2009, 12:37 PM’]

[codebox]CUTBoolean CUTIL_API

cutComparef( const float* reference, const float* data,

        const unsigned int len ) 

{

const float epsilon = 0.0;

return compareData( reference, data, len, epsilon, 0.0f );

}

[/codebox]

[codebox] template<class T, class S>

CUTBoolean  

compareData( const T* reference, const T* data, const unsigned int len, 

             const S epsilon, const float threshold) 

{

    CUT_CONDITION( epsilon >= 0);

    bool result = true;

    unsigned int error_count = 0;

    for( unsigned int i = 0; i < len; ++i) {

        T diff = reference[i] - data[i];

        bool comp = (diff <= epsilon) && (diff >= -epsilon);  

        result &= comp;

        error_count += !comp;

#ifdef _DEBUG

        if( ! comp) {

            std::cerr << "ERROR, i = " << i << ",\t " 

                << reference[i] << " / " << data[i] << " (reference / data)\n";

        }

#endif

    }

    if (threshold == 0.0f) {

        return (result) ? CUTTrue : CUTFalse;

    } else {

        if (error_count) {

            printf("%4.2f(%%) of bytes mismatched (count=%d)\n", (float)error_count*100/(float)len, error_count);

        }

        return (len*threshold > error_count) ? CUTTrue : CUTFalse;

    }

}[/codebox]
  1. from source code

    "bool comp = (diff <= epsilon) && (diff >= -epsilon); " and “epsilon = 0.0”

comp is true if diff is zero (means two data are the same)

but this is impossible for your code, since floating point don’t have associative property.

so C = AB (cpu version) is not equal to C = AB (GPU version)

you can use debug mode (say invoke macro _DEBUG), then cutComparef will report difference

  1. I suggest that using another metric, say measure relative error

    max|C(cpu) - C(gpu)| / max|C(cpu)|
    

    it should be 1.E-6 ~ 1.E-7

wow thanks

i see now, i wish that “epsilon” could be in the parameters of the cutcomparef function.
ill check how much the error is and do some custom compare functions.
anyway i did the difference of each element of the matrix, on the final part of the printing the results where all 0 but maybe with more precision i can see the diferences.

tmurray will be along shortly (complete with baseball bat) to discuss your usage of CUTIL in your own code :)