使用 C++ 实现 FP16 转 FP32 算法

1 简介

在当今高性能计算和深度学习领域,半精度浮点数(FP16)因其存储空间小、计算效率高的特点而被广泛应用。然而,在某些场景下,如精度要求较高的科学计算或者需要与 FP32 数据格式兼容的情况,将 FP16 转换为 FP32 就显得尤为重要。本文将介绍一种基于 C++ 实现的 FP16 到 FP32 的转换算法,该算法不仅考虑了数值精度,还优化了计算效率,旨在为开发者提供一个高效、可靠的解决方案。

2 代码实现

FP16 转 FP32 一般用于深度学习量化模型的后处理中,这里可以参考了 Rockchip 提供的类型转换代码

#ifndef _RKNN_APP_TYPE_HALF_H_
#define _RKNN_APP_TYPE_HALF_H_

typedef unsigned short half;
typedef unsigned short ushort;
typedef unsigned int uint;

uint as_uint(const float x) {
    return *(uint*)&x;
}
float as_float(const uint x) {
    return *(float*)&x;
}


float half_to_float(half x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
    // printf("1\n");
    const uint e = (x&0x7C00)>>10; // exponent
    // printf("2\n");
    const uint m = (x&0x03FF)<<13; // mantissa
    // printf("3\n");
    const uint v = as_uint((float)m)>>23; // evil log2 bit hack to count leading zeros in denormalized format
    // printf("4\n");
    return as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000))); // sign : normalized : denormalized
}


typedef union suf32
{
  int      i;
  unsigned u;
  float    f;
} suf32;

half float_to_half(float x)
  {
    suf32 in;
    in.f          = x;
    unsigned sign = in.u & 0x80000000;
    in.u ^= sign;
    ushort w;

    if (in.u >= 0x47800000)
      w = (ushort)(in.u > 0x7f800000 ? 0x7e00 : 0x7c00);
    else {
      if (in.u < 0x38800000) {
        in.f += 0.5f;
        w = (ushort)(in.u - 0x3f000000);
      } else {
        unsigned t = in.u + 0xc8000fff;
        w          = (ushort)((t + ((in.u >> 13) & 1)) >> 13);
      }
    }

    w = (ushort)(w | (sign >> 16));

    return w;
}



void float_to_half_array(float *src, half *dst, int size)
{
    for (int i = 0; i < size; i++)
    {
        dst[i] = float_to_half(src[i]);
    }
}

void half_to_float_array(half *src, float *dst, int size)
{
    for (int i = 0; i < size; i++)
    {
        dst[i] = half_to_float(src[i]);
    }
}

#endif

3 参考文档

posted @   Zheng-Bicheng  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示