GCC Profile
Table of Contents
1. GCC Profile
GCC 和 profile 相关的选项有两个:
-fprofile-generate
-pg
-fprofile-generate
与下列优化有关:
- branch prediction
- hot/cold
- prefetch
- coverage
-pg
则与 profiling 有关
1.1. profile guided branch prediction
profile 相关的功能主要 profile 这个 ipa pass (tree-profile.cc)
gcc 可以根据 profile 来决定 predict 的结果.
int foo(int x) { if (x > 0) { return x + 1; } else { return -x + 1; } } int main(int argc, char *argv[]) { int x = 0; for (int i = 0; i < 100000; i++) { x += foo(argc - 2); } return x; }
首先需要用 `-fprofile-generate` 编译出一个可以记录 profile 的 binary
$> riscv64-linux-gnu-gcc test.c -O0 -fprofile-generate -static
然后执行生成的 bin, 会生成 profile 数据 test.gcda, 可以执行多次以收集更多的 profile 数据
$> ./a.out $> ls a.out test.c test.gcda
最后用 `fprofile-use` 或 `fbranch-probabilities` 重新编译, gcc 会使用 test.gcda 记录的 profile 数据来做 branch prediction
$> riscv64-linux-gnu-gcc test.c -O0 -fenable-rtl-bbro -fbranch-probabilities -static -fdump-ipa-profile $> cat test.c.062i.profile ... foo (int x) { int D.1508; int _1; int _3; int _4; <bb 2> [count: 2]: if (x_2(D) > 0) goto <bb 3>; [0.00%] else goto <bb 4>; [100.00%] <--------- 这是 profile 的结果 ... $> riscv64-linux-gnu-objdum -d ./a.out 0000000000010430 <foo>: 10430: 1101 addi sp,sp,-32 10432: ec22 sd s0,24(sp) 10434: 1000 addi s0,sp,32 10436: 87aa mv a5,a0 10438: fef42623 sw a5,-20(s0) 1043c: fec42783 lw a5,-20(s0) 10440: 2781 sext.w a5,a5 10442: 00f04c63 bgtz a5,1045a <foo+0x2a> <---- 10446: 4705 li a4,1 10448: fec42783 lw a5,-20(s0) 1044c: 40f707bb subw a5,a4,a5 10450: 2781 sext.w a5,a5 10452: 853e mv a0,a5 10454: 6462 ld s0,24(sp) 10456: 6105 addi sp,sp,32 10458: 8082 ret 1045a: fec42783 lw a5,-20(s0) 1045e: 2785 addiw a5,a5,1 10460: 2781 sext.w a5,a5 10462: bfc5 j 10452 <foo+0x22>
用另一个 profile 对比一下:
$> riscv64-linux-gnu-gcc test.c -O0 -fprofile-generate -static $> rm -rf ./test.gcda $> qemu-riscv64 ./a.out 1 2 3 4 5 $> riscv64-linux-gnu-gcc test.c -O0 -fenable-rtl-bbro -fbranch-probabilities -static -fdump-ipa-profile $> cat test.c.062i.profile foo (int x) { int D.1508; int _1; int _3; int _4; <bb 2> [count: 1]: if (x_2(D) > 0) goto <bb 3>; [100.00%] <----- else goto <bb 4>; [0.00%] $> riscv64-linux-gnu-objdump -d ./a.out 0000000000010430 <foo>: 10430: 1101 addi sp,sp,-32 10432: ec22 sd s0,24(sp) 10434: 1000 addi s0,sp,32 10436: 87aa mv a5,a0 10438: fef42623 sw a5,-20(s0) 1043c: fec42783 lw a5,-20(s0) 10440: 2781 sext.w a5,a5 10442: 00f05a63 blez a5,10456 <foo+0x26> <---- 10446: fec42783 lw a5,-20(s0) 1044a: 2785 addiw a5,a5,1 1044c: 2781 sext.w a5,a5 1044e: 853e mv a0,a5 10450: 6462 ld s0,24(sp) 10452: 6105 addi sp,sp,32 10454: 8082 ret 10456: 4705 li a4,1 10458: fec42783 lw a5,-20(s0) 1045c: 40f707bb subw a5,a4,a5 10460: 2781 sext.w a5,a5 10462: b7f5 j 1044e <foo+0x1e>
另外, profile 或者 profile_estimate 并不负责移动代码, 最后需要依赖 bbro 这个 rtl pass (basic block reorder)
Backlinks
GCC Branch Prediction (GCC Branch Prediction): 3. 通过 profile
1.2. converage
gconv
1.3. profiling
gprof
https://ftp.gnu.org/old-gnu/Manuals/gprof-2.9.1/html_mono/gprof.html
$> gcc test.c -O0 -g -pg $> ./a.out $> ls a.out gmon.out test.c $> gprof ./a.out gmon.out ... Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 102.01 0.23 0.23 1 234.63 234.63 fo ...
gprof 的原理:
- gprof 能记录函数的调用关系, 实现方法是在每个函数的开头插入一个 mcount 函数的调用, 后者会记录调用关系和调用次数
- gprof 能记录函数执行的时间, 实现方法是通过 profil 这个 syscall 或某个 timer 信号来估计函数的调用时间, 例如假设 timer 每秒触发 100 次, 触发后根据当前 pc 查找对应的函数 A, 则 A 的执行时间增加 0.01 秒.
详细描述参考 https://ftp.gnu.org/old-gnu/Manuals/gprof-2.9.1/html_mono/gprof.html#SEC24
1.4. impls
TODO: pass_profile
Backlinks
GCC Pass (GCC Pass > tree pass > pass_profile): pass_profile
GCC Prefetch (GCC Prefetch): 2) 使用 profile 进行 auto prefetch