• valgrind试用笔记


    valgrind是一款功能齐全的代码诊断软件,Ubuntu下可以获取安装

    sudo apt-get install valgrind

    官网上可以下载 Manuel.pdf。

    可以诊断内存泄漏

    g++ xxx.cpp
    valgrind --tool=memcheck ./a.out

    它会汇报内存漏点。

    也可以诊断缓存命中率

    g++ xxx.cpp
    valgrind --tool=cachegrind ./a.out

    它会汇报一级缓存数据命中率、指令命中率、最末级缓存命中率等信息。

    如下示例

    #include<iostream>
    using namespace std;
    #include<ctime>
    
    const size_t N = 1E3;
    
    int main(){
    
            double y=0,z=0;
            clock_t tstart = clock();
            double *A = new double [N*N];
            for(size_t i=0;i<N*N;i++)A[i]=i;
            double *B = new double [N*N];
            for(size_t i=0;i<N*N;i++)B[i]=i;
            double *C = new double [N*N];
            for(size_t i=0;i<N;i++)
            for(size_t j=0;j<N;j++){
                    z=0;
                    for(size_t l=0;l<N;l++)
                            z += B[l*N+j];
                    y=0;
                    for(size_t k=0;k<N;k++){
                            y += A[k*N+i] * z;
                    }
                    C[i*N+j]=y;
            }
            clock_t t1=clock();
            cout<<(double)(t1-tstart)/CLOCKS_PER_SEC<<" s"<<endl;
            delete [] A; delete [] B; delete [] C;
            return 0;
    }

    这个代码的内层循环中,l,k是行数,所以会导致 memory locality 不太好,反映在 valgrind 的检测报告中,就是1级缓存数据命中率低一些(D1 miss rate: 11.8%)。

    ==2322== Cachegrind, a cache and branch-prediction profiler
    ==2322== Copyright (C) 2002-2017, and GNU GPL'd, by Nicholas Nethercote et al.
    ==2322== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==2322== Command: ./a.out
    ==2322== 
    --2322-- warning: L3 cache found, using its data for the LL simulation.
    276.428 s
    ==2322== 
    ==2322== I   refs:      31,053,190,692
    ==2322== I1  misses:             1,976
    ==2322== LLi misses:             1,928
    ==2322== I1  miss rate:           0.00%
    ==2322== LLi miss rate:           0.00%
    ==2322== 
    ==2322== D   refs:      17,025,701,244  (15,018,537,430 rd   + 2,007,163,814 wr)
    ==2322== D1  misses:     2,001,266,444  ( 2,000,014,098 rd   +     1,252,346 wr)
    ==2322== LLd misses:       125,490,381  (   125,113,840 rd   +       376,541 wr)
    ==2322== D1  miss rate:           11.8% (          13.3%     +           0.1%  )
    ==2322== LLd miss rate:            0.7% (           0.8%     +           0.0%  )
    ==2322== 
    ==2322== LL refs:        2,001,268,420  ( 2,000,016,074 rd   +     1,252,346 wr)
    ==2322== LL misses:        125,492,309  (   125,115,768 rd   +       376,541 wr)
    ==2322== LL miss rate:             0.3% (           0.3%     +           0.0%  )

    而下面的代码的内层循环中,k,l是列数,memory locality 就好一些,

    #include<iostream>
    using namespace std;
    #include<ctime>
    
    const size_t N = 1E3;
    
    int main(){
    
            double y=0,z=0;
            clock_t tstart = clock();
            double *A = new double [N*N];
            for(size_t i=0;i<N*N;i++)A[i]=i;
            double *B = new double [N*N];
            for(size_t i=0;i<N*N;i++)B[i]=i;
            double *C = new double [N*N];
            for(size_t i=0;i<N;i++)
            for(size_t j=0;j<N;j++){
                    z=0;
                    for(size_t l=0;l<N;l++)
                            z += B[j*N+l];
                    y=0;
                    for(size_t k=0;k<N;k++){
                            y += A[i*N+k] * z;
                    }
                    C[i*N+j]=y;
            }
            clock_t t1=clock();
            cout<<(double)(t1-tstart)/CLOCKS_PER_SEC<<" s"<<endl;
            delete [] A; delete [] B; delete [] C;
            return 0;
    }

    反映在 cachegrind 的报告中,就是1级缓存数据命中率高一些(D1 miss rate: 0.7%)。

    ==2334== Cachegrind, a cache and branch-prediction profiler
    ==2334== Copyright (C) 2002-2017, and GNU GPL'd, by Nicholas Nethercote et al.
    ==2334== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==2334== Command: ./a.out
    ==2334== 
    --2334-- warning: L3 cache found, using its data for the LL simulation.
    202.343 s
    ==2334== 
    ==2334== I   refs:      31,053,190,658
    ==2334== I1  misses:             1,974
    ==2334== LLi misses:             1,926
    ==2334== I1  miss rate:           0.00%
    ==2334== LLi miss rate:           0.00%
    ==2334== 
    ==2334== D   refs:      17,025,701,233  (15,018,537,423 rd   + 2,007,163,810 wr)
    ==2334== D1  misses:       125,517,445  (   125,140,099 rd   +       377,346 wr)
    ==2334== LLd misses:       125,510,970  (   125,134,429 rd   +       376,541 wr)
    ==2334== D1  miss rate:            0.7% (           0.8%     +           0.0%  )
    ==2334== LLd miss rate:            0.7% (           0.8%     +           0.0%  )
    ==2334== 
    ==2334== LL refs:          125,519,419  (   125,142,073 rd   +       377,346 wr)
    ==2334== LL misses:        125,512,896  (   125,136,355 rd   +       376,541 wr)
    ==2334== LL miss rate:             0.3% (           0.3%     +           0.0%  )

    在加上 valgrind 以后,两段代码的运行时间分别是 276.428s 和 202.342s。不加 valgrind 命令,两段代码的运行时间分别是 24.0162 s 和 7.99471 s。所以报告中 D1 miss rate 的 10% 的差别(此外几乎没有别的差别,LL refs 差一个数量级,但是 LL misses 数量差不多),会导致几倍的效率区别。这说明 cpu 计算的任务远没有那 10% 的 D1 miss 导致的多余任务。

    关于电脑的缓存,cpu 需要数据的时候,会依次在如下单元中寻找 1级缓存 -> 2级缓存 -> ... -> 最后一级缓存 -> 内存。如果在 1级缓存中找到了就停止寻找,拿去用了,找的深度越大,时间成本越高。如果最后要到内存中找(缓存未命中),就一次取一个“数据块”,存到缓存里,如果下次找的数据在同一个数据块中,就可以节省时间成本。所以,缓存命中率越高,程序性能越好,所以 memory locality 非常重要。

  • 相关阅读:
    倚天
    第5課 森さんは7時に起きます。
    第1課 李さんは中国人です
    一个整体的规划
    こんにちは
    原始凭证
    第3課 ここはデパートです
    ERP术语
    第2課 これはほんです
    vc 问题总结
  • 原文地址:https://www.cnblogs.com/luyi07/p/12725565.html
Copyright © 2020-2023  润新知