float16与float32转换
// based on https://gist.github.com/martin-kallman/5049614
// float32
// Martin Kallman
//
// Fast half-precision to single-precision floating point conversion
// - Supports signed zero and denormals-as-zero (DAZ)
// - Does not support infinities or NaN
// - Few, partially pipelinable, non-branching instructions,
// - Core opreations ~6 clock cycles on modern x86-64
void float32(float *__restrict out, const uint16_t in) {
uint32_t t1;
uint32_t t2;
uint32_t t3;
t1 = in & 0x7fffu; // Non-sign bits
t2 = in & 0x8000u; // Sign bit
t3 = in & 0x7c00u; // Exponent
t1 <<= 13u; // Align mantissa on MSB
t2 <<= 16u; // Shift sign bit into position
t1 += 0x38000000; // Adjust bias
t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero
t1 |= t2; // Re-insert sign bit
*((uint32_t *) out) = t1;
};
// float16
// Martin Kallman
//
// Fast single-precision to half-precision floating point conversion
// - Supports signed zero, denormals-as-zero (DAZ), flush-to-zero (FTZ),
// clamp-to-max
// - Does not support infinities or NaN
// - Few, partially pipelinable, non-branching instructions,
// - Core opreations ~10 clock cycles on modern x86-64
void float16(uint16_t *__restrict out, const float in) {
uint32_t inu = *((uint32_t * ) & in);
uint32_t t1;
uint32_t t2;
uint32_t t3;
t1 = inu & 0x7fffffffu; // Non-sign bits
t2 = inu & 0x80000000u; // Sign bit
t3 = inu & 0x7f800000u; // Exponent
t1 >>= 13u; // Align mantissa on MSB
t2 >>= 16u; // Shift sign bit into position
t1 -= 0x1c000; // Adjust bias
t1 = (t3 < 0x38800000u) ? 0 : t1; // Flush-to-zero
t1 = (t3 > 0x8e000000u) ? 0x7bff : t1; // Clamp-to-max
t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero
t1 |= t2; // Re-insert sign bit
*((uint16_t *) out) = t1;
};
#define ABS(A) ((A) >= 0 ? (A) : -(A))
int main() {
float original = -42.42f;
uint16_t small = 0;
float16(&small, original);
float quantized = 0.0f;
float32(&quantized, small);
float diff = ABS(original - quantized);
printf("orig %f quantized %f absdiff %f\n", original, quantized, diff);
assert(diff < 0.1f);
}
引用
float16与float32转换的更多相关文章
- OpenCL中的half与float的转换
在kernel中使用half类型可以在牺牲一定精度的代价下来提升运算速度. 在kernel中, 可以比较方便的对half数据进行计算, 但在host上的, 对half的使用就没那么方便了. 查看cl_ ...
- [TF] Architecture - Computational Graphs
阅读笔记: 仅希望对底层有一定必要的感性认识,包括一些基本核心概念. Here只关注Graph相关,因为对编程有益. TF – Kernels模块部分参见:https://mp.weixin.qq.c ...
- tenaorflow函数(1)
TensorFlow 将图形定义转换成分布式执行的操作, 以充分利用可用的计算资源(如 CPU 或 GPU.一般你不需要显式指定使用 CPU 还是 GPU, TensorFlow 能自动检测.如果检测 ...
- Tensorflow的基本概念与常用函数
Tensorflow一些常用基本概念与函数(一) 1.tensorflow的基本运作 为了快速的熟悉TensorFlow编程,下面从一段简单的代码开始: import tensorflow as tf ...
- tensorflow和python操作中的笔记
前一段时间做了一些项目,把一些笔记放在了txt中,现分享出来,自己也能够时长预习. 1) 读取文件时,将固定的文件地址,采用数组或者字符串的形式,提前表示出来,后期使用时候采用拼接操作 2) # 得到 ...
- Tensorflow一些常用基本概念与函数(二)
1.tensorflow的基本运作 为了快速的熟悉TensorFlow编程,下面从一段简单的代码开始: import tensorflow as tf #定义‘符号’变量,也称为占位符 a = tf. ...
- Numpy的ndarry:一种多维数组对象
Numpy的ndarry:一种多维数组对象 Numpy最重要的一个特点就是其N维数组对象(即ndarry),该对象是一个快速而灵活的大数据集容器.你可以利用这种数组对整块数据执行一些数学运算,其语法跟 ...
- Numpy的ndarry
Numpy的ndarry:一种多维数组对象 Numpy最重要的一个特点就是其N维数组对象(即ndarry),该对象是一个快速而灵活的大数据集容器.你可以利用这种数组对整块数据执行一些数学运算,其语法跟 ...
- 利用Python进行数据分析_Numpy_基础_2
Numpy数据类型包括: int8.uint8.int16.uint16.int32.uint32.int64.uint64.float16.float32.float64.float128.co ...
- 实操 | 内存占用减少高达90%,还不用升级硬件?没错,这篇文章教你妙用Pandas轻松处理大规模数据
注:Pandas(Python Data Analysis Library) 是基于 NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.此外,Pandas 纳入了大量库和一些标准的数据模型 ...
随机推荐
- CMU 15-445 Project 0 实现字典树
原文链接:https://juejin.cn/post/7139572163371073543 项目准备 代码.手册 本文对应 2022 年的课程,Project 0 已经更新为实现字典树了.C++1 ...
- LibTorch | 使用神经网络求解一维稳态对流扩散方程
0. 写在前面 本文将使用基于LibTorch(PyTorch C++接口)的神经网络求解器,对一维稳态对流扩散方程进行求解.研究问题参考自教科书\(^{[1]}\)示例 8.3. 目录 0. 写在前 ...
- IDEA远程部署项目到Docker
前言 最近在写东西部署到服务器,结构是springboot工程配合docker部署. 但是每次部署都3个步骤: 本地构建jar 复制jar到远程服务器 用DockerFile构建镜像 部署次数一多,我 ...
- 安装MySQL8 工具集
下载地址:https://downloads.mysql.com/archives/utilities/ # wget https://downloads.mysql.com/archives/get ...
- Traefik 2.0 实现自动化 HTTPS
文章转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247484457&idx=1&sn=35112e98 ...
- 20_IO
IO框架 一. 流的概念 概念:内存与存储设备之间传输数据的通道 水借助管道传输:数据借助流传输 二. 流的分类 按方向[重点] 输入流:将<存储设备>中的内容读入到<内存>中 ...
- [题解] Atcoder Regular Contest ARC 148 A B C E 题解
点我看题 题目质量一言难尽(至少对我来说 所以我不写D的题解了 A - mod M 发现如果把M选成2,就可以把答案压到至多2.所以答案只能是1或2,只要判断答案能不能是1即可.如果答案是1,那么M必 ...
- Leetcode栈&队列
Leetcode栈&队列 232.用栈实现队列 题干: 思路: 栈是FILO,队列是FIFO,所以如果要用栈实现队列,目的就是要栈实现一个FIFO的特性. 具体实现方法可以理解为,准备两个栈, ...
- C++面向对象编程之类模板、函数模板等一些补充
1.static数据 和 static函数: 对于 非static函数 在内存中只有一份,当类对象调用时,其实会有该对象的this pointer传进去,那个函数就知道要对那个对象进行操作: stat ...
- GC plan_phase二叉树挂接的一个算法
楔子 在看GC垃圾回收plan_phase的时候,发现了一段特殊的代码,仔细研究下得知,获取当前数字bit位里面为1的个数. 通过这个bit位为1的个数(count),来确定挂接当前二叉树子节点的一个 ...