GCC Profile

Table of Contents

1. GCC Profile

GCC 和 profile 相关的选项有两个:

  • -fprofile-generate
  • -pg

-fprofile-generate 与下列优化有关:

  1. branch prediction
  2. hot/cold
  3. prefetch
  4. 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 的原理:

  1. gprof 能记录函数的调用关系, 实现方法是在每个函数的开头插入一个 mcount 函数的调用, 后者会记录调用关系和调用次数
  2. 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 (GCC > Profile): Profile

GCC Pass (GCC Pass > tree pass > pass_profile): pass_profile

GCC Prefetch (GCC Prefetch): 2) 使用 profile 进行 auto prefetch

Author: [email protected]
Date: 2022-04-15 Fri 18:44
Last updated: 2024-01-10 Wed 14:33

知识共享许可协议