NEON优化:性能优化经验总结

NEON优化:性能优化经验总结

    • 优化技巧
      • 高频常用
      • C语言编码级考虑
      • 编译选项
      • 注意事项
    • 其他问题
    • 相关资源

NEON优化系列文章:

  1. NEON优化1:软件性能优化、降功耗怎么搞?link
  2. NEON优化2:ARM优化高频指令总结, link
  3. NEON优化3:矩阵转置的指令优化案例,link
  4. NEON优化4:floor/ceil函数的优化案例,link
  5. NEON优化5:log10函数的优化案例,link
  6. NEON优化6:关于交叉存取与反向交叉存取,link
  7. NEON优化7:性能优化经验总结,link
  8. NEON优化8:性能优化常见问题QA,link

本文总结常用的NEON优化技巧及重要参考资料。

NEON优化:性能优化经验总结_第1张图片

photo from 《Practical approach to Arm Neon Optimization》,展示了各领域如NEON优化的优秀示例代码库,Neon-enabled libraries。

优化技巧


高频常用

  • 热点函数涉及到大量IO读写操作时,数据的内存地址尽量与NEON数组或系统位数对齐,如32位对齐,可降低访问开销

  • 跑demo得到profile,看开销占比Top5,必须对其优化一版

  • 重点优先搞NEON指令并行计算,能大幅降低开销

  • for循环

    • 循环数字不大优先用4排展开;大循环用8排并行计算
    • 循环变量i,尽量设置成基本数据类型,如32位
    • 如for循环中if优化,if中对cnt进行计数,用4个寄存器存,末尾再将4个寄存器值相加
    • 循环时用减法计数器时可降开销
      • 如: for (b = 0; b < num; b++)
      • 改为:for (b = 0; b < num - 3; b += 4)
      • 可再改:for (b = num - 1; b - 3 >= 0; b -= 4)
      • 可再改:for (b = num - 1; b >= 3; b -= 4)
      • 务必记得读写数据时,将坐标前移相应位次,原读取:cf[b], 今读取:cf[b - 3]
  • 数组索引取值

    • 数组索引以及索引内部涉及运算的,尽量换成指针偏移加减来做
    • 避免大范围索引跳跃,减少cache miss,具体例子见:矩阵乘优化,分块成4*4处理
  • 内存使用

    • 优先用局部变量,而非malloc堆内存,减少cache miss
    • 针对具体变量类型,手动for循环并行拷贝值,可能比memcpy()函数更高效,因为memcpy内部还涉及大量判断,以保证平台兼容性
    • 涉及IO读写时,软仿数据可能无法准确反映硬仿结果,应以硬仿为准,软仿无法模拟最新芯片层面优化
    • 运用NEON指令时,4路运算的数组(128位=16字节),内存地址最好要16字节对齐
  • 指令运算

    • 矩阵乘场景,在不大幅增加寄存器变量的前提下,外部的A也最好并行多读几路数据进来,跟B的各列运算,减少B各列的读取次数
    • 乘加指令,add和mul可以合并为mla,一条指令完成乘加操作
  • 算法角度

    • 观察热点函数的算法,从算法层面优化时间复杂度,进行等效实现
      • 数据是否有序,for循环是否可以变成二分
      • 冒泡排序是否可以变成归并
      • 是否有冗余逻辑,冗余变量计算
  • 细节

    • 差1问题:注意再注意!
      • 发现循环中并行计算时常有:-4, +=4组合问题,会导致结尾处哪怕有4个值也只能单独计算。
      • 应改为:-3,+=4;其他类似:-7, +=8;不管是<=、<或>=场景。
      • 举例:
        • 原始:for (i = 0; i < size; i++)
        • 并行:for (i = 0; i < size - 3; i += 4)
        • 扫尾:for (; i < size; i ++)
      • 原理:以4路为例
        • 并行写法,-3的目的是保证从i开始往后能有4个可用值,+4的目的是对i进行迭代,每4路前进一次
        • 扫尾写法,加上扫尾的目的是为了处理size不能被4整除的场景,末尾不足4个的剩余值单独处理
    • NEON优化宏开关
      • 常用#ifndef XX_NO_NEON宏开关来控制NEON开关,便于回退NEON优化版本来debug

