perf でアプリケーションのプロファイリングをする方法。
perf は Linux システム全体をモニタリングするのに使えるが、アプリケーションのプロファイリングにも使える。 アプリケーションのプロファイリングに特化したツールではないのでその目的では多少使いづらい(個人の感想です)が、Linux システムやCPUレベルでのプロファイリングもできるので、見ようと思ったらより詳細も見れるという意味で重宝する。
perf record & report
$ perf record python test.py
$ perf report
Samples: 3K of event 'cycles:pp', Event count (approx.): 750316952649597
Overhead Command Shared Object Symbol
18.02% python libopenblasp-r0.2.20.so [.] sgemm_kernel_HASWELL
7.47% python libopenblasp-r0.2.20.so [.] sgemm_beta_HASWELL
5.57% python [unknown] [.] 0xffffffff8184470a
? でヘルプを見れるが、カーソルキーで上下移動ができて、 a
を押すとアセンブリが見れる。どこで負荷がかかったのか割合もみれる。
sgemm_beta_HASWELL /home/sonots/miniconda3/envs/myenv/lib/libopenblasp-r0.2.20.so
│ ↓ jle 1b0
│ test %rsi,%rsi
│ ↓ jle 1b0
│ ucomis %xmm1,%xmm0
│ ↓ jne b0
│ nop
│ 30: mov %rdx,%r8
0.67 │ lea (%rdx,%rcx,4),%rdx
│ mov %rdi,%rax
0.67 │ sar $0x3,%rax
│ ↓ jle 80
│ 40: movss %xmm0,(%r8)
│ movss %xmm0,0x4(%r8)
│ movss %xmm0,0x8(%r8)
│ movss %xmm0,0xc(%r8)
│ movss %xmm0,0x10(%r8)
│ movss %xmm0,0x14(%r8)
│ movss %xmm0,0x18(%r8)
│ movss %xmm0,0x1c(%r8)
│ add $0x20,%r8
│ dec %rax
│ ↑ jg 40
│ nop
│ 80: mov %rdi,%rax
0.67 │ and $0x7,%rax
│ ↓ jle a0
1.34 │ nop
82.55 │ 90: movss %xmm0,(%r8)
13.42 │ add $0x4,%r8
d
で DSO (Shared Object) の絞込みができて、たとえば python を除いて特定の .so だけに絞り込んで見たい時に使える。
Overhead Comman Symbol
18.02% python [.] sgemm_kernel_HASWELL
7.47% python [.] sgemm_beta_HASWELL
2.78% python [.] blas_thread_server
0.00% python [.] sgemm_oncopy_HASWELL
0.00% python [.] inner_thread
perf mem record & peport
$ perf mem record python test.py
$ perf mem report
メモリアクセスに関して見れる。操作性はほぼ同じ。
Samples: 3K of event 'cycles:pp', Event count (approx.): 3446
Overhead Samples Local Weight Memory access Symbol
9.26% 319 1 N/A [.] sgemm_kernel_HASWELL
6.62% 228 1 N/A [k] 0xffffffff81064508
4.03% 139 1 N/A [k] 0x00007f6b6ec217f5
3.92% 135 1 N/A [.] 0xffffffff8184470a
2.84% 98 1 N/A [.] pthread_mutex_lock
a
で sgemm_kernel を掘った様子
│ lea 0x80(%rsp),%rsi
│ mov %r12,%rax
0.31 │ shl $0x2,%rax
│ lea (%r8,%rax,4),%rbp
│ mov %rbp,%r8
│ mov %r12,%rax
│ nop
3.45 │ c0: vmovup (%rdi),%xmm0
6.27 │ vmovsd 0x0(%rbp),%xmm1
2.19 │ vmovup %xmm0,(%rsi)
1.25 │ vmovsd %xmm1,0x10(%rsi)
0.31 │ add $0x10,%rdi
│ add $0x10,%rbp
1.88 │ add $0x18,%rsi
0.31 │ dec %rax
1.57 │ ↑ jne c0
perf record -g & report -g
-g
オプションをつけると call graph を見れる。 record 時に -g
をつけていれば、report ではつけても付けなくても良い。
$ perf record -g python test.py
$ perf report
左側に +
マークが出てるので、カーソルキー↑↓で選択して、Enter を押すと展開される。
- 18.92% 18.92% python libopenblasp-r0.2.20.so [.] sgemm_kernel_HASWELL
+ 18.92% 0x3f8000003f800000
- 0.00% sgemm_kernel_HASWELL
- 0.00% 0xffffffff818451a5
0xffffffff81003c16
0xffffffff810031f2
0xffffffff81840585
0xffffffff8183fed6
- 0xffffffff810a9d6e
- 0xffffffff81181aea
0xffffffff8117f8de
0xffffffff8117cb07
0xffffffff81006e41
0xffffffff8100af30
0xffffffff8100aebd
0xffffffff81064508
0.00% 0xffffffff81064508
+ 6.24% 6.24% python libopenblasp-r0.2.20.so [.] sgemm_oncopy_HASWELL
+ 0.00% 0.00% python libopenblasp-r0.2.20.so [.] sgemm_beta_HASWELL
?
で出てくるヘルプに書いてあるが、E
を押すと全展開、C
を押すと全部閉じられる。
$ perf report --stdio
とすると、全展開した状態で出力することもできる。
26.80% 0.00% python [unknown] [.] 0x3f8000003f800000
|
---0x3f8000003f800000
|
|--18.92%-- sgemm_kernel_HASWELL
| |
| |--0.00%-- 0xffffffff818451a5
| | 0xffffffff81003c16
| | 0xffffffff810031f2
| | 0xffffffff81840585
| | 0xffffffff8183fed6
| | 0xffffffff810a9d6e
| | |
| | --0.00%-- 0xffffffff81181aea
| | 0xffffffff8117f8de
| | 0xffffffff8117cb07
| | 0xffffffff81006e41
| | 0xffffffff8100af30
| | 0xffffffff8100aebd
| | 0xffffffff81064508
| |
| --0.00%-- 0xffffffff81064508
|
|--6.24%-- sgemm_oncopy_HASWELL