Glsl WebGL:exp()非常不准确
我只是把数字从1循环到50,然后打印出WebGL的exp(float)计算结果。我使用的是来自WebGL2的highp精度Glsl WebGL:exp()非常不准确,glsl,webgl,webgl2,Glsl,Webgl,Webgl2,我只是把数字从1循环到50,然后打印出WebGL的exp(float)计算结果。我使用的是来自WebGL2的highp精度 precision highp float; varying vec2 TexCoords; uniform highp sampler2D A; void main() { float result = exp(texture2D(A, TexCoords).r); gl_FragColor.r = result;
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)中的lat数字:
差异“,8.25484005595456e-8,
3.700182968913168e-7,
0.0000037810978241736848,
0.0000055018942362039525,
0.000003128868712565236, ... 12720537652, 21883728284, 30738633104, 20683268800, 324543434496, 2989835245824, 6539001840640,
12329169293312, 110431739568128, 262788127178752, 615023709454336,
13695288830853123028196912005120
这些是javascript和pyton之间的最后几个区别
:
3.0517578125e-05
6.10351562E-05
0
0.0 ...
0
0
0
0
0
32
0
0.0 ...
0
0
0
262144.0
以下是WebGL计划的前几个数字:
“来自WebGL的结果”,
'2.7182817459106445,7.3890557289123535,20.08553314289844
从javascript:
“来自javascript的结果”,
'2.718281828459045,7.38905609893065,20.085536923187668
不是WebGL用户,所以我可能错了,但您的差异表明WebGL只有前
6-7位是正确的。对于32位
float精度(仅尾数的23位
)来说,这听起来是正确的
javascript结果在前16位是正确的,对应于64位
double
,因此您最有可能比较32位
与64位
的计算,因此其精确度较低也就不足为奇了
以下是比较:
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
行由e
常数乘以32bit
和64bit
上的x87计算得出。最后一行使用x87 FPU内部e^x
实现80位->64位
正如你所看到的,WebGL与32位的相关性非常紧密地支持了我的结论。不是WebGL用户,所以我可能是错的,但你的差异表明WebGL只有前6-7位是正确的。对于32位
float精度(仅尾数的23位
)来说,这听起来是正确的
javascript结果在前16位是正确的,对应于64位
double
,因此您最有可能比较32位
与64位
的计算,因此其精确度较低也就不足为奇了
以下是比较:
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
行由e
常数乘以32bit
和64bit
上的x87计算得出。最后一行使用x87 FPU内部e^x
实现80位->64位
正如你所看到的,WebGL与32位的相关性
浮动非常紧密地支持我的结论。你说的很有道理。我回去尝试使用Float32Array迫使javascript提供更兼容的答案,但这并没有带来多大区别。我也用pow(e,x)来代替,结果并没有任何改善。我们只能照原样去做。@JeffSaremi在PC上通常使用x87 FPU,其内部数字表示为80位,因此即使在32位浮点上使用exp,也会使用80位指令,结果会被截断为32位格式。在GPU上只有32位(甚至更少),因此exp本身的精度比80位要低。如果你想检查差异计算e^x
你自己喜欢的(result=1.0,i=0;我你说的很有道理。我回去尝试使用Float32Array来强制javascript得出更兼容的答案,但没有多大区别。我还使用了pow(e,x)取而代之的是,结果并没有任何改善。我们只能照原样来处理。@JeffSaremi在PC上通常使用x87 FPU,其内部数字表示为80位,因此即使在32位浮点上使用exp,也会使用80位指令,结果被截断为32位格式。在GPU上,只有32位(甚至更少)因此exp本身与80位相比精度较低。如果您想检查差异computee^x
您自己的(result=1.0,i=0;i