我正在使用本机代码在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
...
我用Google搜索了__addsf3,显然这是一个软件浮点操作。呸。我对ARMv6架构核心进行了更多的研究,除非我遗漏了什么,否则它没有硬件浮点支持。那么我能在这里做些什么来加快速度呢?固定点?我知道通常用整数完成,但我不确定如何转换我的代码来做到这一点。是否有我可以设置的编译器标志,所以它会这样做?欢迎其他建议。
答案 0 :(得分:8)
当然你只能用整数运算做任何事情(毕竟你的程序正是你现在正在做的事情)但是如果它可以更快地完成或者不是真的取决于你想要做什么。
浮点数是一种通用的解决方案,你可以在大多数情况下应用它而忘记它,但是你的问题确实需要从极小到极大的数字以及52位尾数的数字很少见准确性。假设您的计算是关于具有双精度浮点数的图形,您可以从远小于亚原子尺度到远远超过宇宙尺寸...是否真的需要该范围?提供的准确性当然取决于FP的规模,但你真正需要的准确度是多少?
您的“内循环”中使用的数字是多少?不知道如果计算可以更快或更快地进行,则很难说。几乎可以肯定它可以更快(FP是一种通用的盲解决方案)但你可能希望获得的收益程度变化很大。我不知道具体的实现,但我希望它具有合理的效率(对于通用情况)。
您应该瞄准更高的逻辑优化级别。
对于基于DCT或小波变换的图像(de)压缩,我认为确实不需要浮点运算:你可以只考虑你的数字的精确尺度并使用整数运算。此外,由于能够产生近似结果,你可能还有一个额外的自由度。
答案 1 :(得分:2)
首先看到6502的优秀答案......
大多数处理器没有fpus,因为它们不需要。当他们出于某种原因,他们试图符合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等后自己添加一个内核.ARM11是ARMv6,可以选择fpu。
另外,只是因为你可以自己跟踪小数点,如果有一个硬fpu,它可能比在固定点自己做更快。同样,有可能并且很容易不知道如何使用fpu并获得不良结果,只是让它们更快。很容易编写错误的浮点代码。无论您使用固定还是浮动,您都需要跟踪数字的范围,并从该控件中移动点以保持整数数学在尾数内的核心。这意味着有效地使用浮点数你应该考虑整数数学的作用。一个非常常见的错误就是认为乘法会增加你的精确度,而实际上是加法和减法会让你受到最大的伤害。