C语言编码级考虑

  • C语言中一条事件的处理函数尽可能在一个源文件中
  • 至少在一个.o包中,避免函数远跳,一个事件处理的函数都能限制在4K之内,程序运行效率高上数倍至几十倍不稀奇。
  • 只有“if”比“if else"运行的快
  • 同一段代码放在“if else”的“if”块里比放在“else"里快,除非"pragma"要求"else"优先。因此正常流程代码走“if”,异常处理走“else”。
  • “switch”比“if else”快,而且代码整洁。

【深入理解计算机系统】

  • 组织代码结构,善用CPU缓存,数据段/代码段连续可以提高CPU缓存命中率
  • 减少循环中的函数调用或变量,特别是不依赖于循环的函数返回结果或者变量
  • 极简函数时,尽量inline展开,减少函数调用栈的开销
  • 消除不必要的存储器引用,如 for循环中 *dest = *dest - nums[i],可用中间变量替换*dest,for循环后再赋值给*dest,可减少for内的一次读写操作。
  • 简单的循环展开,编译器可以自己完成,优化选项O2及以上,或者命令 -funroll-loops,可调用gcc进行循环展开
  • 能用整型不用浮点,整数乘法/加法和浮点加法,只用一个周期,浮点乘法需要2个周期。

——来自《深入理解计算机系统》第一部分,第四章,优化程序性能

编译选项

  • 初始编译选项:O0,Omemory(优化内存),开内联
  • 优化编译选项:O2,Otime(优化时间),不开内联;一般开O2
  • 建议基线优化时,尽量选不开内联以改善视图,以便观察热点函数中实际大头开销所在
    • 开了内联,容易出现,有的大头开销函数I被内联到X函数中,但仅看X函数半天看不出哪里可以优化的
    • 如关内联,则大头开销函数I则远超X函数,成为Top热点开销函数,便于优化分析
    • O3/O2编译选项都会自动内联可以内联的函数
  • 尽量能用O3优化就用O3,不能的部分代码单独用O2优化编译,然后链接该模块,再整体一起O3编译
  • 不要轻易restore default编译设置,否则会导致所有配置失效,如编译平台、编译选项

注意事项

  • 开销计算

    • 算每帧开销时,要确认每帧时长是10ms、20ms,修改对应的帧长时间
    • RVDS中计算的MCPS本质为MIPS,注意与硬仿的结果进行区分

其他问题


#ifndef XX_NO_NEON来定义有关NEON的宏,用意何在,为啥不用#ifdef XX_NEON

#ifndef ALG_NO_NEON
// opt_neon_code
...
#else
// origin code
...
#endif
  • ifndef的意义在于,因为基线输出查看属于低频操作,而查看每次NEON优化的进展是高频操作,所以默认走NEON优化,而查看基线时只需要添加对应宏即可。
  • 当然,如习惯#ifdef XX_NEON也无不可,不影响效果。

相关资源


附学习过程中用到的好资源,最后一个参考链接是彩蛋,涉及:Optimizing Software in C++ - Agner Fog - PDF,C++软件性能优化。

这本书是所有C++程序员都应该要读的一本书,它事无巨细地从语言层面、编译器层面、内存访问层面、多线程层面、CPU层面讲述了如何对软件性能调优,是一本经典的电子书,欢迎进阶阅读!

资料链接汇总:

  • google keywords: neon optimization,可获取大量有关资源
  • NEON优化ARM官方介绍,link
  • NEON优化ARM官方介绍文章翻译,link
  • ARM官方相关程序员Neon编程指南,link
  • NEON优化指令解释:link
  • Optimizing C Code with Neon Intrinsics, link
  • ARM Neon Intrinsics 学习指北:从入门、进阶到学个通透,link
  • How to improve software performance with NEON, link
  • ittiam:印度以太公司专业优化资料,link1,link2
  • AI神经网络CNN中im2col矩阵卷积核的计算优化,link
  • 谷歌开发cmath.h的NEON优化,库链接:link,库说明:link
  • 重磅!性能优化PDF:Optimizing software in C++,An optimization guide for Windows, Linux, and Mac platforms,link
  • C语言代码性能优化11种实用方法,link

你可能感兴趣的:(经验总结,性能优化,算法)