在 C++ 中分析函数

Posted

技术标签:

【中文标题】在 C++ 中分析函数【英文标题】:Profiling a function in c++ 【发布时间】:2014-03-14 18:45:37 【问题描述】:

我有兴趣在我用 c++ 编写并在 linux 上运行的程序中查找特定函数的内存访问次数。为了找到内存访问的数量,我正在使用 Valgrind 的 cachegrind。我使用以下命令来获取内存访问:

cg_annotate --show=Dr,Dw cachegrind.out.25329  |tee log.txt

我的那个函数的内存访问次数是这样的:

  379,010,475   697,368,671  ???:CheckInput(std::string)

现在基本上我有三个函数,我想根据内存访问次数对这三个函数进行比较。现在我想澄清一下,这是进行比较的正确方法吗?我需要获取平均内存访问次数还是每个函数只读取一次总内存访问就足够了?其次,我可以断定内存访问次数(内存读取+内存写入)较少的那个是快速函数吗?

【问题讨论】:

查看英特尔的 Pin 工具,它是一种在程序中添加动态检测的方法,您可以通过这种方式监控所有内存访问(作为检测代码的回调)。 software.intel.com/en-us/articles/pintool 看看kcachegrind,它会让你的工作更轻松。 @amdn 几个月前我使用了 pinatrace,但它会生成一个包含整个程序所有读写操作的巨大文件,但我想为我的程序中的一个特定功能找到它。可以请在这方面提供任何帮助。 @Zara 您必须修改 pinatrace (github.com/jingpu/pintools/blob/master/source/tools/…),以便在 PIN_StartProgram() 之前使用 PIN_InitSymbols() 获取函数名称,然后使用 RTN_AddInstrumentFunction() 仅挂钩您想要的函数。我自己没有这样做,但阅读我理解的文档 - software.intel.com/sites/landingpage/pintool/docs/49306/Pin/… 【参考方案1】:

查看 cachegrind 并不是单独确定函数性能的好方法。这样的测试不能很好地表明函数在实际使用中在分支预测和缓存命中率等方面的表现。

Cachegrind 通常可以告诉您为什么给定的实现在实践中很慢,但您需要在整个二进制/数据的代表性执行上运行它。

还有几点需要注意:

原始 dr/dw 不能很好地代表性能,因为它们不会告诉您有关缓存命中率的任何信息。在其他条件相同的情况下,从 L1 缓存读取 1000 个值的函数将比从内存中读取单个值的函数更快,这会导致页面错误,并且必须从虚拟内存中加载页面。

您不会看到任何有关失败的分支预测的信息。在其他条件相同的情况下,在分支预测上表现不佳的函数将比在分支预测上表现良好的等效函数慢得多。

编辑 ----------------------------------

由于你没有提供任何细节,我不知道你在做什么。但是假设您编写了这样的测试:

for (int i = 0; i < 100000; ++i) 
   func1("test string");

for (int i = 0; i < 100000; ++i) 
   func2("test string");

这并不代表实际程序将如何使用此功能(因此我所说的使用代表性数据)。正因为如此,这个测试是毫无价值的。这是一个“微基准”。第一次通过函数时,所有内容都适合缓存,并且分支预测应该比实际使用情况要好得多,因为您总是使用相同的输入。

要编写适当的性能测试,问问自己“我将如何在我的应用程序中使用此功能”,然后编写测试来模仿它。更好的是,实际分析应用程序中的功能。没有申请?那么你优化得太快了(除非你的兴趣纯粹是学术性的)。

由于我在原始答案中指出的原因,内存访问的原始计数不会告诉您函数的性能。部分原因是并非所有内存访问都是平等创建的。根据从何处读取内存,访问时间(Approximate cost to access various caches and main memory?)存在数量级差异。除此之外,还有更多的事情不仅仅是内存访问。您可以编写一个完全对寄存器中存储的内容执行数十亿次操作的函数。

您似乎非常关注内存访问...您是否尝试过阅读一般分析?

【讨论】:

你能解释一下吗,“你需要在你的整个二进制/数据的代表执行中运行它。”。其次,在内存访问的基础上,我还能做些什么来比较三个函数? 他在哪里声明他是在孤立地分析这些功能,而不是在他的实际应用程序中? 这是我从他们的帖子和后续问题中得到的印象。至少他们想知道为什么它会有所作为。 OP 在哪里声称他们是“他”? @patros 让我再次清除我的场景。我有三个应用程序代码。每个应用程序都有一个名为 CheckInput() 的函数。这个 CheckInput 函数在每个应用程序中执行不同的算法。所以,我很感兴趣的是哪个应用程序的 CheckInput 函数会在更少的内存访问中完成它的工作。 @patros 我从倒数第二段中明白了你的观点,从哪里访问数据非常重要。您能否提及我可以使用哪些其他指标来检查这三个功能的性能?

以上是关于在 C++ 中分析函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Javascript 中分析异步函数

如何在 PostgreSQL 9.2 中分析 plpgsql 函数

如何在 R 中分析和优化已经快速的代码

如何分析 Rcpp 代码(在 linux 上)

在 Django 中分析视图的最佳方法是啥?

如何在 Python 中分析内存使用情况?