【发布时间】:2017-11-11 00:47:49
【问题描述】:
我有一个例子 50.33123 可以以 FP32(1.8.23) 格式存储为 0x4249532E 。如果我们将其转换为二进制
0100 0010 0100 1001 0101 0011 0010 1110
第一位是符号位,即0表示正数,
接下来的 8 位是指数 -> 1000 01002 -> 8416 -> 13210。指数 132 -127 = 5
尾数1.1001 0010 1010 0110 0101 110(23 位)
左移我的指数 => 110010.0101010011001011102 => 50.3312310
如果我们存储相同的东西,在 FP16(半精度格式) FP16 => 1.5.10:
没有四舍五入
1.1001 0010 102
左移 5 => 110010.010102 => 50.312510,
错误是 50.33123 - 50.3125 => 0.01873。
四舍五入
1.1001 0010 112 => 左移 5 => 110010.010112 => 50.3437510,
错误是 50.33123 - 50.34375 = -0.01252
我的问题是,这里的错误很严重。
有什么方法可以通过 FP16 实现进一步减少错误?
【问题讨论】:
-
我认为你已经达到了精度的极限,没有办法进一步减少错误。 IE。我不确定我是否正确理解了您的问题。这不等于问“如何减少在无符号字节中表示 257 的错误?
257-255==2”? 2 是用无符号 8 位表示的 257 可以得到的最小错误。 -
你能展示一下你在那些 16 位浮点数上所做的计算吗?也许通过一点数学,可以在“中间值”(工作点)的基础上工作,存储在一个浮点数中,然后总是计算增量。最后添加中间值和增量并将结果用于任何用途。
-
例子:float a=50.33123, b=50.33123;键入 fp_16 a_fp16,b_fp16; a_fp16=(fp_16) 一个; b_fp16=b; for(int i =0; i
-
错字已更正。 out_fp32 += a_fp16*b_fp16; a 和 b 浮点值在我原来的情况下有所不同.. 只是为了简单起见,我添加了固定的浮点值。
-
我知道您必须将 a 和 b 存储在 16 位浮点数中;然而,计算结果最终存储(并累积)在 32 位浮点数中。您是否尝试过先转换为 32 位,然后纯粹以 32 位计算。之后,可以删除转换后的 32bit,即 a 和 b 只保留 16bit 存储。我知道这可能不是解决方案,但实验可能很有启发性。从理论上讲,您可能会(在循环中)累积一个相当小的错误,让它变大。我实际上对此表示怀疑,但为了清楚起见和排除分析,这个实验似乎是值得的。
标签: c floating-point ieee-754 half-precision-float