我在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的快速数学选项,但它没有改变任何东西。
答案 0 :(得分:0)
答案 1 :(得分:-1)
由于没有二进制表示,因此浮点值不能为0.01
。这就是使用0.009995
的原因。我想对于二进制中的浮点数表示已经有了很好的答案,所以你只需要搜索。
这里有good tool用于检查二进制数中浮点数的样子。如果您输入0.01
,您会看到:
Decimal Representation: 0.01
Binary Representation: 00111100001000111101011100001010
After casting to double precision: 0.009999999776482582