"iterations" 在 "perf report -b --branch-history" 中是什么意思(perf record -b -g)
what does "iterations" mean in "perf report -b --branch-history" (of perf record -b -g)
我正在使用 perf 分析一个玩具程序(选择排序),我想知道 iterations 在 perf 报告输出中对应什么。它显示的地址对应于内部循环和 if 语句。我希望有人能帮忙。此外,当我将“-b --branch-history”与 perf 一起使用时,基本块循环列消失了。不知道为什么。
这是我的代码被采样的部分(MAX_LENGTH 是 500):
35 // FROM: https://www.geeksforgeeks.org/selection-sort
37 void swap(int *xp, int *yp)
38 {
39 int temp = *xp;
40 *xp = *yp;
41 *yp = temp;
42 }
43
44 void selection_sort(int arr[])
45 {
46 int i, j, min_idx;
47
48 // One by one move boundary of unsorted subarray
49 for (i = 0; i < MAX_LENGTH-1; i++)
50 {
51 // Find the minimum element in unsorted array
52 min_idx = i;
53 for (j = i+1; j < MAX_LENGTH; j++)
54 if (arr[j] < arr[min_idx])
55 min_idx = j;
56
57 // Swap the found minimum element with the first element
58 swap(&arr[min_idx], &arr[i]);
59 }
60 }
编译使用(clang 版本 5.0.0):
clang -O0 -g selection_sort.c -o selection_sort_g_O0
下面是我如何调用性能记录:
sudo perf record -e cpu/event=0xc4,umask=0x20,name=br_inst_retired_near_taken,period=1009/pp -b -g ./selection_sort_g_O0
性能报告及其输出:
sudo perf report -b --branch-history --no-children
Samples: 376 of event 'br_inst_retired_near_taken', Event count (approx.): 37603384
Overhead Source:Line Symbol Shared Object ▒
+ 51.86% selection_sort_g_O0[862] [.] 0x0000000000000862 selection_sort_g_O0 ▒
- 24.47% selection_sort_g_O0[86e] [.] 0x000000000000086e selection_sort_g_O0 ▒
0x873 (cycles:1) ▒
- 0x86e (cycles:1) ▒
- 23.94% 0x86e (cycles:3 iterations:25) ▒
0x862 (cycles:3) ▒
0x83f (cycles:1) ▒
0x87c (cycles:1) ▒
0x873 (cycles:1) ▒
0x86e (cycles:1) ▒
0x86e (cycles:3) ▒
0x862 (cycles:3) ▒
0x83f (cycles:1) ▒
0x87c (cycles:1) ▒
0x873 (cycles:1) ▒
0x86e (cycles:1) ▒
0x86e (cycles:3) ▒
0x862 (cycles:3) ▒
+ 22.61% selection_sort_g_O0[87c] [.] 0x000000000000087c selection_sort_g_O0 ▒
+ 1.06% selection_sort_g_O0[8a5] [.] 0x00000000000008a5 selection_sort_g_O0
我使用 objdump 在地址和源文件行之间进行映射:
objdump -Dleg selection_sort_g_O0 > selection_sort_g_O0.s
../selection_sort.c:53
836: 8b 45 f4 mov -0xc(%rbp),%eax
839: 83 c0 01 add [=16=]x1,%eax
83c: 89 45 f0 mov %eax,-0x10(%rbp)
83f: 81 7d f0 f4 01 00 00 cmpl [=16=]x1f4,-0x10(%rbp)
846: 0f 8d 35 00 00 00 jge 881 <selection_sort+0x71>
../selection_sort.c:54
84c: 48 8b 45 f8 mov -0x8(%rbp),%rax
850: 48 63 4d f0 movslq -0x10(%rbp),%rcx
854: 8b 14 88 mov (%rax,%rcx,4),%edx
857: 48 8b 45 f8 mov -0x8(%rbp),%rax
85b: 48 63 4d ec movslq -0x14(%rbp),%rcx
85f: 3b 14 88 cmp (%rax,%rcx,4),%edx
862: 0f 8d 06 00 00 00 jge 86e <selection_sort+0x5e>
../selection_sort.c:55
868: 8b 45 f0 mov -0x10(%rbp),%eax
86b: 89 45 ec mov %eax,-0x14(%rbp)
../selection_sort.c:54
86e: e9 00 00 00 00 jmpq 873 <selection_sort+0x63>
../selection_sort.c:53
873: 8b 45 f0 mov -0x10(%rbp),%eax
876: 83 c0 01 add [=16=]x1,%eax
879: 89 45 f0 mov %eax,-0x10(%rbp)
87c: e9 be ff ff ff jmpq 83f <selection_sort+0x2f>
当我通过快速浏览 perf
源代码拼凑信息并提交时,对这个答案持保留态度。
perf report --branch-history
尝试根据跟踪中的分支记录构建程序的控制流。这样做时,它还会检测循环。但是,来自 perf record
的信息可能不完整 - 因此环路检测也会出错。
如果你的系统和我的一样(Haswell 桌面,Linux 4.17.6),perf
可能会记录 LBR for each sample taken. If this LBR contains the 16 most recent branches, you would have to decrease the event period to 16 retired branches. Even with convincing the kernel not to throttle recording,我无法取得任何有意义的结果.
不幸的是,我不知道用 perf
.
记录完整分支跟踪的方法
我会尝试重申并在 Zulan 的回答之上添加更多信息。
最后的分支记录 (LBR) 允许在可执行文件中找到热执行路径,以直接检查它们以寻找优化机会。在 perf 中,这是通过扩展调用堆栈显示机制并将最后的基本块添加到调用堆栈中来实现的,调用堆栈通常用于显示最常见的函数调用层次结构。
这可以通过在性能记录中使用 调用图 (-g) 和 LBR (-b) 选项 和 --branch-history 来完成 perf report 中的选项,它将最后一个分支信息添加到调用图中。本质上,它为 8-32 个分支提供了发生某些事情的原因的额外上下文。
最近 perf
版本中的 timed LBR 功能报告每个基本块的平均周期数。
什么是迭代?
据我了解,分支历史代码具有循环检测功能。这样我们就可以通过计算removed loops的次数来得到迭代次数。
通过 Linux 内核中的先前 commit 仅在 perf report
输出(以直方图格式显示)中引入了重复循环的删除。
struct iterations 是一个有用的 C 结构,用于显示 perf report
.
中的迭代次数
This 是保存迭代次数以显示在 perf report
输出中的位置。正在从 remove_loops
函数内部调用 save_iterations
函数。
在解析 callchain 时删除循环。
您还可以阅读此 commit,它描述了 perf report
如何显示更新的 Linux 内核版本中引入的迭代次数和更改。
我正在使用 perf 分析一个玩具程序(选择排序),我想知道 iterations 在 perf 报告输出中对应什么。它显示的地址对应于内部循环和 if 语句。我希望有人能帮忙。此外,当我将“-b --branch-history”与 perf 一起使用时,基本块循环列消失了。不知道为什么。
这是我的代码被采样的部分(MAX_LENGTH 是 500):
35 // FROM: https://www.geeksforgeeks.org/selection-sort
37 void swap(int *xp, int *yp)
38 {
39 int temp = *xp;
40 *xp = *yp;
41 *yp = temp;
42 }
43
44 void selection_sort(int arr[])
45 {
46 int i, j, min_idx;
47
48 // One by one move boundary of unsorted subarray
49 for (i = 0; i < MAX_LENGTH-1; i++)
50 {
51 // Find the minimum element in unsorted array
52 min_idx = i;
53 for (j = i+1; j < MAX_LENGTH; j++)
54 if (arr[j] < arr[min_idx])
55 min_idx = j;
56
57 // Swap the found minimum element with the first element
58 swap(&arr[min_idx], &arr[i]);
59 }
60 }
编译使用(clang 版本 5.0.0):
clang -O0 -g selection_sort.c -o selection_sort_g_O0
下面是我如何调用性能记录:
sudo perf record -e cpu/event=0xc4,umask=0x20,name=br_inst_retired_near_taken,period=1009/pp -b -g ./selection_sort_g_O0
性能报告及其输出:
sudo perf report -b --branch-history --no-children
Samples: 376 of event 'br_inst_retired_near_taken', Event count (approx.): 37603384
Overhead Source:Line Symbol Shared Object ▒
+ 51.86% selection_sort_g_O0[862] [.] 0x0000000000000862 selection_sort_g_O0 ▒
- 24.47% selection_sort_g_O0[86e] [.] 0x000000000000086e selection_sort_g_O0 ▒
0x873 (cycles:1) ▒
- 0x86e (cycles:1) ▒
- 23.94% 0x86e (cycles:3 iterations:25) ▒
0x862 (cycles:3) ▒
0x83f (cycles:1) ▒
0x87c (cycles:1) ▒
0x873 (cycles:1) ▒
0x86e (cycles:1) ▒
0x86e (cycles:3) ▒
0x862 (cycles:3) ▒
0x83f (cycles:1) ▒
0x87c (cycles:1) ▒
0x873 (cycles:1) ▒
0x86e (cycles:1) ▒
0x86e (cycles:3) ▒
0x862 (cycles:3) ▒
+ 22.61% selection_sort_g_O0[87c] [.] 0x000000000000087c selection_sort_g_O0 ▒
+ 1.06% selection_sort_g_O0[8a5] [.] 0x00000000000008a5 selection_sort_g_O0
我使用 objdump 在地址和源文件行之间进行映射:
objdump -Dleg selection_sort_g_O0 > selection_sort_g_O0.s
../selection_sort.c:53
836: 8b 45 f4 mov -0xc(%rbp),%eax
839: 83 c0 01 add [=16=]x1,%eax
83c: 89 45 f0 mov %eax,-0x10(%rbp)
83f: 81 7d f0 f4 01 00 00 cmpl [=16=]x1f4,-0x10(%rbp)
846: 0f 8d 35 00 00 00 jge 881 <selection_sort+0x71>
../selection_sort.c:54
84c: 48 8b 45 f8 mov -0x8(%rbp),%rax
850: 48 63 4d f0 movslq -0x10(%rbp),%rcx
854: 8b 14 88 mov (%rax,%rcx,4),%edx
857: 48 8b 45 f8 mov -0x8(%rbp),%rax
85b: 48 63 4d ec movslq -0x14(%rbp),%rcx
85f: 3b 14 88 cmp (%rax,%rcx,4),%edx
862: 0f 8d 06 00 00 00 jge 86e <selection_sort+0x5e>
../selection_sort.c:55
868: 8b 45 f0 mov -0x10(%rbp),%eax
86b: 89 45 ec mov %eax,-0x14(%rbp)
../selection_sort.c:54
86e: e9 00 00 00 00 jmpq 873 <selection_sort+0x63>
../selection_sort.c:53
873: 8b 45 f0 mov -0x10(%rbp),%eax
876: 83 c0 01 add [=16=]x1,%eax
879: 89 45 f0 mov %eax,-0x10(%rbp)
87c: e9 be ff ff ff jmpq 83f <selection_sort+0x2f>
当我通过快速浏览 perf
源代码拼凑信息并提交时,对这个答案持保留态度。
perf report --branch-history
尝试根据跟踪中的分支记录构建程序的控制流。这样做时,它还会检测循环。但是,来自 perf record
的信息可能不完整 - 因此环路检测也会出错。
如果你的系统和我的一样(Haswell 桌面,Linux 4.17.6),perf
可能会记录 LBR for each sample taken. If this LBR contains the 16 most recent branches, you would have to decrease the event period to 16 retired branches. Even with convincing the kernel not to throttle recording,我无法取得任何有意义的结果.
不幸的是,我不知道用 perf
.
我会尝试重申并在 Zulan 的回答之上添加更多信息。
最后的分支记录 (LBR) 允许在可执行文件中找到热执行路径,以直接检查它们以寻找优化机会。在 perf 中,这是通过扩展调用堆栈显示机制并将最后的基本块添加到调用堆栈中来实现的,调用堆栈通常用于显示最常见的函数调用层次结构。
这可以通过在性能记录中使用 调用图 (-g) 和 LBR (-b) 选项 和 --branch-history 来完成 perf report 中的选项,它将最后一个分支信息添加到调用图中。本质上,它为 8-32 个分支提供了发生某些事情的原因的额外上下文。
最近 perf
版本中的 timed LBR 功能报告每个基本块的平均周期数。
什么是迭代?
据我了解,分支历史代码具有循环检测功能。这样我们就可以通过计算removed loops的次数来得到迭代次数。
通过 Linux 内核中的先前 commit 仅在 perf report
输出(以直方图格式显示)中引入了重复循环的删除。
struct iterations 是一个有用的 C 结构,用于显示 perf report
.
This 是保存迭代次数以显示在 perf report
输出中的位置。正在从 remove_loops
函数内部调用 save_iterations
函数。
在解析 callchain 时删除循环。
您还可以阅读此 commit,它描述了 perf report
如何显示更新的 Linux 内核版本中引入的迭代次数和更改。