IOS/iPad/iPhone的最高速度
我使用OpenCV
为iOS
完成了计算密集型应用程序。当然这很慢。但它比我的PC原型慢200倍。所以我正在优化它。从最初的15秒开始,我能够获得0.4秒的速度。我想知道我是否找到了所有的东西以及其他人可能想要分享的内容。我所做的:IOS/iPad/iPhone的最高速度
替换成 “
double
” 数据类型里面的OpenCV为 “float
”。 Double是64bit和32bit的CPU不能轻易处理它们,所以float给了我一些速度。 OpenCV经常使用double。在编译器选项中增加了“
-mpfu=neon
”。副作用是仿真器编译器无法工作的新问题,只能在本机硬件上测试任何东西。用90个值查找表替换
sin()
和cos()
实现。加速是巨大的!这与PC不同,这种优化不会加速。代码以度为单位工作,此值已转换为弧度为sin()
和cos()
。此代码也被删除。但查找表完成了这项工作。启用
"thumb optimizations"
。有些博客文章推荐完全相反,但这是因为拇指通常会使armv6
上的速度变慢。armv7
没有任何问题,使事情变得更快,更小。为了确保拇指优化和
-mfpu=neon
工作在最佳状态,并且不引入崩溃,我完全移除了armv6目标。我所有的代码都被编译为armv7
,这也被列为应用商店中的要求。这意味着最低iPhone
将是3GS
。我认为放弃旧的是可以的。无论如何,老一代的CPU速度较慢,如果安装在旧设备上,CPU密集型应用程序会提供不良的用户体验。当然我用
-O3 flag
我来自OpenCV的删除
"dead code"
。通常在优化OpenCV时,我会看到我的项目显然不需要的代码。例如,经常有额外的"if()"
来检查像素大小为8位或32位,我知道我只需要8位。这会删除一些代码,为优化器提供更好的机会去除更多内容或用常量替换。此外,代码更适合缓存。
其他技巧和想法?对于我来说,启用拇指和替换三角函数是助推器制造商,让我感到惊讶。也许你知道要做更多的事情,这会让应用程序飞行?
如果您正在进行大量的浮点计算,那么使用Apple的Accelerate框架将大大受益。它旨在使用浮点硬件并行计算矢量。
我也将解决你点一个接一个:
1)这是不是因为CPU的,这是因为随着ARMv7的时代只有32位浮点运算将在浮来计算的点处理器硬件(因为苹果取代了硬件)。而是用软件计算64位的。作为交换,32位操作速度更快。
2)NEON是设置
3)是,这是一个公知的方法中的新的浮点处理器指令的名称。另一种方法是使用我上面提到的Apple框架。它提供了可以并行计算4个值的正弦和余弦函数。该算法在组装和NEON中进行了精细调整,以便在使用最少电池时提供最佳性能。
4)拇指的新armv7实现没有armv6的缺点。禁用建议仅适用于v6。 5)是的,考虑到现在有80%的用户在iOS 5.0或更高版本(armv6设备在4.2.1结束支持),这在大多数情况下是完全可以接受的。
6)当您在发布模式下构建时,会自动发生这种情况。
7)是的,这不会有像上述方法一样大的影响。
我的建议是检查加速。这样,您可以确保充分利用浮点处理器的全部功能。
我对以前的帖子提供了一些反馈。这解释了我在第7点中试图提供的关于死代码的一些想法。这是为了稍微宽泛的想法。我需要格式化,所以不能使用评论表单。这样的代码是在OpenCV中:
for(kk = 0; kk < (int)(descriptors->elem_size/sizeof(vec[0])); kk++) {
vec[kk] = 0;
}
我想看看它是如何看待程序集。为了确保我可以用汇编找到它,我把它包这样的:
__asm__("#start");
for(kk = 0; kk < (int)(descriptors->elem_size/sizeof(vec[0])); kk++) {
vec[kk] = 0;
}
__asm__("#stop");
现在我按“产品 - >生成输出 - >大会文件”,我得到的是:
@ InlineAsm Start
#start
@ InlineAsm End
Ltmp1915:
ldr r0, [sp, #84]
movs r1, #0
ldr r0, [r0, #16]
ldr r0, [r0, #28]
cmp r0, #4
mov r0, r4
blo LBB14_71
LBB14_70:
Ltmp1916:
ldr r3, [sp, #84]
movs r2, #0
Ltmp1917:
str r2, [r0], #4
adds r1, #1
Ltmp1918:
Ltmp1919:
ldr r2, [r3, #16]
ldr r2, [r2, #28]
lsrs r2, r2, #2
cmp r2, r1
bgt LBB14_70
LBB14_71:
Ltmp1920:
add.w r0, r4, #8
@ InlineAsm Start
#stop
@ InlineAsm End
很多代码。我的printf-D输出的(int)(descriptors->elem_size/sizeof(vec[0]))
价值,它一直是64.所以我硬编码它是64,并通过汇编再次通过:
@ InlineAsm Start
#start
@ InlineAsm End
Ltmp1915:
vldr.32 s16, LCPI14_7
mov r0, r4
movs r1, #0
mov.w r2, #256
blx _memset
@ InlineAsm Start
#stop
@ InlineAsm End
正如你可能现在看到的优化上心和代码变得更短。它能够对此进行矢量化。要点是编译器总是不知道什么输入是常量,如果这是像摄像头大小或像素深度,但实际上在我的情况下,它们通常是恒定的,我所关心的只是速度。
我也试图加快的建议与替代三行:
__asm__("#start");
vDSP_vclr(vec,1,64);
__asm__("#stop");
大会现在看起来:
@ InlineAsm Start
#start
@ InlineAsm End
Ltmp1917:
str r1, [r7, #-140]
Ltmp1459:
Ltmp1918:
movs r1, #1
movs r2, #64
blx _vDSP_vclr
Ltmp1460:
Ltmp1919:
add.w r0, r4, #8
@ InlineAsm Start
#stop
@ InlineAsm End
不能确定这是否是比bzero更快虽然。在我的情况下,这部分没有太多时间,两个变体似乎以相同的速度工作。
我学到的另一件事是使用GPU。更多关于它的信息http://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework
这个加速度对我来说是新的。由于需要大会级别的思考,因此使用它仍然有点困难。但仍然有可能,也许会试一试。我稍后再接受它,因为我想看看我们是否能在这里获得更多有用的提示。 –
在WWDC 2012视频中有一个会议完全处理Accelerate框架。你应该看看它^^ – borrrden
http://adcdownload.apple.com//wwdc_2012/wwdc_2012_session_pdfs/session_708__the_accelerate_framework.pdf 和 https://developer.apple.com/videos/wwdc/2012/#708似乎作为它的链接 –