精华内容
下载资源
问答
  • 浮点数转换器1.0

    2013-11-23 22:22:54
    提供浮点数转换功能,单精度和精度都支持!
  • 本文都是下面文章开头6个问题的解答:张雅宸:浮点数的二进制表示以及几个例子​zhuanlan.zhihu.com问题1int 当两个数字都是float类型时,相乘的结果却是58...0.58 * 1000.58的精度表示是:0 01111111110 0010100...

    本文都是下面文章开头6个问题的解答:

    张雅宸:浮点数的二进制表示以及几个例子zhuanlan.zhihu.com

    问题1

    int 

    当两个数字都是float类型时,相乘的结果却是58。揭开谜底的过程涉及了浮点数的存储方式、浮点数的乘法规则和舍入。

    关于浮点数的存储方式可以参看浮点数的二进制表示以及几个例子,这里不再赘述。

    0.58 * 100

    0.58的双精度表示是:
    0 01111111110 0010100011110101110000101000111101011100001010001111

    100的双精度表示是(浮点数):
    0 10000000101 1001000000000000000000000000000000000000000000000000

    我们看一下0.58 * 100的计算过程:

    转变为标准的科学技术法:

    0.58是1.0010100011110101110000101000111101011100001010001111 * 2^-1
    100是1.1001000000000000000000000000000000000000000000000000 * 2^6

    将两个指数相加

    -1 + 6 = 5

    将两个尾数相乘

    1.0010100011110101110000101000111101011100001010001111 * 1.1001000000000000000000000000000000000000000000000000 =
    1.11001111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000

    规格化

    上面的结果是规格化小数,无需变化(小数点左边只有一个1)

    符号位相加mod2

    0 + 0 = 0

    舍入

    重点在这里,由于双精度的位数只有52位,所以我们要舍弃一部分尾数。IEEE默认使用向偶数舍入。所以上面的结果舍入后是:
    1.1100111111111111111111111111111111111111111111111111

    判断溢出

    判断阶码相加是否有溢出。 无

    所以最后的结果是
    0 10000000100 1100111111111111111111111111111111111111111111111111

    结果为:57.999999999999992894572642399

    由于C语言中float/double转向整数使用向零靠近,所以最后结果0.58 * 100 = 57。

    我们再看一下0.58f * 100.0f的计算过程:

    0.58f * 100.0f

    0.58的单精度表示是:
    0 01111110 00101000111101011100001

    100的单精度表示是(浮点数):
    0 10000101 10010000000000000000000

    具体过程:

    转变为标准的科学技术法

    0.58是1.00101000111101011100001 * 2^-1
    100是1.10010000000000000000000 * 2^6

    将两个指数相加

    -1 + 6 = 5

    将两个尾数相乘

    1.00101000111101011100001 * 1.10010000000000000000000 =
    1.1100111111111111111111110010000000000000000000

    规格化

    上面的结果是规格化小数,无需变化(小数点左边只有一个1)

    符号位相加mod2

    0 + 0 = 0

    舍入

    由于单精度的位数只有23位,所以我们要舍弃一部分尾数。上面的双精度舍入时是把最后的0全部舍入。但是这里的单精度舍入时,需要进一位。这也是造成两个乘法结果不相等的原因。 所以上面的结果舍入后是:
    1.11010000000000000000000

    判断溢出

    判断阶码相加是否有溢出。 无

    所以最后的结果是
    0 10000100 11010000000000000000000

    结果恰好为58.0。所以0.58f * 100.0f = 58

    最后说一下,向偶数舍入和我们学的四舍五入还不太一样。可以看一下浮点数的二进制表示以及几个例子的浮点数舍入部分。

    问题2

    printf

    这个问题涉及到的是浮点数的加法。

    我们看一下浮点数加法的过程:

    0.1的双精度表示是:
    0 01111111011 1001100110011001100110011001100110011001100110011010

    0.2的双精度表示是:
    0 01111111100 1001100110011001100110011001100110011001100110011010

    转变为标准的科学技术法

    首先和乘法一样,我们先将0.1和0.2转变为标准的科学计数法:
    0.1是1.1001100110011001100110011001100110011001100110011010 * 2^-4
    0.2是1.1001100110011001100110011001100110011001100110011010 * 2^-3

    阶码对齐

    想象一下十进制科学计数法相加:1.234567 × 10^5 + 1.017654 × 10^2,我们必须将后者变为0.001017654 × 10^5,使其阶码一样,才能使尾数相加。二进制浮点数同理。

    0.1的阶码是-4,0.2的阶码是-3。这里有一条规则是:小阶向大阶看齐。

    所以0.1的阶码变为了-3,相应的尾数变为0.11001100110011001100110011001100110011001100110011010

    尾数相加

    0.11001100110011001100110011001100110011001100110011010 +
    1.1001100110011001100110011001100110011001100110011010 =
    10.01100110011001100110011001100110011001100110011001110

    规格化

    1.001100110011001100110011001100110011001100110011001110 * 2^-2

    舍入

    双精度尾数只有52位,通过向偶数舍入,得出
    1.0011001100110011001100110011001100110011001100110100 * 2^-2

    所以,最后的结果是
    0 1111111101 0011001100110011001100110011001100110011001100110100

    十进制为0.300000000000000044408920985006

    所以0.1 + 0.2 = 0.300000000000000044408920985006 != 0.3

    问题3

    printf

    这个问题和上面的问题都不太一样,希望读者能够看一下。

    我们还是一步步来分析。
    3.14f的单精度表示是:
    0 10000000 10010001111010111000011

    1e10f的单精度表示是:
    0 10100000 00101010000001011111001

    转为科学计数法

    3.14f的表示是:1.10010001111010111000011 * 2^1
    1e10f的表示是:1.00101010000001011111001 * 2^33

    阶码对齐

    小阶向大阶看齐
    3.14f转变为0.0000000000000000000000000000000110010001111010111000011* 2^33(小数点右边连续31个0)

    尾数相加

    0.0000000000000000000000000000000110010001111010111000011 + 1.00101010000001011111001 =
    1.0010101000000101111100100000000110010001111010111000011

    规格化

    已经是规格化的数字,无需转变,即1.0010101000000101111100100000000110010001111010111000011 * 2^33

    舍入

    1.00101010000001011111001 * 2^33

    结果为
    0 10100000 00101010000001011111001

    这个结果还是1e10。我们发现3.14加和没加好像没有什么区别。因为在对阶和尾数相加时,3.14的实际有效数字都加在了最末端,而这些数字都在舍入时被舍掉了。

    这个问题当浮点数是双精度,即double类型时不复存在,因为double类型的尾数有52位,足以保证3.14的有效数字在舍入时不会被舍弃。

    问题4

    float 

    步骤和加法差不多,区别只是在尾数操作是减法。

    194268.02f的单精度表示是:
    0 10010000 01111011011011100000001

    194268f的单精度表示是:
    0 10010000 01111011011011100000000

    转为科学计数法

    194268.02f = 1.01111011011011100000001 * 2^17
    194268f = 1.01111011011011100000000 * 2^17

    对阶

    阶码一样。都是17

    尾数相减

    很容易看出来答案是0.00000000000000000000001

    规格化

    这个比较特殊,规格化后尾数都为0,即1.00000000000000000000000 * 2^-6

    舍入

    最后结果为:
    0 01111001 00000000000000000000000
    即为0.015625 < 0.02

    那么为什么printf 194268.02f结果是194268.015625呢?
    答案很简单,194268的二进制是101111011011011100,去除第一位的1,一共17位,而单精度float的尾数一共才23位,只有6位给0.02的二进制表示,即000001,所以:
    0 10010000 01111011011011100000001 = 194268.015625

    问题5

    gcc 

    gcc编译时加上-mfpmath选项:

    gcc -mfpmath=387 compare.c -o compare.o 
    float p3x = 80838.0f;
    float p2y = -2499.0f;
    double v321 = p3x * p2y;
    printf("%f",v321);          //-202014162,not -202014160

    为什么两次运行结果不一样?而且80838.0 * -2499在不考虑精度的情况下答案是-202014162,不是-202014160。

    我们首先看一下gcc -mfpmath选项的意思:

    Generate floating point arithmetics for selected unit unit.  The choices for unit are:
    
    387 Use the standard 387 floating point coprocessor present majority of chips and emulated otherwise.  Code
        compiled with this option will run almost everywhere.  The temporary results are computed in 80bit
        precision instead of precision specified by the type resulting in slightly different results compared to
        most of other chips.  See -ffloat-store for more detailed description.
    
        This is the default choice for i386 compiler.
    
    sse Use scalar floating point instructions present in the SSE instruction set.  This instruction set is
        supported by Pentium3 and newer chips, in the AMD line by Athlon-4, Athlon-xp and Athlon-mp chips.  The
        earlier version of SSE instruction set supports only single precision arithmetics, thus the double and 
        extended precision arithmetics is still done using 387.  Later version, present only in Pentium4 and the
        future AMD x86-64 chips supports double precision arithmetics too.
    
        For the i386 compiler, you need to use -march=cpu-type, -msse or -msse2 switches to enable SSE 
        extensions and make this option effective.  For the x86-64 compiler, these extensions are enabled by 
        default.   
    
        The resulting code should be considerably faster in the majority of cases and avoid the numerical
        instability problems of 387 code, but may break some existing code that expects temporaries to be 80bit.
    
        This is the default choice for the x86-64 compiler.

    387选项会将运算的临时结果保存成80位,然后再根据目标类型(float/double)截取成32位或者64位。FPU这么做会减少由于四舍五入带来的问题。(在此例中FPU类型算出了"正确"的结果)。

    但是sse选项会直接将结果截断成单精度的32位,再赋给目标类型64位。

    浮点数的运算过程前面已经说过了,这里不再一步步算了,只给出尾数相乘的规格化小数是
    1.10000001010011111011101001。但是由于目标类型时double,所以FPU不会进行截断,而是直接赋值给double,结果是-202014162。但是SSE模式下,会进行截断,将结尾的001截断来保证尾数只有23位,所以最后结果是-202014160。

    所以我们把目标类型改成float,就不会出现不同的结果。或者干脆将两个操作数都改为double类型。

    分析的最后,我们看下FPU和SSE模式产生的汇编代码:

    • FPU
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    $0x479de300, %eax
    movl    %eax, -16(%rbp)
    movl    $0xc51c3000, %eax
    movl    %eax, -12(%rbp)
    flds    -16(%rbp)
    fmuls   -12(%rbp)
    fstpl   -8(%rbp)
    movl    $.LC2, %eax
    movsd   -8(%rbp), %xmm0
    movq    %rax, %rdi
    movl    $1, %eax
    call    printf  
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
    • SSE
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    $0x479de300, %eax
    movl    %eax, -16(%rbp)
    movl    $0xc51c3000, %eax
    movl    %eax, -12(%rbp)
    movss   -16(%rbp), %xmm0
    mulss   -12(%rbp), %xmm0
    unpcklps        %xmm0, %xmm0
    cvtps2pd        %xmm0, %xmm0
    movsd   %xmm0, -8(%rbp)
    movl    $.LC2, %eax
    movsd   -8(%rbp), %xmm0
    movq    %rax, %rdi
    movl    $1, %eax
    call    printf
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

    很明显的看出一个是flds/fmuls/fstpl系列,一个是movss/mulss/movsd系列。

    问题6

    比较下面2个程序的运行时间:
    test.c

    float 

    test1.c

    float 

    第二个程序的运行时间是第一个的10倍左右,为什么会出现这样的差距?

    我们在j=50000000和循环结束时将j打印出来:
    第一个程序的结果:

    0.0000001751516833792265970259904861450195312500000000000000000000
    0.0000001788139343261718750000000000000000000000000000000000000000

    第二个程序的结果:

    0.0000000000000000000000000000000000000000000630584308946167681916
    0.0000000000000000000000000000000000000000000630584308946167681916

    为什么会出现这样的结果?(提示一下,0.1的二进制表示为1.10011001100110011001101 * 2^-4,可以再回看前面分析过的3.14f + 1e10f - 1e10f != 0.0f。留一段空白大家思考一下)。
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    ^-^
    因为0.1的指数是-4,在做浮点数加减法时,会将指数从小阶向大阶看齐。所以,程序运行到一定程度,会出现类似如下的形式:

    0.00000000...(很多0)..1yyy   * 2^-4   +
    1.xxxxxxxxx                  * 2^-4

    由于精度和舍入的原因,最后的结果可能是1.xxxx...1yy * 2^-4,被加数可能会被舍弃一部分有效数字,但是由于指数还是-4,所以结果还是规格化小数。-0.1f同理,结果还是规格化小数。

    但是第二个程序,由于没有规格化小数0.1约束指数,所以最后的结果会越来越小,最后退化成非规格化小数:0 00000000 xxxxxxxxxxxx。

    计算机在计算非规格化小数时,会比计算规格化小数慢10-100倍左右。 为什么会这样?笔者才疏学浅,在硬件和电路方面的知识不成体系,始终不能理解。(硬件和电路的知识一直是我的痛点,经常阻止我更加深入的研究问题。)

    关于如何避免非规格化小数,可以查看下面两篇文章:

    • Denormal number
    • x87 and SSE Floating Point Assists in IA-32: Flush-To-Zero (FTZ) and Denormals-Are-Zero (DAZ)

    在笔者的计算机上,使用

    #include <xmmintrin.h>
    _mm_setcsr( _mm_getcsr() | 0x8040 );

    可以使得第二个程序的性能变得和第一个程序一样。但是精度就差了很多,加上上面两句后,程序的运行结果是0.0,而允许非规格化小数运算的结果是0.0000000000000000000000000000000000000000000630584308946167681916。

    简单叙述一下为什么上面的两行程序会避免非规格化小数的计算:
    在SSE和SSE2指令集中,有两种模式FTZ( Flush-to-Zero)和DAZ(Denormals-Are-Zero)帮助我们提高非规格化小数的运算速度。其中FTZ的意思是当运算结果产生非规格化小数时,FTZ模式将运算结果设置为0。而DAZ的意思是当操作数有非规格化小数时,先将它设置为0再与其他操作数进行运算。也可以说FTZ影响输出结果而DAZ影响输入结果。

    defdd07d624c90d72ba0ee7cedf58d4d.png

    要想使FTZ模式生效,需要满足两个条件:

    • MXCSR寄存器(FTZ位)的第15位为1。
    • 下溢异常位,即第15位为1(underflow exception)。

    要想使DAZ模式生效,需要满足两个条件:

    • MXCSR寄存器(DAZ位)的第6位为1。
    • 处理器必须支持DAZ模式。

    上面代码首先用_mm_getcsr()获取MXCSR寄存器的值,我们将结果打印出来看看:

    printf("%d",_mm_getcsr());    //8064  二进制1111110000000

    第11位为0。但是FTZ位和DAZ位均为0,所以我们或上0x8040(1000000001000000)即可使FTZ模式与DAZ模式生效。

    (完)

    参考资料:

    • Multiplying Floating Point Numbers
    • Floating-point arithmetic
    • PHP浮点数的一个常见问题的解答
    • 一个浮点数跨平台产生的问题
    • x87 and SSE Floating Point Assists in IA-32: Flush-To-Zero (FTZ) and Denormals-Are-Zero (DAZ)
    • Denormal number
    展开全文
  • 对于Cockos Reaper中可用的“回放重采样模式”选项,特别是Medium(64pt ...我想这是因为大多数CPU现在都是64位引擎来工作,但这个设置与我们的外置ADDA转换器(或是声卡)有什么关系吗,因为外置ADDA和声卡都是最高...

    beeee3ce8624471555733f3d033c879c.png

    对于Cockos Reaper中可用的“回放重采样模式”选项,特别是Medium(64pt Sinc)、Good(192pt Sinc)和Better(384pt Sinc) 模式之间的差异,我表示不理解。此外,默认轨道混合位深度为'64-bit 浮点数'。我想这是因为大多数CPU现在都是64位引擎来工作,但这个设置与我们的外置ADDA转换器(或是声卡)有什么关系吗,因为外置ADDA和声卡都是最高以24位工作的。

    ——Michael

    对此,SOS(SOUND ON SOUND)技术编辑Hugh Robjohns回复:“回放重采样模式”选项与导入具有与当前项目的采样率不同的采样率的音频文件时的自动采样率转换有关,例如导入24位时,将96kHz源文件转换成44.1kHz项目。当对数字信号应用采样率转换时,必须从现有采样重建原始音频波形,以便可以计算所需要的每个(新)采样点的正确采样值(译者注:如从48000hz转换为44100hz,需要将48000hz重采样为尽可能接近连续的模拟音频的高采样数字音频文件,再从其中更为精确地重新采样出44100hz的新采样音频,以及使用抗混叠滤波器)

    'Sinc'指的是一种数学函数,其本质上涉及从各个样本重建原始音频波形。简单来说,它描述了每个采样点如何对每个采样点之前和之后的音频波形的空缺做出补充。对于这篇回复来说,我很难为你讲解采样理论的数学内容。但如果你想了解更多,我推荐Dan Lavry的采样理论白皮书(http://lavryengineering.com/pdfs/lavry-sampling-theory.pdf)。

    需要注意的重要一点是,Sinc函数看起来像是一个具有衰减波纹的脉冲,在理论上,它在每个采样点之前和之后都会永久延伸,但在每个采样点始终具有零振幅。因此,这些波纹会影响整个重建波形的幅度,并且在执行采样率转换时需要将其考虑在内。

    在大多数情况下,计算每个采样点的Sinc补偿是不实际的,因此Reaper的采样率转换过程可以针对不同的准确度和速度进行优化。对当前样本两侧的64个采样点执行计算可以得到很好的结果,但是将其扩展到任意一侧的192、384甚至是768个采样点更准确(它可以实现更低的噪声和失真)。但是,它需要更长的时间,因为它涉及更多的计算。

    (译者注:REAPER支持在工程项目中使用不同于工程采样率的音频文件进行回放,于是提供了“回放重采样”的选项设置。译者以为,无论是回放还是渲染,都应该使用更高的采样率进行重采样。如果在尝试后发现回放重采样太高,系统难以承受,可以考虑将其直接使用极高的采样率进行渲染重采样,以保证回放声音的质量尽可能不受损失。如REAPER中提供的最高重采样模式:768khz采样率)

    关于内部位深度,我推荐继续使用内部的'64位浮点数'混音引擎,这是为了最大化内部动态范围功能,以适应非常响亮或非常安静的信号而不损失它们。当很多信号组合在一起时,结果通常比任何单个信号都大得多,因此DAW引擎需要额外的余量来应对。以类似的方式,改变数字信号的水平通常导致计算中的“剩余”。需要额外的位数来保存这些剩余部分,以避免在处理时丢失它们从而降低信号质量。

    这种额外的动态范围要求在不同系统中以不同方式实现,并且取决于所应用的处理类型。例如,您经常会看到对双精度或三精度的引用(其中计算以48位或72位完成),大多数早期DAW使用32位浮点数(如Adobe Audition),这给出了一个内部的概念:1500dB的动态范围。现代计算机硬件设计用于64位操作系统环境,许多DAW软件也遵循实用的方便。它只是意味着更大的内部动态范围能力,这使得内部削波几乎不可能,并且处理失真的本底噪声很小。

    然而,音频信号总是必须在人类世界中进行试听,而我们的耳朵和重放设备不能容纳超过约120dB的动态范围。24位系统(理论上)可以容纳大约140dB的动态范围,因此业界已经对旗舰级的音频接口(声卡、ADDA)进行了24位标准化,这样的动态范围已经绰绰有余了。不过这意味着我们必须“管理”在DAW内部创建的(可能)无比巨大的动态范围信号,以确保它们适合在24位动态范围内进行实际试听。这就是为什么当内部电平太高时,DAW的输出电平表会显示削波(颜色上的变化); 它不是计算机中64位浮点信号产生了削波,而是提醒你在输出至外部24位转换器时真的有可能会产生削波。

    文章作者:Hugh Robjohns

    转载自SOUNDONSOUND,侵删。

    展开全文
  • 软件介绍: 一款绿色的进制转换工具,能够在浮点数及整形数据间进行互转,能够将浮点数转换为16进制,支持十六进制单精度、精度等格式转浮点,能将32位整数十进制转换为十六进制。
  • 有了它,就能在几乎不损失模型精度的情况下,将模型压缩至一半大小,还能改善CPU和硬件加速延迟。这一套工具囊括混合量化,全整数量化和修剪。如何量化模型,尽可任君挑选。压缩大小,不减精度精度是64位,单...

    鱼羊 发自 凹非寺

    量子位 报道 | 公众号 QbitAI

    近日,TensorFlow模型优化工具包又添一员大将,训练后的半精度浮点量化(float16 quantization)工具。

    062ace44ceb27e5c2fc3ed4c75bb9a17.gif

    有了它,就能在几乎不损失模型精度的情况下,将模型压缩至一半大小,还能改善CPU和硬件加速器延迟。

    这一套工具囊括混合量化,全整数量化和修剪。

    fd5627c883d3a638cb30122bb8b401af.png

    如何量化模型,尽可任君挑选。

    压缩大小,不减精度

    双精度是64位,单精度是32位,所谓的半精度浮点数就是使用2个字节(16位)来存储。

    比起8位或16位整数,半精度浮点数具有动态范围高的优点;而与单精度浮点数相比,它能节省一半的储存空间和带宽。

    3b4d6bf04d7b8d7dfd166b6c4a6453eb.png

    比起双精度和单精度浮点数,半精度浮点显然没有那么适合计算。那么问题来了,为什么要主动降低精度呢?

    因为实际上,很多应用场景对于精度的要求并没有那么高。在分布式深度学习中,模型可能会有成千上万个参数,体积一个赛一个的大,如果能把所有常量值都用16位浮点数而不是32位浮点数来存储,那么模型大小就能压缩至一半,还是相当可观的。

    体积压缩了,精确度难道不会损失吗?

    降低浮点数精度,当然会带来精确度的损失,但是不必担心,这样的损失小到可以忽略不计。

    在ILSVRC 2012图像分类任务上分别测试标准的MobileNet float32模型和float16模型变体,可以看到,无论是MobileNet v1还是MobileNet v2,无论是top1还是top5,fp16模型的精度损失都小于0.03%

    fcd6cf389b8366a00f5ad098c57ab069.png

    再试试对象检测任务,fp16变体比之标准模型,几乎没有精度损失。

    67812017f1dd95fbaef68edb9a01c2b1.png

    而无论是MobileNet v1还是MobileNet SSD,fp16变体的体积都比标准模型的大小降低了约一半。

    76ed0fb22dd76e3b641a655b827b969a.png

    小体积,高精度,有什么理由不试试半精度浮点量化工具呢?

    便捷使用

    想要把你训练过的32位模型转成16位,操作并不复杂。只需设置两行关键代码。

    在TensorFlow Lite converter上把32位模型的优化设置设为DEFAULT,然后把目标规范支持类型设置为FLOAT16:

    import tensorflow as tfconverter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)converter.optimizations = [tf.lite.Optimize.DEFAULT]converter.target_spec.supported_types = [tf.lite.constants.FLOAT16]Tflite_quanit_model = converter.convert()

    模型转换成功之后就可以直接运行了。

    默认情况下,模型是这样在CPU上运行的:把16位参数“上采样”为32位,并在标准32位浮点运算中执行操作。

    这样做的原因是目前很多硬件还不支持加速fp16计算。在未来,有更多硬件支持的情况下,这些半精度值就不再需要“上采样”,而是可以直接进行计算。

    在GPU上运行fp16模型更简单。

    TensorFlow Lite的GPU代理已经得到加强,能够直接获取并运行16位精度参数:

    //Prepare GPU delegate.const TfLiteGpuDelegateOptions options = { .metadata = NULL, .compile_options = { .precision_loss_allowed = 1, // FP16 .preferred_gl_object_type = TFLITE_GL_OBJECT_TYPE_FASTEST, .dynamic_batch_enabled = 0, // Not fully functional yet },};

    如果你感兴趣,TensorFlow官方还给出了教程demo,打开文末Colab链接,你就可以在线训练一个16位的MNIST模型啦。

    传送门

    官方指南:

    https://www.tensorflow.org/lite/performance/post_training_quantization

    Colab链接:

    https://colab.research.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/performance/post_training_float16_quant.ipynb

    — 完 —

    诚挚招聘

    量子位正在招募编辑/记者,工作地点在北京中关村。期待有才气、有热情的同学加入我们!相关细节,请在量子位公众号(QbitAI)对话界面,回复“招聘”两个字。

    量子位 QbitAI · 头条号签约作者

    վ'ᴗ' ի 追踪AI技术和产品新动态

    展开全文
  • 有了它,就能在几乎不损失模型精度的情况下,将模型压缩至一半大小,还能改善CPU和硬件加速延迟。这一套工具囊括混合量化,全整数量化和修剪。如何量化模型,尽可任君挑选。压缩大小,不减精度精度是64位,单...
    鱼羊 发自 凹非寺 
    量子位 报道 | 公众号 QbitAI

    近日,TensorFlow模型优化工具包又添一员大将,训练后的半精度浮点量化(float16 quantization)工具。

    96ce39fff4fa76851e3708b2779e7192.gif

    有了它,就能在几乎不损失模型精度的情况下,将模型压缩至一半大小,还能改善CPU和硬件加速器延迟。

    这一套工具囊括混合量化,全整数量化和修剪。

    4a4e2935a2aff5db8a66a0a848369071.png

    如何量化模型,尽可任君挑选。

    压缩大小,不减精度

    双精度是64位,单精度是32位,所谓的半精度浮点数就是使用2个字节(16位)来存储。

    比起8位或16位整数,半精度浮点数具有动态范围高的优点;而与单精度浮点数相比,它能节省一半的储存空间和带宽。

    b4e8f77ba57ee5ced1449391945dea91.png

    比起双精度和单精度浮点数,半精度浮点显然没有那么适合计算。那么问题来了,为什么要主动降低精度呢?

    因为实际上,很多应用场景对于精度的要求并没有那么高。在分布式深度学习中,模型可能会有成千上万个参数,体积一个赛一个的大,如果能把所有常量值都用16位浮点数而不是32位浮点数来存储,那么模型大小就能压缩至一半,还是相当可观的。

    体积压缩了,精确度难道不会损失吗?

    降低浮点数精度,当然会带来精确度的损失,但是不必担心,这样的损失小到可以忽略不计。

    在ILSVRC 2012图像分类任务上分别测试标准的MobileNet float32模型和float16模型变体,可以看到,无论是MobileNet v1还是MobileNet v2,无论是top1还是top5,fp16模型的精度损失都小于0.03%

    58bc909a84ea81cd18daca03f4c0c8d8.png

    再试试对象检测任务,fp16变体比之标准模型,几乎没有精度损失。

    dbb31fc90baa7fc57416ffbcf363fce2.png

    而无论是MobileNet v1还是MobileNet SSD,fp16变体的体积都比标准模型的大小降低了约一半。

    bac3bfa9cf756deea1f1842c3c3c3233.png

    小体积,高精度,有什么理由不试试半精度浮点量化工具呢?

    便捷使用

    想要把你训练过的32位模型转成16位,操作并不复杂。只需设置两行关键代码。

    在TensorFlow Lite converter上把32位模型的优化设置设为DEFAULT,然后把目标规范支持类型设置为FLOAT16:

    import tensorflow as tf
    converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
    converter.optimizations = [tf.lite.Optimize.DEFAULT]
    converter.target_spec.supported_types = [tf.lite.constants.FLOAT16]
    Tflite_quanit_model = converter.convert()

    模型转换成功之后就可以直接运行了。

    默认情况下,模型是这样在CPU上运行的:把16位参数“上采样”为32位,并在标准32位浮点运算中执行操作。

    这样做的原因是目前很多硬件还不支持加速fp16计算。在未来,有更多硬件支持的情况下,这些半精度值就不再需要“上采样”,而是可以直接进行计算。

    在GPU上运行fp16模型更简单。

    TensorFlow Lite的GPU代理已经得到加强,能够直接获取并运行16位精度参数:

    //Prepare GPU delegate.
    const TfLiteGpuDelegateOptions options = {
      .metadata = NULL,
      .compile_options = {
        .precision_loss_allowed = 1,  // FP16
        .preferred_gl_object_type = TFLITE_GL_OBJECT_TYPE_FASTEST,
        .dynamic_batch_enabled = 0,   // Not fully functional yet
      },
    };

    如果你感兴趣,TensorFlow官方还给出了教程demo,打开文末Colab链接,你就可以在线训练一个16位的MNIST模型啦。

    传送门

    官方指南:
    https://www.tensorflow.org/lite/performance/post_training_quantization

    Colab链接:
    https://colab.research.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/performance/post_training_float16_quant.ipynb

    加入社群 | 与优秀的人交流

    7c8df3c886753fc9fff2a50828f03233.png

    小程序 | 全类别AI学习教程

    f0d59af043edec6d96581f2001f1e333.png

    259177882b0d6ed2646c274a21ce6aa4.png

    量子位 QbitAI · 头条号签约作者

    վ'ᴗ' ի 追踪AI技术和产品新动态

    喜欢就点「好看」吧 !

    展开全文
  • “IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值...
  • IEEE二进制浮点数算术标准(IEEE 754)是1980年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷...
  • JSF转换器(converter),数字(number)

    千次阅读 2013-04-16 00:00:43
    数字是一个用来表示事物的普遍概念,像年龄,薪水,百分比,...下面我们来看一个JSF自带的标准的数字转换器的例子。 standardConverterNumbers.xhtml <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transiti
  • 应用下述STL指令:1、RND:RND指令(32位IEEE浮点数...使用该指令,可以将32位IEEE浮点数转换成为一个32位整数(整数),并将结果取整为最近的整数。2、TRUNC:TRUNC指令(32位IEEE浮点数转换成为32位整数)将累加1中...
  • IEEE二进制浮点数算术标准(IEEE 754)是1980年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷...
  • double:精度浮点数校验 date:日期校验 expression:表达式校验 fieldexpression:字段表达式校验 email:电子邮件校验 url:网址校验 visitor:Visitor校验 conversion:转换校验 stringlength:...
  • $inc 只能用于 整数 、 长整数 或 精度浮点数 , 修改其他类型 会失败报错,即使其他多种语言中能自动转换的类型 (如:null , 布尔 或 数字构成字符串),都是不行的。 报错字符串 如下: Modifier"$inc...
  • 大纲: 1浮点数的格式指定 2浮点数的运算(加法) 3浮点数加减法的实现(难于乘除法器的...主要分为单精度浮点数精度浮点数 在两个默认空壳格式规定下:转换规则如下 转换实例: 2.浮点数加...
  • 3.10 积分型A/D转换器与MCS51系列单片机接口的新方法 3.11 8031单片机与AD574A/D转换器的最简接口 3.12 8098单片机A/D转换接口及其程序设计 3.13 提高A/D转换器分辨率的实用方案 3.14 用CD4051提高8098单片机内...
  • Python学习笔记(二)

    2018-10-25 14:53:00
    在文本编辑中,需要设置把Tab自动转换为4个空格,确保不混用Tab和空格。 注:Python程序是大小写敏感的。 2.字符类型  整数、浮点数 字符串 字符串是以单引号'或引号"括起来的任意文本,比如'abc',"xyz...
  • 在文本编辑中,需要设置把Tab自动转换为4个空格,确保不混用Tab和空格。 3.1 数据类型和变量 1、整数 2、浮点数 3、字符串 (1)字符串是以单引号'或引号"括起来的任意文本; (2)如果'本身也是一个字符,那就...
  • 单片微机测控系统设计大全(推荐)

    热门讨论 2009-01-15 09:39:11
    8 微型打印机及其与单片机接口 第8章 D/A转换器及其与单片机接口 8. 1 D/A转换器的工作原理和性能指标 8. 2 8位DAC及其与单片机接口 8. 3 DAC的极性输出 8. 4 多路输出D/A转换电路 8. 5 8位以上D/A转换器及其...
  • 1 二进制浮点数转换为十进制数的方法和子程序 3. 2. 2 十进制浮点数转换为二进制数的方法和子程序 3. 3 二进制数的算术子程序 3. 3. 1 定点数与浮点数的表示方法 3. 3. 2 浮点数的四则运算规则 3. 3. 3 多字节...
  • 10.2.4 MCS—51与A/D转换器MCl4433(积分型)的接口 10.2.5 MCS—51与ICL7135(积分型)的接口 10.2,6 MCS—51与ICL7109(积分型)的接口 10.3 MCS—51与V/F转换器的接口 10.3.1 用V/F转换器实现A/D转换的方法 ...
  • 2.14 高精度A/D转换器应用中的误差调整 2.15 提高7135 A/D分辨率的应用技术 2.16 单片精密型V/f,f/V转换器 2.17 通用压控振荡器的单片机接口 2.18 频偏式传感器 2.19 智能压力变送...
  • 062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言翻译 072 火车车厢...
  • 200个经典C程序【源码】

    千次下载 热门讨论 2013-08-08 10:48:40
    062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言翻译 072 火车车厢...
  • 浮点数与整数的除法运算 70 字符 73 答案 74 编程练习 75 第五章 数组、修饰符与读取数字 76 数组 76 串 78 读取串 81 多维数组 84 读取数字 86 变量初始化 88 整型 90 浮点型 92 常量说明 93 十六...
  • 062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言翻译 072 火车车厢...
  • 062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言...
  • C语言学习实例220例

    2015-06-16 23:47:59
    062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言翻译 072 火车车厢重排 073 ...
  • C语言实例解析精粹

    2014-03-14 21:57:05
    062 浮点数转换为字符串 063 汉诺塔问题 064 哈夫曼编码 065 图的深度优先遍利 066 图的广度优先遍利 067 求解最优交通路径 068 八皇后问题 069 骑士巡游 070 用栈设置密码 071 魔王语言翻译 072 火车车厢...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 149
精华内容 59
热门标签
关键字:

双浮点数转换器