我在NVIDIA的CUDA SDK示例中找到了此代码。
void computeGold( float* reference, float* idata, const unsigned int len)
{
reference[0] = 0;
double total_sum = 0;
unsigned int i;
for( i = 1; i < len; ++i)
{
total_sum += idata[i-1];
reference[i] = idata[i-1] + reference[i-1];
}
// Here it should be okay to use != because we have integer values
// in a range where float can be exactly represented
if (total_sum != reference[i-1])
printf("Warning: exceeding single-precision accuracy. Scan will be inaccurate.\n");
}
//(C) Nvidia Corp
有人可以告诉我一个会打印警告的情况,最重要的是,为什么。
答案 0 :(得分:5)
通常,您不能对许多浮点数求和。
最终,总和变得与每个新添加的数字不同,因此精度会丢失。例如,在浮动的情况下,添加一百万个相同数量级的数字会得到与一千万个相同的结果,因为到它完成时,每添加一个新数字都不会改变任何东西。
围绕这个的算法涉及每增加一个数字的几次乘法(实际上,只是为了正确地对数字求和)。是的,浮点很棘手。
答案 1 :(得分:2)
该功能在编写时考虑了一定范围的输入数据。如果未满足输入数据期望,则会打印警告:
#include <stdio.h>
#define COUNT_OF(x) (sizeof(x)/sizeof(0[(x)]))
void computeGold( float* reference, float* idata, const unsigned int len)
{
double total_sum = 0;
unsigned int i;
reference[0] = 0;
for( i = 1; i < len; ++i)
{
total_sum += idata[i-1];
reference[i] = idata[i-1] + reference[i-1];
}
// Here it should be okay to use != because we have integer values
// in a range where float can be exactly represented
if (total_sum != reference[i-1])
printf("Warning: exceeding single-precision accuracy. Scan will be inaccurate.\n");
}
//(C) Nvidia Corp
float data[] = {
1.0,
2.0,
3.0,
4.0,
5.0
};
float data2[] = {
123456.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
999999.0,
123456.0
};
float ref[COUNT_OF(data2)] = {0.0};
int main()
{
computeGold( ref, data, COUNT_OF(data));
computeGold( ref, data2, COUNT_OF(data2));
return 0;
}
答案 2 :(得分:1)
float
通常具有类似+/- 1e38的范围,但精度仅为大约5或6位数。这意味着,例如,可以存储类似12345678的内容,但它只能以大约6位精度存储,因此您将收到警告。