首页 > 编程语言 >使用 C++ 实现 FP16 转 FP32 算法

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

时间:2024-11-30 11:13:03浏览次数:5  
标签:ushort FP32 float C++ uint half FP16

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 参考文档

标签:ushort,FP32,float,C++,uint,half,FP16
From: https://www.cnblogs.com/Zheng-Bicheng/p/18578170

相关文章

  • c++历史
    #1.起源与初期阶段(1980s)##1.1BjarneStroustrup与C++的诞生C++的历史起源于1979年,当时BjarneStroustrup在AT&T贝尔实验室工作,他的目标是创建一种新编程语言,这种语言能够结合C语言的高效性和灵活性,同时加入面向对象编程(OOP)的特性以提高软件的可维护性和可扩展性。Stroust......
  • C++类的自动转换和强制类型转换
    目录一、类型转换     二、转换函数一、类型转换             C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数        简单说就是可以将内置类型转化为自定义类型    示例:classTest......
  • springboot庀材二手房交易平台--41611(免费领源码)可做计算机毕业设计JAVA、PHP、爬虫、
    摘要在互联网飞速发展的当下,开发庀材二手房交易平台是为了利用互联网和科学技术来满足二手房交易市场日益增长的需求,提供一个方便快捷的平台供用户进行二手房交易。通过开发此系统,可以解决传统二手房交易中信息不透明、中介费高昂等问题,提供更便捷、透明、安全的交易环境。......
  • C++ 游戏开发入门
    一、为什么选择C++进行游戏开发C++在游戏开发领域具有独特的地位。它兼具高效性与对底层硬件的良好控制能力,这使得它非常适合开发对性能要求极高的游戏核心引擎部分。许多知名的大型游戏,如《使命召唤》系列、《虚幻竞技场》等,其底层架构都是基于C++构建的。C++能够直接......
  • 【C++进阶篇】C++继承进阶:深入理解继承的复杂性
    文章目录须知......
  • 【C++】数据类型的存储范围与 typedef 的深度解析
    博客主页:[小ᶻ☡꙳ᵃⁱᵍᶜ꙳]本文专栏:C++文章目录......
  • C/C++大限将至!美国强硬要求:2026年前关键软件必须全面剔除C
    快科技11月3日消息,据媒体报道,美国正在加强关于危险软件开发实践的警告,提醒开发商应高度关注使用非内存安全编程语言等不良行为,C和C++更是被列为反面典型。美国网络安全与基础设施安全局(CISA)和联邦调查局(FBI)在最新报告中指出:“在支持关键基础设施或国家关键职能开发过程中,使用......
  • C++_Linux二进制格式
    C++调试工具GDB适合用于调试代码逻辑错误和程序崩溃,二者结合使用可以大大提高错误排查效率Valgrind和Memcheck更适合用于检查程序的内存问题,如内存泄漏、非法内存访问等。GFlags是VS中自带的内存检查工具gprof是一个GNU项目中的性能分析工具,用于分析C和C++程序的......
  • C++下的gRPC与protobuf使用和介绍
    目录gRPC允许定义四类服务方法流是会结束的stream(流式传输)编写流程客户端使用ClientReader客户端使用ClientWriter客户端使用ClientReaderWriter服务器端gRPC允许定义四类服务方法一元RPC:客户端发送一次请求,等待服务端响应结构,会话结束,就像一次普通的函数调用这样简单......
  • C++11-lambda表达式
    目录 1.labmda的表达式1.1.仿函数的使用  1.2lambda表达式的书写 1.3lambda的捕获列表1.3.1传值捕捉1.3.2mutable可以修改拷贝对象  1.3.3 引用捕获 1.3.4混合捕捉  1.4函数对象与lambda表达式 1.5  lambda和仿函数的比较......