使用 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上:
- libgoogle-perftools-dev
- google-性能工具
然后按照 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.
我正在尝试分析我的软件以对其进行优化。
我使用 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上:
- libgoogle-perftools-dev
- google-性能工具
然后按照 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.