Mads Andersen
Mads Andersen

Reputation: 3153

Float values changes. Not sure why

I have two files.

In TreeSearch.cpp I have:

int* searchTree(vector<TreeNode> &tree, vector<ImageFeature> featureList)
{
    float** features = makeMatrix(featureList, CHILDREN);
    float* featuresArray = makeArray(features, featureList.size());
    float* centroidNodes = convertTree(tree);

    int numFeatures = featureList.size();
    for(int j = 0; j < 10; j++)
    {
        cout << "C++ " << centroidNodes[j] << endl;
    }
    cout << "" << endl;

    int* votes = startSearch(centroidNodes, tree.size(), featuresArray, numFeatures);

    return votes;
}

startSearch exists in TreeSearchCUDA.cu which looks like this:

int* startSearch(float* centroids, int nodesCount, float* features, int featuresCount)
{
    for(int j = 0; j < 10; j++)
    {
        printf("CUDA %f \n", centroids[j]);
    }
    ...
}

Now if we look at the output it looks like this:

C++ 0
C++ 2.52435e-29
C++ 0
C++ 2.52435e-29
C++ 6.72623e-44
C++ 1.26117e-44
C++ 2.03982e+12
C++ 4.58477e-41
C++ 0
C++ 1.26117e-44

CUDA 0.000000 
CUDA 0.000000 
CUDA 0.000000 
CUDA 0.000000 
CUDA 0.000000 
CUDA 0.000000 
CUDA 2039820058624.000000 
CUDA 0.000000 
CUDA 0.000000 
CUDA 0.000000 

The results are not the same. Does anyone have any ideas? :) I have an idea that it is because some parts of the code is compiled with -m64 and some parts are not. However it is not possible to change this. When linking the objects I use -m64.

I hope someone has a solution or explanation :)

Upvotes: 0

Views: 1158

Answers (3)

Filip Ros&#233;en
Filip Ros&#233;en

Reputation: 63902

floats are not exact, you can use the header <limits> to get information about how many digits in your (decimal) float you can safely use and that are guaranteed to remain unchanged.

 #include <limits>

 ...

 std::cerr << std::numeric_limits<float>::digits10 << std::endl;

On my system this outputs 6, which means I can be sure that the float will be exact when using up to 6 decimals. But a number consisting of more decimals are not considered to be exact, numeric_limits<float> doesn't guarantee that these numbers will stick and remain 100% unchanged.

Another thing I might add is that printf doesn't print floating points as std::ostream does, there are often internal difference on how floating points are handled and printed. I don't think printf with %f as default "trusts" as many decimals as std::ostream in scientific representation.


#include <limits>
#include <iostream>

int
main (int argc, char *argv[])
{
  float x = 0.1234599999; // 10 digits

  std::cout.precision (10);
  std::cout << x << std::endl;
}

output (on my system)

0.1234600022

Upvotes: 1

Jeffrey Yasskin
Jeffrey Yasskin

Reputation: 5732

According to http://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf, in "Devices with compute capability 1.2" [or 1.3 for floats], "Denormal numbers (small numbers close to zero) are flushed to zero." Denormal numbers are the ones between ~1.4e−45 and ~1.18e−38 (http://en.wikipedia.org/wiki/Single-precision_floating-point_format), so that explains how your e-41 and e-44 numbers wound up at 0. I'm not sure about the e-29 ones, but something similar could have happened.

Upvotes: 0

shibumi
shibumi

Reputation: 378

It looks like from your output that CUDA is approximating really small floats to 0. All your inputs are really small floats or 0 except 2.03982e+12. 2.03982e+12 remains the same in the output. Are your centroids supposed to be really small?

Upvotes: 2

Related Questions