【发布时间】: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 是的,它有一个
vfpv4fpu
标签: gcc floating-point arm precision neon