一、背景
\qquad 在使用TensorRT的FP16的时候想知道FP32->FP16的时候具体做了什么,然后发现这个这方面是我的知识盲点,因此查阅资料,并记录下来。
二、解析
\qquad 这里以8.25作为例子
2.1 浮点数 十进制->二进制科学计数
\qquad
把十进制浮点数转化为二进制浮点数,整数部分和小数部分分别转化。8变为1000
,0.25变为.01
(关于小数的二进制转化),所以8.25转化为二进制就是1000.01
。
\qquad
把二进制小数转化为科学计数法
1000.1
1000.1
1000.1 ->
1.0001
×
2
3
1.0001\times2^3
1.0001×23
2.2 二进制科学计数在内存中的表示
\qquad 如果是FP32,则一个浮点数占有32bit,其中含有1bit的符号位、8bit的指数位、23bit的尾数位。由于指数为有正负之分(需要进一步探究),所以指数位的取值范围应该是-127~128,所以实际记录的时候需要把原始的指数加上偏移127( = 2 8 − 1 − 1 =2^{8-1} -1 =28−1−1); 已知 8.25 8.25 8.25-> 1.00001 × 2 3 1.00001\times2^3 1.00001×23
- 符号位为0(正);
- 指数位为3+127 = 130 转化为8位二进制就是 1000 0010
- 尾数位就是后面补零即可,保证总数是23bit。结果为 00001000000000000000000
所以 8.25在计算机中的存储方式就是
符号位 1 bit | 指数位 8 bit | 尾数位 23 bit |
---|---|---|
0 | 1000 0010 | 00001000000000000000000 |
\qquad 如果是FP64也是同理。则一个浮点数占有64bit,其中含有1bit的符号位、11 bit的指数位、52bit的尾数位,所以实际记录的时候需要把原始的指数加上偏移1023( = 2 11 − 1 − 1 =2^{11-1} -1 =211−1−1);则 8.25 8.25 8.25-> 1.00001 × 2 3 1.00001\times2^3 1.00001×23 。
- 符号位为0(正);
- 指数位为3+1023 = 1026 转化为11位二进制就是 100 0000 0010
- 尾数位就是后面补零即可,保证总数是52bit。结果为 00001000000000000000000…
符号位 1 bit | 指数位 11 bit | 尾数位 52 bit |
---|---|---|
0 | 100 0000 0010 | 0000100000000000000…0000 |
三、fp32->fp16的转化
fp32->fp16的转化有不同的转化方式:见下面的连接
http://whitelok.github.io/2018/09/05/how_to_do_caffemodel_inference_with_tensorrt_with_FP16/
参考
- https://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html
- https://en.wikipedia.org/wiki/Single-precision_floating-point_format