WebGL:exp() 非常不准确

WebGL: exp() is insanely inaccurate

我只是对从 1 到 50 的数字进行了循环,并打印出了 WebGL 对 exp(float) 的计算。我使用的是高精度,这些来自 WebGL2。

   precision highp float;
    varying vec2 TexCoords;
    uniform highp sampler2D A;

    void main() {
      float result = exp(texture2D(A, TexCoords).r);
      gl_FragColor.r = result;
    }

我运行在javascript中做了同样的事情并比较了结果。聪明的东西很小,但加起来很快就会变成非常非常大的数字。

所以我也比较了 javascript 和 python (numpy) 的结果,它们非常具有可比性。

这是 Math.abs(diff) 中的几个纬度数字:

Diffs', '8.25484005595456e-8, 3.700182968913168e-7, 0.0000037810978241736848, 0.0000055018942362039525, 0.000003128868712565236, ... 12720537652, 21883728284, 30738633104, 20683268800, 324543434496, 2989835245824, 6539001840640, 12329169293312, 110431739568128, 262788127178752, 615023709454336, 1369528883085312, 3028196912005120

这些是 javascript 和 pyton 之间的最后几个差异 :

3.0517578125e-05 6.103515625e-05 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 32.0 0.0 0.0 ... 0.0 0.0 0.0 262144.0

这些是 WebGL 程序的前几个数字:

'Results from WebGL', '2.7182817459106445,7.3890557289123535,20.085533142089844,

来自javascript:

'Results from javascript', '2.718281828459045,7.38905609893065,20.085536923187668,

不是 WebGL 用户,所以我可能是错的,但您的差异表明只有前 6-7 位数字对于 WebGL[=41= 是正确的].这听起来适合 32bit 浮点精度(只有 23bits 的尾数)

javascript 结果在前 16 位数字中是正确的,对应于 64bit double 所以你很可能比较 32bit64bit 计算相比,它的精确度较低也就不足为奇了。

此处比较:

WebGL     : 2.7182817459106445 ,7.3890557289123535 ,20.085533142089844  ,
javascript: 2.718281828459045  ,7.38905609893065   ,20.085536923187668  ,
PI float  : 2.71828174591064453,7.38905572891235352,20.08553504943847656,
PI double : 2.71828182845904509,7.38905609893064952,20.08553692318766437,
x87 double: 2.7182818284590451 ,7.3890560989306504 ,20.0855369231876679 ,

前两行是您的号码。 PI 行是通过 32bit64bitx87 计算的 e 常数相乘计算得出的。最后一行使用 x87 FPU 内部 e^x 实现 80bit -> 64bit.

如您所见,WebGL32bit 浮动密切相关,支持我的结论。