使用cachegrind和callgrind测量不同的读写次数

14

我正在使用Cachegrind、Callgrind和Gem5进行一些实验。我注意到在缓存模拟器中,许多存储访问被计算为读取,而在Callgrind中被计算为写入,而在Gem5中则同时被计算为读取和写入。

我们来看一个非常简单的例子:

int main() {
    int i, l;

    for (i = 0; i < 1000; i++) {
        l++;
        l++;
        l++;
        l++;
        l++;
        l++;
        l++;
        l++;
        l++;
        l++;
        ... (100 times)
     }
 }

我使用以下命令进行编译:

gcc ex.c --static -o ex

因此,根据汇编文件,addl $1, -8(%rbp) 被执行了 100,000 次。由于它既是读取操作又是写入操作,我本来期望有 100k 次读取和 100k 次写入。但是,cachegrind 只计算了读取次数,callgrind 只计算了写入次数。

 % valgrind --tool=cachegrind --I1=512,8,64 --D1=512,8,64
--L2=16384,8,64 ./ex
==15356== Cachegrind, a cache and branch-prediction profiler
==15356== Copyright (C) 2002-2012, and GNU GPL'd, by Nicholas Nethercote et al.
==15356== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==15356== Command: ./ex
==15356== 
--15356-- warning: L3 cache found, using its data for the LL simulation.
==15356== 
==15356== I   refs:      111,535
==15356== I1  misses:        475
==15356== LLi misses:        280
==15356== I1  miss rate:    0.42%
==15356== LLi miss rate:    0.25%
==15356== 
==15356== D   refs:      104,894  (103,791 rd   + 1,103 wr)
==15356== D1  misses:        557  (    414 rd   +   143 wr)
==15356== LLd misses:        172  (     89 rd   +    83 wr)
==15356== D1  miss rate:     0.5% (    0.3%     +  12.9%  )
==15356== LLd miss rate:     0.1% (    0.0%     +   7.5%  )
==15356== 
==15356== LL refs:         1,032  (    889 rd   +   143 wr)
==15356== LL misses:         452  (    369 rd   +    83 wr)
==15356== LL miss rate:      0.2% (    0.1%     +   7.5%  )
 % valgrind --tool=callgrind --I1=512,8,64 --D1=512,8,64
--L2=16384,8,64 ./ex
==15376== Callgrind, a call-graph generating cache profiler
==15376== Copyright (C) 2002-2012, and GNU GPL'd, by Josef Weidendorfer et al.
==15376== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==15376== Command: ./ex
==15376== 
--15376-- warning: L3 cache found, using its data for the LL simulation.
==15376== For interactive control, run 'callgrind_control -h'.
==15376== 
==15376== Events    : Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw
==15376== Collected : 111532 2777 102117 474 406 151 279 87 85
==15376== 
==15376== I   refs:      111,532
==15376== I1  misses:        474
==15376== LLi misses:        279
==15376== I1  miss rate:    0.42%
==15376== LLi miss rate:    0.25%
==15376== 
==15376== D   refs:      104,894  (2,777 rd + 102,117 wr)
==15376== D1  misses:        557  (  406 rd +     151 wr)
==15376== LLd misses:        172  (   87 rd +      85 wr)
==15376== D1  miss rate:     0.5% ( 14.6%   +     0.1%  )
==15376== LLd miss rate:     0.1% (  3.1%   +     0.0%  )
==15376== 
==15376== LL refs:         1,031  (  880 rd +     151 wr)
==15376== LL misses:         451  (  366 rd +      85 wr)
==15376== LL miss rate:      0.2% (  0.3%   +     0.0%  )

有人能给我一个合理的解释吗?如果我认为实际上有大约100k个读取和100k个写入操作(即添加了2个缓存访问),那么我的想法是正确的吗?

2个回答

3

来自cachegrind手册:5.7.1. 缓存模拟细节

  • 修改内存位置的指令(例如inc和dec)被计算为只进行了一次读取,即单个数据引用。这可能看起来很奇怪,但由于写入永远不会导致未命中(读取保证块在缓存中),因此并不是非常有趣。

    因此,它测量的不是数据缓存访问次数,而是数据缓存未命中次数。

看起来callgrind的缓存模拟逻辑与cachegrind不同。我认为callgrind应该产生与cachegrind相同的结果,所以这可能是一个bug吗?


这正是我的想法。可能是个bug,但令人惊讶的是,他们会写两遍缓存模拟吗? - Maxime Chéramy
1
从我所看到的情况来看,他们似乎至少实现了缓存模拟的部分两次。我并不完全理解本地->VEX IR转换和仪器逻辑。 - Neopallium

-1

1
添加cache-sim = yes不会改变任何内容:指定缓存大小会自动激活缓存模拟。 - Maxime Chéramy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接