如何找到在Linux上运行的C++应用程序中运行缓慢的代码区域?
当前回答
还值得一提的是
HPC工具包(http://hpctoolkit.org/)-开源,适用于并行程序,并具有一个GUI,可通过该GUI以多种方式查看结果英特尔VTune(https://software.intel.com/en-us/vtune)-如果你有英特尔编译器,这很好τ(http://www.cs.uoregon.edu/research/tau/home.php)
我使用过HPCToolkit和VTune,它们在寻找帐篷中的长极点方面非常有效,并且不需要重新编译代码(除了必须在CMake中使用-g-O或RelWithDebInfo类型的内置来获得有意义的输出)。我听说TAU的能力类似。
其他回答
这是对Nazgob Gprof回答的回应。
过去几天我一直在使用Gprof,已经发现了三个重要的限制,其中一个是我在其他地方还没有看到过的:
它不能在多线程代码上正常工作,除非您使用变通方法调用图被函数指针弄糊涂了。示例:我有一个名为multithread()的函数,它使我能够在指定的数组上对指定的函数进行多线程处理(两者都作为参数传递)。然而,Gprof将所有对多线程()的调用视为等效的,以计算在孩子身上花费的时间。由于我传递给多线程()的一些函数花费的时间比其他函数长得多,所以我的调用图基本上是无用的。(对于那些想知道线程是否是这里的问题的人来说:不,多线程()可以选择,在这种情况下,只在调用线程上按顺序运行所有内容)。这里说“……调用数数字是通过计数而不是采样得出的。它们是完全准确的……”。然而,我发现我的调用图给了我5345859132+784984078作为对我调用最多的函数的调用统计数据,其中第一个数字应该是直接调用,第二个递归调用(都来自它本身)。因为这意味着我有一个bug,所以我在代码中加入了长(64位)计数器,并再次运行相同的程序。我的计数:5345859132个直接调用和78094395406个自递归调用。这里有很多数字,所以我要指出,我测量的递归调用是780亿,而Gprof是7.84亿:相差100倍。两次运行都是单线程和未优化的代码,一次是编译的-g,另一次是-pg。
这是在64位Debian Lenny下运行的GNUGprof(Debian的GNUBinutils)2.18.0.20080103,如果这对任何人都有帮助的话。
较新的内核(例如最新的Ubuntu内核)附带了新的“perf”工具(apt-get-install-linux-tools)AKA perf_events。
这些都配有经典的采样分析器(手册页)以及很棒的时间图表!
重要的是,这些工具可以是系统评测,而不仅仅是进程评测-它们可以显示线程、进程和内核之间的交互,并让您了解进程之间的调度和I/O依赖关系。
您可以使用iprof库:
https://gitlab.com/Neurochrom/iprof
https://github.com/Neurochrom/iprof
它是跨平台的,允许您不实时测量应用程序的性能。您甚至可以将其与实时图表相结合。完整免责声明:我是作者。
编译和链接代码并运行可执行文件时,请使用-pg标志。执行此程序时,分析数据收集在文件a.out中。有两种不同类型的分析
1-平面轮廓:通过运行命令gprog--flat profile a.out,可以获得以下数据-该功能所花费的总时间的百分比,-在包括和排除对子函数的调用的函数中花费了多少秒,-呼叫的数量,-每次通话的平均时间。
2-图形分析使用命令gprof--graph a.out获取每个函数的以下数据,其中包括-在每个部分中,一个函数都标有索引编号。-在函数上方,有一个调用该函数的函数列表。-在函数下面,有一个函数调用的函数列表。
要获取更多信息,请查看https://sourceware.org/binutils/docs-2.32/gprof/
使用Valgrind、callgrind和kcachegrind:
valgrind --tool=callgrind ./(Your binary)
生成callgrind.out.x。使用kcachegrind读取它。
使用gprof(add-pg):
cc -o myprog myprog.c utils.c -g -pg
(对于多线程、函数指针不太好)
使用google perftools:
使用时间采样,可以发现I/O和CPU瓶颈。
英特尔VTune是最好的(出于教育目的免费)。
其他:AMD Codeanalysis(已被AMD CodeXL取代)、OProfile、“perf”工具(apt-get-install-linux工具)
推荐文章
- 什么是“参数依赖查找”(又名ADL,或“Koenig查找”)?
- 公共朋友交换成员函数
- 如何将文件指针(file * fp)转换为文件描述符(int fd)?
- 如何在Go中使用c++
- 自定义c++分配器的引人注目的例子?
- RAII和c++中的智能指针
- 如何构建和使用谷歌TensorFlow c++ api
- Linux Bash中双&和分号有什么区别?
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在SSH会话中查找客户端的IP地址
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 如何为Fedora安装g++ ?
- Std::cin输入空格?