浮点值的变化。不知道为什么

时间:2011-12-14 05:41:49

标签: c++ floating-point cuda 32bit-64bit

我有两个文件。

  • TreeSearch.cpp
  • TreeSearchCUDA.cu

在TreeSearch.cpp中我有:

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存在于TreeSearchCUDA.cu中,如下所示:

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

现在,如果我们查看输出,它看起来像这样:

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 

结果不一样。有没有人有任何想法? :) 我知道这是因为代码的某些部分是用-m64编译的,而有些部分则不是。但是不可能改变这一点。链接对象时我使用-m64。

我希望有人有解决方案或解释:)

3 个答案:

答案 0 :(得分:2)

从您的输出看起来,CUDA正在逼近0的小浮点数。除了0之外,您的所有输入都是小浮点数或2.03982e+122.03982e+12在输出中保持不变。你的质心应该真的很小吗?

答案 1 :(得分:1)

float不准确,您可以使用标题<limits>来获取有关您可以安全使用的(十进制)浮点数中有多少位数的信息,并保证保持不变。

 #include <limits>

 ...

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

在我的系统上输出6,这意味着当使用最多6位小数时我可以确定浮点数是准确的。但是,由更多小数组成的数字不被认为是精确的,numeric_limits<float>并不能保证这些数字会保持不变并保持100%不变。

我可能会添加的另一件事是printf不会像std::ostream那样打印浮点数,因此浮点的处理和打印方式通常存在内部差异。我不认为printf %f作为默认值“信任”与科学表示中的std::ostream一样多的小数。


#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;
}

输出(在我的系统上)

0.1234600022

答案 2 :(得分:0)

根据http://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf,在“具有计算能力1.2的设备”[或浮点数为1.3]中,“非正常数字(接近零的小数字)被刷新为零。”非正规数是~1.4e-45和~1.18e-38之间的数字(http://en.wikipedia.org/wiki/Single-precision_floating-point_format),因此这解释了你的e-41和e-44数字如何结果为0.我不确定e-29的情况,但可能会发生类似情况。