加速浮点运算(Android ARMv6)

4

我正在使用本地代码在Android上进行图像压缩。由于各种原因,我无法使用预编译库。

我使用android-ndk-profiler对我的代码进行了分析,并发现瓶颈是--令人惊讶的--浮点运算!以下是分析输出:

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 40.37      0.44     0.44                             __addsf3
 11.93      0.57     0.13     7200     0.02     0.03  EncodeBlock
  6.42      0.64     0.07   535001     0.00     0.00  BitsOut
  6.42      0.71     0.07                             __aeabi_fdiv
  6.42      0.78     0.07                             __gnu_mcount_nc
  5.50      0.84     0.06                             __aeabi_fmul
  5.50      0.90     0.06                             __floatdisf
  ...

我搜索了 __addsf3,显然它是一种软件浮点运算。可恶。我对ARMv6架构核心进行了更多的研究,除非我漏掉了什么,否则它没有硬件浮点支持。那么我该怎么做才能加速呢?定点运算?我知道这通常是用整数来实现的,但我不太确定如何转换我的代码。我是否可以设置编译器标志来实现?欢迎提出其他建议。

2个回答

8
当然,你可以仅使用整数算术来完成任何任务(毕竟这正是你的程序正在做的),但是否可以更快地完成取决于你要做什么。
浮点数是一种通用解决方案,你可以在大多数情况下应用它并将其忘记,但你的问题确实需要非常小到极为微小或非常大到宇宙大小,并且具有52位尾数精度的数字的情况相对较少。假设你的计算涉及双精度浮点数的图形,则可以从亚原子尺度远小于宇宙的大小,但你真正需要的范围是多少?当然,FP提供的准确度取决于规模,但你真正需要的准确度是多少?
你的“内循环”中的数字用于什么目的?如果不知道这一点,很难确定计算能否加速。几乎肯定可以更快地完成(因为FP是通用的盲目解决方案),但你希望获得的增益程度却变化很大。我不知道具体的实现方式,但我预计它会相当高效(针对通用情况)。
你应该以更高的逻辑级别进行优化。
对于基于DCT或小波变换的图像(去)压缩,我认为确实不需要浮点算术:你可以考虑数字的准确比例并使用整数算术。此外,也许你还有一个额外的自由度,因为能够产生近似结果。

2
首先看6502的出色答案...
大多数处理器没有浮点单元,因为它们不需要。当它们因某种原因需要时,它们会试图符合IEEE754标准,但这同样是不必要的,需要使用它的情况非常罕见。FPU只是一个带有一些围绕其周围的东西来跟踪浮点数的整数ALU,所有这些都可以由您自己完成。
如何做到呢?我们可以考虑小数和美元,我们可以考虑$110.50并添加$0.07得到$110.57,或者您可以直接用便士计算,11050 + 7 = 11057,然后在正确的位置上放一个点以供用户查看。这就是FPU正在做的事情,也是您需要做的事情。此链接可能会或可能不会对此提供一些见解http://www.divms.uiowa.edu/~jones/bcd/divide.html
不要笼统地将所有ARMv6处理器都归为一类,这不是ARM的分类方式。一些核心有FPU的选项,或者您可以在购买后从ARM添加一个FPU等等。例如,ARM11是带有FPU选项的ARMv6。
此外,即使您自己可以跟踪小数点,如果有硬件FPU,则可能比在定点中自己处理更快。同样,可能很容易不知道如何使用FPU并得到错误的结果,只是更快。编写错误的浮点代码非常容易。无论您使用固定点还是浮点,都需要跟踪数字的范围,并从中控制移动点的位置,以保持核心内的整数运算在尾数中。这意味着要有效地使用浮点,您应该考虑整数运算正在做什么。一个非常常见的错误是认为乘法会破坏精度,而实际上加减法可能会对您造成最大的伤害。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接