Cachegrind输出解释
这是cachegrind输出的一部分。这部分代码已经执行了1224次。elmg1是大小为16 x 20的无符号长数组。我的机器一级缓存大小为32KB,64B缓存线大小和8路设置Cachegrind输出解释,c,caching,optimization,kcachegrind,cachegrind,C,Caching,Optimization,Kcachegrind,Cachegrind,这是cachegrind输出的一部分。这部分代码已经执行了1224次。elmg1是大小为16 x 20的无符号长数组。我的机器一级缓存大小为32KB,64B缓存线大小和8路设置 对于(i=0;i2);146880048960002448000 } 我之所以把它放在这里,是因为在for循环的第三行中,我看到了许多I1未命中(还有一个L2未命中)。这有点令人困惑,我猜不出原因是什么 我正试图优化(时间)代码的一部分。以上只是一个小片段。我认为在我的程序内存中,访问一个内存占用了我很多钱。与上面的示例
谢谢。您是否尝试展开循环
Ir 146,880
I1mr 1,224
ILmr 1
Dr 48,960
D1mr 0
DLmr 0
Dw 24,480
D1mw 0
DLmw 0
一级缓存分为两个32KByte缓存,一个用于代码I1,另一个用于数据D1。IL和DL是由数据和指令共享的二级或三级缓存
大量I1mr是指令未命中而不是数据未命中,这意味着循环代码正在从I1指令缓存中弹出
第1行和第5行的I1未命中总数为3672,是1224的3倍,因此每次运行循环时,您都会得到3个I1缓存未命中,其中包含64字节的缓存线,这意味着您的循环代码大小在128-192字节之间,以覆盖3条缓存线。因此,第5行的I1未命中是因为循环代码穿过最后一条缓存线
编辑:有关缓存线的详细信息
这个循环代码看起来不像是被自己调用了1224次,所以这意味着有更多的代码将这个代码从I1缓存中推出
32Kbyte I1缓存分为512个缓存线(每个缓存线64字节)。“8路集合关联”部分意味着每个内存地址只映射到512条缓存线中的8条。如果您配置的整个程序是一个32KB的连续内存块,那么它将全部放入I1缓存中,并且不会被弹出。最有可能的情况并非如此,对于相同的8条缓存线,将有超过8个64字节的代码内容块。假设您的整个程序有1M字节的代码(这包括库),那么每组8条缓存线将有大约32条(1M字节/32KB)的代码满足这些相同的8条缓存线
编译器无法始终检测程序的哪些函数将成为热点(多次调用),哪些函数将成为代码点(即几乎从不运行的错误处理程序代码)。GCC具有函数属性,允许您将函数标记为热/冷,这将允许编译器将热函数分组到一个内存块中,以获得更好的缓存使用率(即冷代码不会将热代码推出缓存)
无论如何,这些I1未命中真的不值得花时间担心。A.这没关系,但为什么第5行有缓存未命中,而第3、4行的缓存未命中较少。我是否需要自己指定对齐方式,我了解到malloc默认提供8/16字节对齐方式。是的,malloc应提供至少8字节对齐方式,但这与64字节缓存对齐方式不同。只有当对象数组的每个字节为64字节时,缓存对齐才很重要。如果阵列未分配缓存对齐,则访问阵列中的任何一项可能会导致两次缓存未命中,而不是一次。但在这种情况下,缓存对齐不是问题。谢谢您的回复。但是,有一件事我不明白这与3条缓存线有什么关系?应该有更多的缓存线。