C++ C++;功能:内存访问次数

C++ C++;功能:内存访问次数,c++,memory,memory-management,profiling,C++,Memory,Memory Management,Profiling,我想知道某个函数导致的内存访问次数。为此,我正在使用pintool。在pintool中,我使用了pinatrace,但它生成了一个巨大的文件(文件大小>534MB),包含了整个程序的所有读写操作。但我想为一个特定的函数找到它。我还没有找到这样的例子。请在这方面帮助我或提供任何有用的链接 S:我在Linux上编译我的C++程序。< /P> < P>,这是Valgrind的一部分,测量(或更确切地说,模拟)缓存访问的数量以及缓存缺失(即访问实际RAM)。查找概述 它可以输出带注释的代码版本,并逐行

我想知道某个函数导致的内存访问次数。为此,我正在使用pintool。在pintool中,我使用了pinatrace,但它生成了一个巨大的文件(文件大小>534MB),包含了整个程序的所有读写操作。但我想为一个特定的函数找到它。我还没有找到这样的例子。请在这方面帮助我或提供任何有用的链接

S:我在Linux上编译我的C++程序。< /P> < P>,这是Valgrind的一部分,测量(或更确切地说,模拟)缓存访问的数量以及缓存缺失(即访问实际RAM)。查找概述

它可以输出带注释的代码版本,并逐行输入缓存访问和缓存未命中的计数

Valgrind包含在流行操作系统的软件包管理器中,易于安装

以下是一个例子:

#include <random>
#include <vector>

int main()
{
  std::vector<int> vec;

  // Seed with a real random value, if available
  std::random_device rd;
  std::default_random_engine eng(rd());
  std::uniform_int_distribution<int> dist(1,10000);

  for (std::size_t i = 0 ; i < 1000 ; ++i)
    vec.push_back(dist(eng));

  for (auto &num : vec)
    num *= 3;

  return 0;
}
  • 在cachegrind模式下运行valgrind

    valgrind --tool=cachegrind ./test
    
  • 运行cg_注释工具:

    cg_annotate ./cachegrind.out.2543 /absolute/path/test.cpp
    
  • 这将产生:

    ==2438== Cachegrind, a cache and branch-prediction profiler
    ==2438== Copyright (C) 2002-2012, and GNU GPL'd, by Nicholas Nethercote et al.
    ==2438== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
    ==2438== Command: ./test
    ==2438== 
    --2438-- warning: L3 cache found, using its data for the L2 simulation.
    ==2438== 
    ==2438== I   refs:      1,686,675
    ==2438== I1  misses:        1,160
    ==2438== LLi misses:        1,095
    ==2438== I1  miss rate:      0.06%
    ==2438== LLi miss rate:      0.06%
    ==2438== 
    ==2438== D   refs:        676,987  (458,995 rd   + 217,992 wr)
    ==2438== D1  misses:       12,616  ( 11,023 rd   +   1,593 wr)
    ==2438== LLd misses:        6,338  (  5,272 rd   +   1,066 wr)
    ==2438== D1  miss rate:       1.8% (    2.4%     +     0.7%  )
    ==2438== LLd miss rate:       0.9% (    1.1%     +     0.4%  )
    ==2438== 
    ==2438== LL refs:          13,776  ( 12,183 rd   +   1,593 wr)
    ==2438== LL misses:         7,433  (  6,367 rd   +   1,066 wr)
    ==2438== LL miss rate:        0.3% (    0.2%     +     0.4%  )
    
    注意1:Cachegrind模拟缓存行为,因此其输出可能不完全准确。特别是,模拟只考虑您正在分析的流程;它忽略操作系统/内核活动和其他进程


    注2:Cachegrind也可能生成一个大的中间文件。因此,如果您的问题是空间需求,Cachegrind可能不是一个好的解决方案。但是,如果您的问题仅仅是输出的格式和可读性,它将有所帮助,因为cg_注释生成易于读取的输出。

    pinatrace只是一个用于跟踪每个具有mem操作数的指令的示例。 当它调用(例如)时-


    它被传递一个
    IARG_INST_PTR
    ,它是捕获指令的IP(指令指针)。如果您知道函数所在的虚拟地址范围,您只需在其中添加一个检查,如果不在该范围内,则无需打印任何内容即可返回

    我不熟悉pintool的输出格式,但我几乎可以肯定,您可以提供一些开关,这些开关产生的输出可以使用标准工具(如grep、awk等)进行解析。如果您提供示例输出,可能会有所帮助。使用nm(1)获取函数的起始地址。也许可以分解函数以获得其大小。@brianbeuning您能详细说明一下吗?在哪里使用nm(1)?有没有其他简单的方法来实现这个目标(在我的问题中提到)?取决于二进制文件中的具体内容-如果没有调试信息,那么识别此函数的唯一方法是使用其地址I使用cachegrind,在编译和链接时也使用-g,但仍然是我感兴趣的函数,它的统计信息不在那里。甚至那个函数名也不存在。可能函数是内联的。在这种情况下,您仍然可以获得函数内部调用的注释。
    ==2438== Cachegrind, a cache and branch-prediction profiler
    ==2438== Copyright (C) 2002-2012, and GNU GPL'd, by Nicholas Nethercote et al.
    ==2438== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
    ==2438== Command: ./test
    ==2438== 
    --2438-- warning: L3 cache found, using its data for the L2 simulation.
    ==2438== 
    ==2438== I   refs:      1,686,675
    ==2438== I1  misses:        1,160
    ==2438== LLi misses:        1,095
    ==2438== I1  miss rate:      0.06%
    ==2438== LLi miss rate:      0.06%
    ==2438== 
    ==2438== D   refs:        676,987  (458,995 rd   + 217,992 wr)
    ==2438== D1  misses:       12,616  ( 11,023 rd   +   1,593 wr)
    ==2438== LLd misses:        6,338  (  5,272 rd   +   1,066 wr)
    ==2438== D1  miss rate:       1.8% (    2.4%     +     0.7%  )
    ==2438== LLd miss rate:       0.9% (    1.1%     +     0.4%  )
    ==2438== 
    ==2438== LL refs:          13,776  ( 12,183 rd   +   1,593 wr)
    ==2438== LL misses:         7,433  (  6,367 rd   +   1,066 wr)
    ==2438== LL miss rate:        0.3% (    0.2%     +     0.4%  )
    
    // Print a memory read record
    VOID RecordMemRead(VOID * ip, VOID * addr)
    {
        fprintf(trace,"%p: R %p\n", ip, addr);
    }