c++ - 使用 valgrind 测量缓存未命中

标签 c++ performance optimization cpu valgrind

<分区>

我有一个关键路径,它在一个线程中执行,固定到一个核心。

我有兴趣确定发生缓存未命中的位置。环顾四周后,valgrind 的 cachegrind 工具似乎对我有帮助。但是,我对该工具在这种情况下的功能有一些疑问:

  1. 提供的缓存未命中位置有多具体?是否输出变量名?
  2. 我可以只介绍一个话题吗?
  3. 是否可以分析代码的特定部分?
  4. 所有用于测量缓存未命中的功能,它们是否同样适用于 TLB 未命中?
  5. 我可以将 cachegrind 与我的发布/优化代码一起使用吗?
  6. 我知道 valgrind 使用虚拟机进行采样。这种方法的准确性如何?

问题 1 是最重要的。

非常感谢任何有关命令行参数的帮助。

最佳答案

cachegrind 可以输出有关缓存未命中的全局和局部信息,并在行级别进行注释(如果原始程序是使用调试信息编译的)。比如下面的代码:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int main(int argc, char**argv) {
  size_t n = (argc == 2 ) ? atoi(argv[1]) : 100;
  double* v = malloc(sizeof(double) * n);
  for(size_t i = 0; i < n ; i++)
    v[i] = i;

  double s = 0;
  for(size_t i = 0; i < n ; ++i)
    s += v[i] * v[n - 1 - i];
  printf("%ld\n", s);
  free(v);
  return 0;
}

gcc a.c -O2 -g -o a 编译 并使用 valgrind --tool=cachegrind ./a 10000000 输出运行:

==11551== Cachegrind, a cache and branch-prediction profiler
==11551== Copyright (C) 2002-2013, and GNU GPL'd, by Nicholas Nethercote et al.
==11551== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==11551== Command: ./a 10000000
==11551== 
--11551-- warning: L3 cache found, using its data for the LL simulation.
80003072
==11551== 
==11551== I   refs:      150,166,282
==11551== I1  misses:            876
==11551== LLi misses:            870
==11551== I1  miss rate:        0.00%
==11551== LLi miss rate:        0.00%
==11551== 
==11551== D   refs:       30,055,919  (20,041,763 rd   + 10,014,156 wr)
==11551== D1  misses:      3,752,224  ( 2,501,671 rd   +  1,250,553 wr)
==11551== LLd misses:      3,654,291  ( 2,403,770 rd   +  1,250,521 wr)
==11551== D1  miss rate:        12.4% (      12.4%     +       12.4%  )
==11551== LLd miss rate:        12.1% (      11.9%     +       12.4%  )
==11551== 
==11551== LL refs:         3,753,100  ( 2,502,547 rd   +  1,250,553 wr)
==11551== LL misses:       3,655,161  ( 2,404,640 rd   +  1,250,521 wr)
==11551== LL miss rate:          2.0% (       1.4%     +       12.4%  )

I1 未命中率告诉我们没有指令缓存未命中。

D1 未命中率告诉我们有很多缓存 L1 未命中

LL 未命中率告诉我们有一些 LL级缓存未命中。

为了更准确地查看未命中位置,我们可以运行 kcachegrind cachegrind.out.11549,选择 L1 Data Read miss 并在应用程序代码中导航, 如图所示 this screenshot

这应该回答 1)。我认为答案是否定的 2) 3) 和 4)。如果您使用调试信息进行编译(没有它们,您将获得全局信息,但不是每行信息),则 5) 是肯定的。从 6) 开始,我会说 valgrind 通常会提供非常不错的一阶近似值。 Goig 到 perf 显然更准确!

关于c++ - 使用 valgrind 测量缓存未命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32542164/

相关文章:

C++ 符号处理和导出 => 允许代码重复?

c - 优化数组转置功能

python - 如何在对其项目施加一些限制的同时快速消除列表中的项目?

c++ - 按值捕获的广义 lambda 始终位于同一地址

c++ - 这个程序会不会导致内存泄漏

iphone - 查找 iPhone 上 OpenGL 应用程序的瓶颈

MYSQL SELECT 查询非常慢 - 可以使用 JOIN 吗?

mysql - 简单的更新查询需要很长时间才能在 MySQL 中执行

java - 值比较和值分配之间是否存在任何性能差异?

c++ - 对于矩阵乘法,Eigen + MKL 比 Matlab 慢