---
title: Cache Miss高
description: "- Cache Line对齐"
url: https://www.hikunpeng.com/document/detail/zh/kunpengdevkithistory/devkit_25_0_0/usermanual/devkit-hypertuner-051.html
sourcePath: /source/zh/kunpengdevkithistory/devkit_25_0_0/usermanual/devkit-hypertuner-051.html
indexId: a1452721c8012add6fc1701a2016947e40d2392df3dfad61b19d95b025cb26f783
---
# Cache Miss高

#### Cache优化

- Cache Line对齐
  请参见：https://www.hikunpeng.com/document/detail/zh/perftuning/tuningtip/kunpengtuning_12_0052.html(https://www.hikunpeng.com/document/detail/zh/perftuning/tuningtip/kunpengtuning_12_0052.html)

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

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


优化方案：

  - OpenMP代码中使用reduction子句代替直接写入共享变量（循环过程中写入线程私有变量）。
  - 线程私有的变量按照Cache Line大小对齐（线程栈上的变量除外）。
  - 使用线程私有变量（如GCC支持__thread，C11支持_Thread_local关键字）。
- 数据重排
  数据重排是指物理上不连续的热点数据变成连续的数据，使得CPU可以按Cache Line访问，提升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)，其中addr为要预取的地址，rw预取addr所在Cache Line，接下来是要做什么操作（读还是写，取值可为0/1，默认值为0，0表示读，1表示写），locality为预取之后访问此Cache Line的频率（取值可为0/1/2/3，0表示只访问一次，该Cache Line不应该驻留；3表示该条Cache Line将来会被较为频繁地访问，应尽量驻留在所有level的Cache中）。
