Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cachegrind输出解释_C_Caching_Optimization_Kcachegrind_Cachegrind - Fatal编程技术网

Cachegrind输出解释

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未命中)。这有点令人困惑,我猜不出原因是什么 我正试图优化(时间)代码的一部分。以上只是一个小片段。我认为在我的程序内存中,访问一个内存占用了我很多钱。与上面的示例

这是cachegrind输出的一部分。这部分代码已经执行了1224次。elmg1是大小为16 x 20的无符号长数组。我的机器一级缓存大小为32KB,64B缓存线大小和8路设置

  • 对于(i=0;i<20;i++)783362448250184001220
  • {
  • telm01=elmg1[i];14688007344002448000
  • telm31=(telm01 1);146880 1224 1 48960 0 0 24480 0 0
  • telm11=(telm01>2);146880048960002448000
  • }
  • 我之所以把它放在这里,是因为在for循环的第三行中,我看到了许多I1未命中(还有一个L2未命中)。这有点令人困惑,我猜不出原因是什么

    我正试图优化(时间)代码的一部分。以上只是一个小片段。我认为在我的程序内存中,访问一个内存占用了我很多钱。与上面的示例一样,elmg1是一个大小为16 x 20的无符号长数组。当我试图在代码中使用它时,总会有一些遗漏,在我的程序中,这些变量经常出现。有什么建议吗

    我需要分配和(有时初始化)这些未签名的long。你能建议我更喜欢哪一种吗,calloc还是数组声明,然后是显式初始化。 顺便问一下,缓存处理它们的方式会有什么不同吗


    谢谢。

    您是否尝试展开循环

  • 我现在不会担心L1失误。此外,1224次中有一次二级未命中是正常的,cpu必须在某个点将值加载到缓存中
  • 与程序的其余部分相比,此代码的二级未命中率是多少
  • 使用calloc(),如果数组大小始终相同,并且使用常量作为大小,则编译器可以优化数组的归零。另外,影响缓存线使用的唯一因素是对齐,而不是它的初始化方式
  • 编辑:第一次读错时很难读懂的数字

    让我们确保我正确阅读了第5行的数字:

    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条缓存线有什么关系?应该有更多的缓存线。