---
title: cache Miss高
description: "进入系统性能分析，采用微架构分析，确定造成Cache Miss高的进程和代码。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengdevkithistory/devkit_24_rc1/Plugins_UserGuide/devkit-hypertuner-037.html
sourcePath: /source/zh/kunpengdevkithistory/devkit_24_rc1/Plugins_UserGuide/devkit-hypertuner-037.html
indexId: 96ed0a1762a1ed930acd336a4302d1f366fb99707c63bea291a5b36efe09620390
---
# cache Miss高

进入系统性能分析，采用微架构分析，确定造成Cache Miss高的进程和代码。

#### Cache优化

- cacheline对齐
  请参见：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)

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