Eli*_*ias 5 profiling g++ gprof
我正在尝试使用gprof来分析我正在开发的一些数字代码,但是gprof似乎无法从我的程序中收集数据.这是我的命令行:
g++ -Wall -O3 -g -pg -o fftw_test fftw_test.cpp -lfftw3 -lfftw3_threads -lm && ./fftw_test
Run Code Online (Sandbox Code Playgroud)
gmon.out文件已创建,但似乎没有数据.当我跑
gprof -b fftw_test gmon.out > gprof.out
Run Code Online (Sandbox Code Playgroud)
我得到的只是
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
Call graph
granularity: each sample hit covers 2 byte(s) no time propagated
index % time self children called name
Index by function name
Run Code Online (Sandbox Code Playgroud)
任何见解?
代码做了很多东西,它不只是调用FFTW例程.它具有计算某些复系数的函数,通过这些系数乘以输入数据的函数,等等.
编辑:包括示例代码和结果.
#include <cstdlib>
#include <ctime>
int main()
{
std::srand( std::time( 0 ) );
double sum = 0.0;
for ( int i = 0; i < RAND_MAX; ++i )
sum += std::rand() / ( double ) RAND_MAX;
std::cout << sum << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
命令行:
$ g++ -Wall -O3 -g -pg -o gprof_test gprof_test.cpp && ./gprof_test
1.07374e+09
$ gprof -b gprof_test gmon.out > gprof.out
$ cat gprof.out
Run Code Online (Sandbox Code Playgroud)
结果:
Flat profile:
Each sample counts as 0.01 seconds.
no time accumulated
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
Call graph
granularity: each sample hit covers 2 byte(s) no time propagated
index % time self children called name
Index by function name
Run Code Online (Sandbox Code Playgroud)
就是这样.
gprof 似乎无法从我的程序中收集数据。这是我的命令行:
Run Code Online (Sandbox Code Playgroud)g++ -Wall -O3 -g -pg -o fftw_test fftw_test.cpp -lfftw3 -lfftw3_threads -lm && ./fftw_test
您的程序使用 fftw 库,并且可能几乎仅包含 fftw 库调用。运行时间是多少?您的程序可能太快而无法使用 gprof 进行分析。更新gprof 可能看不到库,因为它是在没有启用 gprof 分析的情况下编译的。
GNU gprof 有两个部分。首先,它在使用选项编译的 c/cpp 文件中检测函数调用-pg(使用 mcount 函数调用 - https://en.wikipedia.org/wiki/Gprof) - 以获取调用者/被调用者信息。其次,它将额外的分析库链接到可执行文件中,以添加定期采样来查找哪些代码执行时间更长。采样是通过 profile (setitimer) 完成的。Setitimer 分析的分辨率有限,无法解析小于 10 ms 或 1 ms(每秒 100 或 1000 个样本)的间隔。
在您的示例中,fftw 库可能是在没有仪器的情况下编译的,因此mcount其中没有调用。它仍然可以通过采样部分捕获,但仅限于程序的主线程(https://en.wikipedia.org/wiki/Gprof - “通常它只分析应用程序的主线程”)。
perf探查器没有仪器mcount(当使用选项记录时,它从堆栈展开中获取被调用者/调用者-g),但它有更好的统计/采样变体(它可以使用硬件 PMU 计数器),没有 100 或 1000 Hz 限制,并且它支持(配置文件) 螺纹正确。尝试perf record -F1000 ./fftw_test(使用 1 kHz 采样频率)和perf report或perf report > report.txt。还有一些 GUI/HTML 前端可以执行:https://github.com/KDAB/hotspot https://github.com/jrfonseca/gprof2dot
要获得更好的 setitimer 风格分析器,请检查 google-perftools https://github.com/gperftools/gperftools中的“CPU PROFILER”。
======
通过您的测试,我在 Debian 8.6 Linux 内核版本 3.16.0-4-amd64 x86_64 机器上得到了一些 gprof 结果,g++ (Debian 4.9.2-10),gprof 是“GNU gprof (GNU Binutils for Debian) 2.27”
$ cat gprof_test.cpp
#include <cstdlib>
#include <ctime>
#include <iostream>
int main()
{
std::srand( std::time( 0 ) );
double sum = 0.0;
for ( int i = 0; i < 100000000; ++i )
sum += std::rand() / ( double ) RAND_MAX;
std::cout << sum << '\n';
return 0;
}
$ g++ -Wall -O3 -g -pg -o gprof_test gprof_test.cpp && time ./gprof_test
5.00069e+06
real 0m0.992s
$ gprof -b gprof_test gmon.out
Flat profile:
Each sample counts as 0.01 seconds.
no time accumulated
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
0.00 0.00 0.00 1 0.00 0.00 _GLOBAL__sub_I_main
Run Code Online (Sandbox Code Playgroud)
因此,gprof 在这个 1 秒示例中没有捕获任何时间样本,并且没有有关调用库的信息(它们是在没有 的情况下编译的-pg)。添加一些包装器函数并禁止内联优化后,我从 gprof 获得了一些数据,但未考虑库时间(它看到 2 秒运行时间为 0.72 秒):
$ cat *cpp
#include <cstdlib>
#include <ctime>
#include <iostream>
int rand_wrapper1()
{
return std::rand();
}
int rand_scale1()
{
return rand_wrapper1() / ( double ) RAND_MAX;
}
int main()
{
std::srand( std::time( 0 ) );
double sum = 0.0;
for ( int i = 0; i < 100000000; ++i )
sum+= rand_scale1();
// sum += std::rand() / ( double ) RAND_MAX;
std::cout << sum << '\n';
return 0;
}
$ g++ -Wall -O3 -fno-inline -g -pg -o gprof_test gprof_test.cpp && time ./gprof_test
real 0m2.345s
$ gprof -b gprof_test gmon.out
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
80.02 0.57 0.57 rand_scale1()
19.29 0.71 0.14 100000000 1.37 1.37 rand_wrapper1()
2.14 0.72 0.02 frame_dummy
0.00 0.72 0.00 1 0.00 0.00 _GLOBAL__sub_I__Z13rand_wrapper1v
0.00 0.72 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int) [clone .constprop.0]
Call graph
granularity: each sample hit covers 2 byte(s) for 1.39% of 0.72 seconds
index % time self children called name
<spontaneous>
[1] 97.9 0.57 0.14 rand_scale1() [1]
0.14 0.00 100000000/100000000 rand_wrapper1() [2]
-----------------------------------------------
0.14 0.00 100000000/100000000 rand_scale1() [1]
[2] 19.0 0.14 0.00 100000000 rand_wrapper1() [2]
Run Code Online (Sandbox Code Playgroud)
perf 可以看到所有部分:
$ perf record ./gprof_test
0
[ perf record: Woken up 2 times to write data ]
[ perf record: Captured and wrote 0.388 MB perf.data (~16954 samples) ]
$ perf report |more
# Samples: 9K of event 'cycles'
# Event count (approx.): 7373484231
#
# Overhead Command Shared Object Symbol
# ........ .......... ................. .........................
#
25.91% gprof_test gprof_test [.] rand_scale1()
21.65% gprof_test libc-2.19.so [.] __mcount_internal
13.88% gprof_test libc-2.19.so [.] _mcount
12.54% gprof_test gprof_test [.] main
9.35% gprof_test libc-2.19.so [.] __random_r
8.40% gprof_test libc-2.19.so [.] __random
3.97% gprof_test gprof_test [.] rand_wrapper1()
2.79% gprof_test libc-2.19.so [.] rand
1.41% gprof_test gprof_test [.] mcount@plt
0.03% gprof_test [kernel.kallsyms] [k] memset
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2460 次 |
| 最近记录: |