【问题标题】:gcc on raspberry half precision floating point (binary16, alternative, __fp16) uses library function覆盆子半精度浮点(binary16,替代,__fp16)上的 gcc 使用库函数
【发布时间】:2018-12-31 07:24:28
【问题描述】:

我在树莓派 3 上使用了一些基于机器学习的算法,其中包含大量存储系数,不需要完整的 float32 精度。

我尝试使用半精度浮点来存储这些数据,以减少程序内存(可能还有内存带宽)占用。

算法的其余部分保持不变。

在使用__fp16 时,将float32 与float16 版本进行比较,我得到了(显着:+ 33% 的测试程序运行时间)性能损失,尽管cpu 应该支持转换。

我查看了汇编器的输出,还创建了一个简单的函数,它只读取一个 __fp16 值并将它作为 float 返回,似乎一些库函数调用用于转换。 (与实际代码中调用的函数相同)

rapspberry 的 cpu 应该有半精度硬件支持,所以我希望看到一些指令加载数据并且看不到任何性能影响(或者由于内存带宽要求降低而看到改进)

我正在使用以下编译器标志:

-O3 -mfp16-format=alternative -mfpu=neon-fp16 -mtune=cortex-a53 -mfpu=neon

这里是一小段代码和小测试功能的汇编器输出:

const float test(const Coeff *i_data, int i ){
  return (float)(i_data[i]);
}

float 用于Coeff

    .align  2
    .global test
    .syntax unified
    .arm
    .fpu neon
    .type   test, %function
test:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    @ link register save eliminated.
    add r1, r0, r1, lsl #2  @ tmp118, i_data, i,
    vldr.32 s0, [r1]    @, *_5
    bx  lr  @

__fp16 用于Coeff (-mfp16-format=alternative):

    .align  2
    .global test
    .syntax unified
    .arm
    .fpu neon
    .type   test, %function
test:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    lsl r1, r1, #1  @ tmp118, i,
    push    {r4, lr}    @
    ldrh    r0, [r0, r1]    @ __fp16    @, *_5
    bl  __gnu_h2f_alternative   @
    vmov    s0, r0  @,
    pop {r4, pc}    @

__fp16 用于Coeff (-mfp16-format=ieee):

    .align  2
    .global test
    .syntax unified
    .arm
    .fpu neon
    .type   test, %function
test:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    lsl r1, r1, #1  @ tmp118, i,
    push    {r4, lr}    @
    ldrh    r0, [r0, r1]    @ __fp16    @, *_5
    bl  __gnu_h2f_ieee  @
    vmov    s0, r0  @,
    pop {r4, pc}    @

我错过了什么吗?

【问题讨论】:

  • Rasperry Pi 3 使用的 A53 处理器是否有任何权威规格说明它包含对 FP16 的硬件支持?通过快速搜索,我只能找到 FP16 支持是 ARMv8.2 处理器的可选功能。
  • 快速浏览ARM-specific gcc options 建议的标志与此处用于打开 FP16 的标志不同:-march=armv8.2-a+fp16
  • @njuffa 是的,它有一个 vfpv4 fpu

标签: gcc floating-point arm precision neon


【解决方案1】:

编译器标志-mfpu=neon 会覆盖之前的-mfpu=neon-fp16,因为-mfpu= 只能指定一次。

设置两次是错误的(在 Makefile 的不同位置添加)。

但由于 raspberry 3 具有始终支持 fp16 的 vfpv4,因此最佳规范是 -mfpu=neon-vfpv4

在这种情况下,编译器不会为转换生成任何库调用。

编辑:据此ghist -mfpu=neon-fp-armv8 -mneon-for-64bits 可用于树莓派 3。

【讨论】:

    【解决方案2】:

    在 ARM 的网站上:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0774d/chr1421838476257.html

    注意 __fp16 类型只是一种存储格式。出于算术和其他操作的目的,C 或 C++ 表达式中的 __fp16 值会自动提升为浮点数。

    【讨论】:

    • 是的,这很清楚,这就是我的意图:我认为这从我的问题中很清楚 - 我改写了一下。问题是,我可能错过了,为什么 gcc 确实使用库函数进行此转换
    猜你喜欢
    • 2019-11-10
    • 2022-01-23
    • 2020-02-03
    • 1970-01-01
    • 2011-09-03
    • 2011-10-14
    • 2011-11-17
    • 2013-04-16
    • 2011-08-26
    相关资源
    最近更新 更多