首页 > 代码库 > 软件性能优化方法汇编

软件性能优化方法汇编

本文主要是对平时工作和Ulrich Drepper的《What Every Programmer Should Know About Memory》中软件性能优化方法的总结归纳,主要为了方便日后快速查看和检查,不涉及方法具体细节。本文涉及的软件性能优化手段包括cache、TLB、预取、多线程、总线带宽、NUMA等。日后会不定期更新。

cache优化

跳过cache

  • 对于一次性的读写操作(比如网卡收发包等),因为数据不会被重复使用,所以没有必要把数据更新到cache line中,避免换出cache中有用数据。相关方法:_mm_stream_si32/_mm_stream_load_si128等。

L1D cache优化

  • 改进数据局部性,如对于数组,1)把列访问改为行访问;2)把大矩阵切分成小矩阵,使数据集为一个cache line大小。
  • 如果CPU支持vectorization特性,使用SIMD (Single Instruction, Multiple Data)操作,提高指令效率。相关方法:_mm_load_sd/_mm_add_pd/_mm_mul_pd等。
  • 保证Critical Word First & Early Restart能最大发挥作用,最先使用的字段(Critical Word)放在数据结构的前面。
  • 按数据结构字段顺序访问字段。
  • 数据结构按cache line字长对齐。相关方法:__attribute((aligned(64)), posix_memalign等
  • 字段保证自然对齐,不要使用pack属性。
  • 大数据结构拆分成小数据结构。
  • 数组(集中)结构优于链表(分散)结构。

L1I cache优化

  • 使用分支预测,以便于编译器进行代码局部化优化。相关方法:__builtin_expect或-O2、-freorder-blocks编译器选项等。
  • 使用小循环代码块。
  • 保证代码对齐。相关方法:-falign_fuctions/-falign_jumps/-falign_loops=cache line字长等。

L2 cache优化

  • 数据集保证在L2 cache大小以内,以便减少L2 cache miss。
  • 对于超过L2 cache大小的大数据集,按L2 cache大小拆分成小数据集。

TLB优化

  • 减少使用页面数,减少TLB miss。相关方法:减小软件目标文件大小,减少数据集大小等。
  • 关闭内核 ASLR(Address Space Layout Randomization)特性,减少TLB miss。

预取优化

  • CPU自带的硬件预取。一般功能简单,如不支持跨页,不支持非线性访问,2+次cache miss后才会触发等。可酌情关闭,使用软件预取。
  • 软件预取。支持跨页和非线性访问。相关方法:__mm_prefetch、-fprefetch_loop_arrays等编译器选项等。
  • 使能CPU OOO(out of order)特性的推测预取。不需要软件干预。
  • 使用预取线程,要注意多线程同步问题。相关方法:超线程预取等。
  • 使能CPU DCA(Direct Cache Access)特性。不需要软件干预。

多线程优化

并发优化

  • 分离只读变量和读写变量,减少 false sharing,减少RFO(Request For Ownership)。相关方法:只读变量用const修饰等。
  • 使用线程本地变量,减少RFO。相关方法:__thread等。
  • 把变量分组集中,并按cache line对齐。相关方法:把只读变量、读写变量分别定义在不同的结构体中。

原子优化

  • LL/SC (Load Lock/Store Conditional)。相关方法:__sync_add_and_fetch等。
  • CAS (Compare-and-Swap)。相关方法:__sync_bool_compare_and_swap等。
  • Transaction Menory。

内存总线带宽优化

  • 设置线程亲和性(thread affinity)。保证工作在不同数据集的线程工作在不同的核上,从而保证L1 cache不共享。

NUMA优化

  • 设置内存亲和性策略。相关方法:set_mempolicy等。
  • 设置VMA地址空间亲和性策略。相关方法:mbind等。
  • 设置线程的CPU和内存亲和性策略:相关方法:cpuset等。

其他

通过gcc自动优化分支预测。相关方法:配置-fprofile_use、-fprofile_generate编译器选项。

把共享数据转化为独享数据。相关方法:对于只读数据,通过复制;对于读写数据,通过先在各node上累加,然后把累加结果再累加得到最终结果。

用度量工具(如massif、memuage等)发现连续分配小内存块的代码流程,重构为分配连续地址的大内存块。

用度量工具(pagein, time等)统计缺页情况。针对缺页严重模块改用大页面以便减少缺页次数。相关技术:hugetlb等。

 

 --EOF--

软件性能优化方法汇编