一个项目的优化总结

近期在X86和ARM平台上优化一个实时人脸追踪程序,优化后PC(i5-6600K 3.50G)上可以到300fps, ARMv7a(华为Mate7)上可到25~30fps, 总结一下优化经验!

用SIMD实现核心计算函数

  • 短矢量内积(DOT), 绝对值(SAD)都可以完全展开,用SSE/NEON汇编加速。一般库函数版本都需要应对各种情况要面面俱到,对计算性能有不小影响,有的库函数为了保证计算精度,内部还会采用double进行累加等计算!神经网络之类的计算基本都在这两个函数的覆盖范围。对长矢量的计算,采用SIMD方式一样可以获得提高,循环内可以部分展开(loop unroll),减少分支提高指令的发射速度。
  • 特殊函数(EXP,LOG,SINCOS,ATAN2,TANH), 这些函数一般都能找到SIMD版本的实现(GitHub, StackOverflow是好去处)
  • 回归函数SIGMOID: a/(1+EXP(-w*x-b)), 内部响应计算用到此函数,结合SIMD版本EXP,或采用查表结合的方法都可明显提高效率!
  • 二维卷积(conv),二维相关(xcorr)。这两个函数都可以基于DOT函数来优化。这两个函数OpenCV内部计算是采用FFT实现,而且是双精度FFT, 对尺度比较小的情况下效率很低。模板在11x11,窗口在22x22情况下,SIMD直接计算版本会比OpenCV快10倍!
  • Cholesky求解AX=B, 在小矩阵下情况,比如6x6可以完全展开,在分解算法内部可以完全采用float计算!
  • 考虑数据Prefetching会带来明显的提高,优化xcorr函数碰到了,改变数据访问方式,该函数就提高了20%左右!

改进算法内部计算

  • 用指针代替OpenCV的Mat运算。尤其是一些变换多次,表达式比较复杂的Mat运算,效率提高一般会很明显!比如A.t()WA这种计算,其中W是对角权重矩阵。采用SIMD版本的DOT,效率会提高5倍左右!
  • 有些OpenCV的内部算法是采用double进行计算的,最终结果会进行double->float的转化, double对性能,尤其是ARM平台上有一定影响。有些计算,尤其是规模很小的计算,采用double毫无必要!
  • 避免重复计算,尤其是在循环内!Mat或Mat_表达式虽然清爽,但效率未必高!
  • 在确定小循环数目已知的情况下,一定要展开内部循环,如果有多种情况用switch应对!
  • 避免多个Mat或Mat_变量的create调用:可以预先计算需要多大memory,预先申请,然后在该内存上构建Mat或Mat_变量,尤其是在多线程环境下,可避免频繁内存申请和释放引起的overhead!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值