为什么我在GPU上有很大的精度错误?

时间:2015-08-22 06:06:19

标签: ios precision metal

我在GPU上进行了一系列计算,需要足够高的精度,但看起来我的精度要比在CPU上使用float时低得多。

对于初学者,当我在浮点缓冲区中加载0.01的值时,它会在着色器中以0.009995加载。这是为什么?我认为0.01是浮点向量的范围值(使用可用于Metal的simd库)。

然后,当做这样的简单操作时,精度会明显变差:

simd::float4 p = simd::float4 { -0.04, -0.07, 0, 1 };
simd::float4 v = myMatrix * p;
v *= 1.0 / v.w;
示例中的

p是我期望并在CPU测试中使用的;在GPU上,它计算为{ -0.039978, -0.069946, 0.0, 1.0 },一个整数减法和一个浮点乘以已经错误的0.009995

我期望从v获得的是{ -0.010627, 0.006991, -0.034100 }(使用CPU上的simd库计算,已经比使用双精度{ -0.010613, 0.006982, -0.034056 }更精确,但可以忍受)

我得到的是{ -0.010483, 0.006405, -0.044067 }。随后的操作会变得更糟,结果很快就会无法使用。

为什么结果如此不同,即使使用相同的精度,为什么浮动数据不会以1:1的比例加载?我尝试禁用Metal的快速数学选项,但它没有改变任何东西。

2 个答案:

答案 0 :(得分:0)

唉,这不是一个精确的问题,因为我设置测试的方式是不正确的,所以GPU并没有使用我实际想到的数字。

答案 1 :(得分:-1)

由于没有二进制表示,因此浮点值不能为0.01。这就是使用0.009995的原因。我想对于二进制中的浮点数表示已经有了很好的答案,所以你只需要搜索。

这里有good tool用于检查二进制数中浮点数的样子。如果您输入0.01,您会看到:

Decimal Representation: 0.01
Binary Representation: 00111100001000111101011100001010
After casting to double precision: 0.009999999776482582