2010-11-01 155 views
3

这是cachegrind输出的一部分。这部分代码已执行1224次。 elmg1是一个无符号长数组,大小为16 x 20。我的机器L1高速缓存大小为32KB,64B高速缓存行大小和8路组相关联。Cachegrind输出解释

  1. 为(I = 0;我< 20; i ++在)78336 2448 2 50184 0 0 1224 0 0
  2. {
  3. telm01 = elmg1 [I]; 146,880 0 0 73,440 0 0 24,480 0 0
  4. telm31 =(telm01 < < 3)^ val1; 97,920 0 0 48,960 0 0 24,480 0 0
  5. telm21 =(telm01 < < 2)^(val1 >> 1); 146,880 1,224 1 48,960 0 0 24,480 0 0
  6. telm11 =(telm01 < < 1)^(val1 >> 2); 146880 0 0 48960 0 0 24,480 0 0
  7. }

答:我已经把它放在这里的原因,就是在里面的3号线的循环,我看到一些I1的惦记(一个L2错过)。这有点混乱,我猜不出为什么?

B.我想优化(时间)一部分代码。以上只是一小段片断。我认为在我的程序内存中存取成本很高。像上面的例子一样,elmg1是一个16 x 20大小的无符号长整型数组。当我尝试在代码中使用它时,总会有一些错误,并且在我的程序中这些变量发生了很多。有什么建议么?

C.我需要分配和(有时初始化)这些无符号长整数。你能建议哪一个我更喜欢,calloc或数组声明,然后显式初始化。顺便说一下,缓存处理它们的方式会有什么不同吗?

谢谢。

回答

3

您是否试图展开循环?

  1. 我现在不担心L1错失。另外,1224次中的一个L2错过了,CPU必须在某个时刻将值加载到缓存中。
  2. 与程序的其余部分相比,此代码的L2缺失的百分比是多少?
  3. 使用calloc(),如果数组大小始终相同,并且您使用大小的常量,则编译器可以优化数组的归零。此外,唯一会影响缓存行用法的是对齐,而不是如何初始化。

编辑:难以阅读的数字,并阅读错误的第一次。

可以确保我读的数字正确的线路5:

Ir 146,880 
I1mr 1,224 
ILmr 1 
Dr 48,960 
D1mr 0 
DLmr 0 
Dw 24,480 
D1mw 0 
DLmw 0 

L1缓存被分成两个32K字节缓存一个代码I1和数据D1之一。 DL是由数据和指令共享的L2或L3缓存。

大量的I1mr是指令未命中而未丢失数据,这意味着循环代码正在从I1指令缓存中弹出。

I1错过第1行& 5总计3672是1224的3倍,所以每次循环运行时,都会得到3个I1高速缓存未命中,64Byte高速缓存行,这意味着您的循环代码大小在128-192字节之间以覆盖3个缓存行。所以那些I1在第5行错过是因为这是循环代码跨越最后一个缓存行的地方。

I would recommend using KCachegrind for viewing the results from cachegrind

编辑:更多关于高速缓存行。

该循环代码看起来并不像它自己调用1224次那样,这意味着有更多的代码将这些代码从I1缓存中移出。

您的32K字节I1高​​速缓存分为512个高速缓存行(每个64bytes)。 “8路组关联”部分意味着每个存储器地址仅被映射到这512个高速缓存行中的8个。如果你正在配置的整个程序是一个连续32K字节的内存块,那么它将全部放入I1缓存中,并且不会被弹出。这很可能不是这种情况,并且对于相同的8个高速缓存行将会有多于8个64字节的代码块内容。假设你的整个程序有1M字节的代码(这包括库),那么每组8条高速缓存行将有大约32条(1Mbyte/32K字节)的代码满足这些相同的8条高速缓存行。

Read this lwn.net article for all the gory details about CPU caches

编译器有时不能检测出该程序的功能将是热点(称为很多很多次),并且将codespots(即错误处理程序代码,这几乎从不运行)。 GCC具有功能属性hot/cold,这将允许您将功能标记为热/冷,这将允许编译器将热功能组合在一块内存中以获得更好的缓存使用(即,冷码不会将热码推出高速缓存)。

反正那些I1错过真的不值得花时间去担心。

+0

答:没关系,但是为什么在第5行存在缓存未命中,而第3,4行的存储空间不足。我是否需要自己指定对齐方式,我读取默认情况下的malloc提供了8/16字节的对齐方式。 – anup 2010-11-01 08:57:09

+0

是的,malloc应该提供至少8byte的对齐方式,但这与64bytes缓存对齐不一样。只有当你有一个64bytes的对象数组时,高速缓存对齐才是重要的。如果数组未分配缓存对齐,则访问数组中的任何一项可能会导致两次缓存未命中,而不是一次。但在这种情况下,缓存对齐不是问题。 – Neopallium 2010-11-01 10:34:16

+0

感谢您的回复。但是,有一件事我不明白这些与3个缓存行有什么关系?应该有更多数量的缓存行。 – anup 2010-11-01 10:52:04