fp32和fp16之间转换

       深度学习中我们一般使用浮点进行原始模型的训练推理,但是有时候我们希望占用更少的内存,加快推理速度,精度又要求没有特别高的情况下,假设硬件支持了fp16的加速优化,我们就可以使用。

        那么是如何处理float和fp16转换的,在介绍这个之前,有一个前置知识点就是fp32、fp16在内存中是怎么存储的,可以看这个这篇文章。

fp32和fp16之间转换_第1张图片

下面贴下转换代码

fp32 ->fp16

typedef unsigned short half;

half nvFloat2Half(float m)
{
/*
1、强制把float转为unsigned long(32bit)
2、截取后23位尾数,右移13位,剩余10位,得到了fp16的尾数位
3、符号位直接右移16位,得到了fp16的符号位
4、截取指数的8位先右移13位,这里得到8位,但是我们只用到5位,左边多出的8位不用管
   由于之前0~255表示-127~128,调整过后变成 0~31表示-15~16,所以fp16情况下指数位是+15,
   所以这里需要在移位后指数的基础上减去(127-15) = 112(左移10位,因为指数是在bit10开始),
*/

    unsigned short t = ((m2 & 0x007fffff) >> 13) | ((m2 & 0x80000000) >> 16) 
        | (((m2 & 0x7f800000) >> 13) - (112 << 10));           
    if(m2 & 0x1000) 
        t++;                   // 四舍五入(尾数被截掉部分的最高位为1, 则尾数剩余部分+1)
    half h = *(half*)(&t);     // 强制转为half
    return h ;
}

fp16->fp32

float nvHalf2Float(half n)
{
    unsigned short frac = (n & 0x3ff) | 0x400;
    int exp = ((n & 0x7c00) >> 10) - 25;
    float m;
    if(frac == 0 && exp == 0x1f)
        m = INFINITY;
    else if (frac || exp)
        m = frac * pow(2, exp);
    else
        m = 0;
    return (n & 0x8000) ? -m : m;
}

你可能感兴趣的:(杂项,深度学习)