中文
注册

cache Miss高

Cache优化

  • cacheline对齐

    参考链接:https://www.hikunpeng.com/document/detail/zh/perftuning/tuningtip/kunpengtuning_12_0052.html

  • 消除伪共享

    伪共享是指多核的多个私有变量位于同一个cacheline内,由于每个核修改变量时,会将其它核的整个cacheline无效掉,这样就会造成该cacheline在不同的核频繁迁移。这种现象类似共享变量的读写,但又不是真正的共享变量,故称伪共享。如图 伪共享所示。

    图1 伪共享

    CPU0与CPU1的私有变量刚好位于同一个cacheline内(私有变量分别对应红色块与蓝色块),CPU0修改其私有变量,会将整个cacheline无效,CPU1要访问其私有变量又需要重新从内存中读取,效率降低。

    优化方案:

    • OpenMP代码中使用reduction子句代替直接写入共享变量(循环过程中写入线程私有变量)。
    • 线程私有的变量按照cacheline大小对齐(线程栈上的变量除外)。
    • 使用线程私有变量(如GCC支持_thread,C11支持_Thread_local关键字)。
  • 数据重排

    数据重排是指物理上不连续的热点数据变成连续的数据,使得CPU可以按cacheline访问,提升Cache命中率。例如矩阵乘法,假设矩阵按行储存,则读取矩阵B的列元素不连续,Cache命中率低。(为了方便理解,下图假设B矩阵的行/列元素总大小与Cache块大小一致)

    图2 矩阵乘法1

    通过对矩阵B重排后,提升了Cache命中率,可以从L1 Cache中连续读取列元素。

    图3 矩阵乘法2
  • 使用软件预取

    软件预取是指通过PRFM指令提前将后面要使用的数据加载到Cache中,避免使用时再读取数据增加Cache Miss的内存访问延迟。如图4所示,提前预取addr2的数据,执行addr1完成,addr2的数据已经准备好。

    图4 软件预取

    GCC中可以使用_builtin_prefetch()函数,函数原型为_builtin_prefetch(const void addr, int rw, int locality),其中add为要预取的地址,rw预取addr所在cacheline,接下来是要做什么操作(读还是写,取值可为0/1,默认值为0,0表示读,1表示写),locality为预取之后访问此cacheline的频率(取值可为0/1/2/3,0表示只访问一次,该cacheline不应该驻留;3表示该条cacheline将来会被较为频繁地访问,应尽量驻留在所有level的Cache中)。

搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词