C++ 为什么没有2字节的浮点,并且实现已经存在?

C++ 为什么没有2字节的浮点,并且实现已经存在?,c++,floating-point,16-bit,half-precision-float,C++,Floating Point,16 Bit,Half Precision Float,假设我的内存非常紧张,需要更小的范围(类似于shortvsint)。着色器语言已经支持精度为一半的浮点类型的half(不只是来回转换,使值介于-1和1之间,也就是说,返回如下浮点:shortominin/maxRangeOfShort)。2字节浮点是否已有实现 我还想知道为什么没有2字节浮点的任何(历史的)原因。Re:implementation:显然有人为C编写了一半的代码,这在C++中(当然)是可行的: Re:Why isfloat四个字节:可能是因为在这四个字节下面,.有一个 < P>这是

假设我的内存非常紧张,需要更小的范围(类似于
short
vs
int
)。着色器语言已经支持精度为一半的浮点类型的
half
(不只是来回转换,使值介于-1和1之间,也就是说,返回如下浮点:
shortominin/maxRangeOfShort
)。2字节浮点是否已有实现


我还想知道为什么没有2字节浮点的任何(历史的)原因。

Re:implementation:显然有人为C编写了一半的代码,这在C++中(当然)是可行的:

Re:Why is
float
四个字节:可能是因为在这四个字节下面,.

有一个


< P>这是一个新的格式,已经在2002发布的GPU中被标准化了2008。

< P>如果你内存不足,你是否考虑放弃浮点概念?浮点数仅用于保存小数点所在的位置,就占用了大量位。如果你知道小数点在哪里,你可以解决这个问题,比如说你想保存一个美元值,你可以用美分保存它:

uint16_t cash = 50000;
std::cout << "Cash: $" << (cash / 100) << "." << ((cash % 100) < 10 ? "0" : "") << (cash % 100) << std::endl;
uint16\u t现金=50000;

std::cout要比Kiralein更进一步地转换为整数,我们可以定义一个范围,并允许short的整数值表示该范围内的等分,如果跨越零,则具有一定的对称性:

short mappedval = (short)(val/range);
这些整数版本与使用半精度浮点之间的差异:

  • 整数在整个范围内的间隔是相等的,而浮点数在零附近更密集
  • 使用整数将在CPU中使用整数数学,而不是浮点。这通常更快,因为整数运算更简单。话虽如此,将值映射到非对称范围将需要额外的加法等来检索最后的值
  • 绝对精度损失更容易预测;您知道每个值中的误差,因此可以根据给定的范围提前计算总损失。相反,使用浮点时相对误差更容易预测
  • 可能有一小部分操作可供选择,您可以使用成对的值,特别是按位操作,将两个短路填充到一个int中。这可以将所需的循环数减半(如果短操作涉及转换为int,则可以选择更多),并保持32位宽度。这只是一个稀释版本的位切片,其中32位并行操作,用于加密

  • 在不同的实现中可能有多种类型。相当于stdint.h的浮点值似乎是个好主意。按大小调用(别名?)类型。(
    float16_t
    ?)现在只有4字节的浮点值,但它可能不会变小。随着时间的推移,像“一半”和“长”这样的术语大多变得毫无意义。有了128或256位的计算机,它们可能意味着什么

    我正在处理图像(1+1+1字节/像素),我想表达每个像素相对于平均值的值。所以,请用浮点或定点,但不要用原始数据的4倍大。一个16位的浮点数听起来差不多正确

    < GCC 7.3不知道“半”,可能在C++上下文中。

    TL;DR:16位浮点确实存在,有各种软件和硬件实现 目前有两种常见的标准16位浮点格式:IEEE-754 binary16和Google的bfloat16。因为它们是标准化的,显然,如果任何了解规范的人都可以编写一个实现。一些例子:

    或者,如果您不想使用它们,也可以设计一种不同的16位浮点格式并实现它


    通常不使用2字节浮点,因为即使浮点的精度也不足以进行正常操作,并且默认情况下应始终使用
    double
    ,除非您受到带宽或缓存大小的限制。在C和C类语言中使用不带后缀的浮点文本时,浮点文本也是双精度的。看

    不过。它们主要用于存储目的,比如在图形中,当96位/像素(32位/通道*3通道)被浪费得太多时,它们将被转换为正常的32位浮点运算(在某些特殊硬件上除外)。OpenGL中存在各种各样的功能。许多HDR格式对每个通道使用16位浮点,Direct3D 9.0以及一些GPU(如Radeon R300和R420)具有24位浮点格式。24位浮点也由like支持,其中32位浮点支持成本太高。8位或更窄的浮点类型用处不大,但由于其简单性,它们通常在计算机科学课程中教授。此外,小浮点也用于小浮点指令

    官方增加了一种16位浮点格式,即二进制16,具有5位指数和11位尾数

    有些编译器支持IEEE-754二进制16,但主要用于转换或矢量化运算,而不用于计算(因为它们不够精确)。例如,ARM的工具链有两个变体:IEEE和alternative,这取决于您是否需要更多的范围表示或NaN/inf表示。并且还支持
    \uuu fp16
    以及标准化名称
    \ufloat16
    。看

    最近,由于人工智能的兴起,另一种称为()的格式变得很常见,它是IEEE-754二进制文件32前16位的简单截断

    减少尾数背后的动机来自谷歌的实验,该实验表明,减少尾数是很好的,只要它仍然可以表示接近零的微小值,作为训练期间微小差异总和的一部分。较小的尾数带来了许多其他优势,如降低倍增功率和物理硅面积

    • 弗洛亚
      // needs to be compiled with -mf16c enabled
      #include <immintrin.h>
      #include <cstdint>
      
      struct float16
      {
      private:
        uint16_t _value;
      public:
      
        inline float16() : _value(0) {}
        inline float16(const float16&) = default;
        inline float16(float16&&) = default;
        inline float16(const float f) : _value(_cvtss_sh(f, _MM_FROUND_CUR_DIRECTION)) {}
      
        inline float16& operator = (const float16&) = default;
        inline float16& operator = (float16&&) = default;
        inline float16& operator = (const float f) { _value = _cvtss_sh(f, _MM_FROUND_CUR_DIRECTION); return *this; }
      
        inline operator float () const 
          { return _cvtsh_ss(_value); }
      
        inline friend std::istream& operator >> (std::istream& input, float16& h) 
        { 
          float f = 0;
          input >> f;
          h._value = _cvtss_sh(f, _MM_FROUND_CUR_DIRECTION);
          return input;
        }
      };