使用 GPerf 工具:不工作,重定向问题?

Using GPerf Tool: not working, issue with redirection?

我正在尝试分析我的软件以对其进行优化。

我使用 gprof 和编译标志 -g -pg -O3 但结果没有给我足够的精度。

这是我的编译 Stacktrace:

$: make clean; make;

rm -f ./obj/*.o
rm -f ./bin/mdk-verifier
rm -f ./grammar/modal.output
rm -f ./grammar/modal.tab.h
rm -f ./grammar/*.cpp
rm -f ./lex.backup

bison -d -t -l -v -o ./grammar/modal.tab.c ./grammar/modal.y && mv ./grammar/modal.tab.c ./grammar/modal.tab.cpp
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./grammar/modal.tab.cpp -o ./obj/modal.tab.o
flex -l -b -o./grammar/lex.yy.cpp ./grammar/modal.lex   
g++ -O3 -g -pg -I./include -c ./grammar/lex.yy.cpp -o ./obj/lex.yy.o
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/Kripke.cc -o ./obj/Kripke.o   
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/Term.cc -o ./obj/Term.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/BooleanConstant.cc -o ./obj/BooleanConstant.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/Variable.cc -o ./obj/Variable.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/PropositionalVariable.cc -o ./obj/PropositionalVariable.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/Operation.cc -o ./obj/Operation.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/BooleanOperation.cc -o ./obj/BooleanOperation.o 
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/ModalOperation.cc -o ./obj/ModalOperation.o   
g++ -O3 -g -pg -fPIC -std=c++11  -I./include -c ./src/Formula.cc -o ./obj/Formula.o 
g++ -O3 -g -pg -fPIC -std=c++11  -o ./obj/Main.o -c ./src/Main.cc 
g++ -O3 -g -pg -static -lprofiler -o ./bin/mdk-verifier ./obj/modal.tab.o ./obj/lex.yy.o ./obj/Kripke.o ./obj/Term.o ./obj/BooleanConstant.o ./obj/PropositionalVariable.o ./obj/Variable.o ./obj/Operation.o ./obj/BooleanOperation.o ./obj/ModalOperation.o ./obj/Formula.o ./obj/Main.o               

下面是我如何调用我的程序:

$: ./bin/mdk-verifier ./problem.txt < solution.txt 

所以执行后,一切正常,我得到了一个gmon.out文件。我正在执行命令 gprof ./bin/mdk-verifier | more 并得到以下结果:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 34.00      2.13     2.13       18   118.33   118.33  ModalOperation::checkBranch(Kripke&, unsigned int)
  ...
  ...
  5.91      4.98     0.37 54684911     0.00     0.00  BooleanOperation::checkBranch(Kripke&, unsigned int)
  4.63      5.27     0.29 54684911     0.00     0.00  PropositionalVariable::checkBranch(Kripke&, unsigned int)

很明显,ModalOperation::checkBranch 的调用次数溢出了……每次我进入这个函数时都会显示,我确实调用了 18 次以上……

所以我考虑使用另一个分析器,更精确,我发现 GPerfTools Google。

我想用它,我安装在我的Ubuntu上:

然后按照 tutorial,他们让我设置环境变量 CPUPROFILE

我做到了,我得到了:

 $: env | grep "CPU"
 CPUPROFILE=./prof.out

我还在我的可执行文件的链接过程中放置​​了 -lprofiler,所以我认为一切正常,我可以开始分析文件中的数据 ./prof.out

但不幸的是,这个文件没有出现...没有创建任何内容,所以我无法分析任何内容...

有谁知道为什么没有创建 ./prof.out 文件以及为什么分析没有收集数据?

在此先感谢您的帮助!

此致;

您的目的是在您的软件中节省时间。多个问题,首先是底片:

  • -O3:编译器可以优化某些东西。它不能优化只有你能优化的东西。 可以做的是通过打乱代码使它们很难找到。使用 -O3 的时间是你找到并解决了可以解决的问题之后。

  • gprof 是可敬的,但仅此而已。它对程序计数器进行采样并对函数调用进行计数。 Here is a list of problems with that. 它确实给你一个调用图,但是 speedups can easily hide in that.

  • gperftools 更好(根据 Aliaksei 的评论修改)因为它是一个真正的堆栈采样器。通常它是一个 "CPU-profiler",在这种模式下它对阻塞所花费的任何时间都是盲目的,比如 I/O 或睡眠。但是,如果您设置环境变量 CPUPROFILE_REALTIME=1,您可以使其在挂钟时间采样,因此它会看到 I/O、睡眠和其他阻塞系统调用。 它有许多输出选项。 似乎不容易看到带有行号信息的实际堆栈样本本身的小随机选择。

现在是积极的:

  • 有一种方法(不是产品)被很多人使用,random pausing。 这个想法是用质量代替数量——在正确的时间获取堆栈样本。 在感兴趣的时间间隔内,需要的次数很少,例如 5、10 或 20。如果某件事占用了 95% 的时间,则每个堆栈样本都有 95% 的机会出现在正确的时间。 然后 检查每个堆栈样本 看看发生了什么 - 不要只是总结/积累/平均/做假装统计。 (如果这是在调试器下手动完成的,您还可以检查数据变量,从而更深入地了解程序为什么要花那个时间。) 目的是找到问题,而不是衡量问题。 任何你能看到但可以避免的事情,如果你在多个样品上看到它,将节省大量时间。 Here's how much. 您需要查看两次的样本越少,节省的就越多。 如果您想确切地看到它为您节省了什么,只需在前后使用秒表即可。 而且不要只做一次。每解决一个问题,你就会发现更多,所以如果你坚持下去,你可能会得到 dramatic speedups.