这是缓存器输出的一部分。这部分代码已经执行了1224次。elmg1是一个大小为16x20的无符号长数组。我的机器L1缓存大小是32 16,64B缓存线大小和8路集关联。
答:我把它放在这里的原因是,在for循环中的第3行中,我看到了一些I1遗漏(一个L2也错过了)。这有点令人困惑,我猜不出原因何在?
我正在努力优化(时间)一部分代码。以上只是一个小片段。我想在我的程序内存访问中花费我很多钱。与上面的示例一样,elmg1是一个大小为16x20的无符号多头数组。当我尝试在代码中使用它时,总是会有一些遗漏,在我的程序中,这些变量经常发生。有什么建议吗?
我需要分配和(有时初始化)这些未签名的多头。你能建议我应该选择哪一个,calloc或数组声明,然后显式初始化。顺便问一下,缓存处理它们的方式会有什么不同吗?
谢谢。
发布于 2010-11-01 07:43:59
你试过打开循环吗?
编辑:第一次很难读错的数字。
让我确保我正在正确地阅读第5行的数字:
Ir 146,880
I1mr 1,224
ILmr 1
Dr 48,960
D1mr 0
DLmr 0
Dw 24,480
D1mw 0
DLmw 0L1缓存分为两个32 32KByte缓存,一个用于代码I1,另一个用于数据D1。IL & DL是由数据和指令共享的L2或L3缓存。
大量的I1mr是指令丢失而不是数据丢失,这意味着循环代码被从I1指令缓存中弹出。
I1在第1行和第5行中遗漏了总计3672,即3乘以1224,因此每次运行循环时,您都会得到3个I1缓存缺失和64字节缓存行,这意味着您的循环代码大小在128-192字节之间,可以覆盖3行缓存行。因此,这些I1在第5行中没有出现,因为循环代码就是在那里穿过最后一个缓存行的。
我建议使用KCachegrind查看缓存研磨的结果。
编辑:有关缓存行的更多信息。
这个循环代码看起来不像是自己被调用了1224次,所以这意味着有更多的代码将这些代码从I1缓存中推开。
您的32K字节I1缓存被划分为512个缓存行(每个64字节)。“8路集关联”部分意味着每个内存地址仅映射到这512行中的8行。如果您是profile的整个程序是一个连续块,内存为32K字节,那么它将全部装入I1缓存,没有一个会被弹出。这很可能不是这样,对于相同的8行缓存行,将有超过8 64字节的代码块内容。假设您的整个程序有1M字节的代码(这包括库),那么每组8行缓存行将有32条(1M字节/32K字节)代码内容,用于这些相同的8条缓存行。
有关CPU缓存的所有血淋淋的详细信息,请阅读这篇lwn.net文章。
编译器不能始终检测程序的哪些函数将是热点(多次调用),哪些将是代码独裁者(即错误处理程序代码,几乎从不运行)。GCC具有函数属性热/冷,它允许您将函数标记为热/冷,这将允许编译器将热函数分组到一个内存块中,以获得更好的缓存使用(即冷代码不会将热代码从缓存中推送出去)。
无论如何,那些I1的错过真的不值得花时间去担心。
https://stackoverflow.com/questions/4066937
复制相似问题