fp16半精度浮点数转成float类型------C/C++

2024-08-30 22:48

本文主要是介绍fp16半精度浮点数转成float类型------C/C++,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在深度学习算法模型推理时,会遇到fp16类型,但是我们的c语言中没有这种类型,直接转成unsigned short又会丧失精度,因此我们首先将FP16转成float类型,再进行计算。

方法1:

typedef unsigned short ushort;//占用2个字节
typedef unsigned int uint;    //占用4个字节uint as_uint(const float x) {return *(uint*)&x;
}
float as_float(const uint x) {return *(float*)&x;
}float half_to_float(const ushort 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 digitsconst uint e = (x&0x7C00)>>10; // exponentconst uint m = (x&0x03FF)<<13; // mantissaconst uint v = as_uint((float)m)>>23; // evil log2 bit hack to count leading zeros in denormalized formatreturn 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
}
ushort float_to_half(const float 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 digitsconst uint b = as_uint(x)+0x00001000; // round-to-nearest-even: add last bit after truncated mantissaconst uint e = (b&0x7F800000)>>23; // exponentconst uint m = b&0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial roundingreturn (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate
}

方法2:

float cpu_half2float(unsigned short x)
{unsigned sign = ((x >> 15) & 1);unsigned exponent = ((x >> 10) & 0x1f);unsigned mantissa = ((x & 0x3ff) << 13);if (exponent == 0x1f) {  /* NaN or Inf */mantissa = (mantissa ? (sign = 0, 0x7fffff) : 0);exponent = 0xff;} else if (!exponent) {  /* Denorm or Zero */if (mantissa) {unsigned int msb;exponent = 0x71;do {msb = (mantissa & 0x400000);mantissa <<= 1;  /* normalize */--exponent;} while (!msb);mantissa &= 0x7fffff;  /* 1.mantissa is implicit */}} else {exponent += 0x70;}int temp = ((sign << 31) | (exponent << 23) | mantissa);return *((float*)((void*)&temp));
}

3 demo

 下面的demo中,yolov5_outputs[0].buf是void *类型的,void *类型不能++,因此先转换成ushort*类型。

    ......   float *data0 = (float*)malloc(4 * output_attrs[0].n_elems);float *data1 = (float*)malloc(4 * output_attrs[1].n_elems);float *data2 = (float*)malloc(4 * output_attrs[2].n_elems);unsigned short *temp0 = (ushort*)yolov5_outputs[0].buf;unsigned short *temp1 = (ushort*)yolov5_outputs[1].buf;unsigned short *temp2 = (ushort*)yolov5_outputs[2].buf;for(int i=0; i < output_attrs[0].n_elems;i++){data0[i] = half_to_float(temp0[i]);}for(int i=0; i < output_attrs[1].n_elems;i++){data1[i] = half_to_float(temp1[i]);}for(int i=0; i < output_attrs[2].n_elems;i++){data2[i] = half_to_float(temp2[i]);}......

参考文献:

https://github.com/PrincetonVision/marvin/blob/master/tools/tensorIO_matlab/half2float.cpp

这篇关于fp16半精度浮点数转成float类型------C/C++的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1122156

相关文章

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Python如何查看数据的类型

《Python如何查看数据的类型》:本文主要介绍Python如何查看数据的类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python查看数据的类型1. 使用 type()2. 使用 isinstance()3. 检查对象的 __class__ 属性4.