“迭代”在“性能报告-b-分支历史”中的含义(性能记录-b -g)是什么意思

时间:2018-08-01 19:26:34

标签: assembly x86 perf branch-prediction

我正在使用性能分析工具对玩具程序(选择排序)进行性能分析,我想知道性能报告输出中对应的迭代次数是什么。它显示的地址对应于内部循环和if语句。希望有人能帮忙。另外,当我在perf中使用“ -b --branch-history”时,基本的块循环列会消失。我不知道为什么。

这是我的代码中被采样的部分(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    $0x1,%eax
 83c:   89 45 f0                mov    %eax,-0x10(%rbp)
 83f:   81 7d f0 f4 01 00 00    cmpl   $0x1f4,-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    $0x1,%eax
 879:   89 45 f0                mov    %eax,-0x10(%rbp)
 87c:   e9 be ff ff ff          jmpq   83f <selection_sort+0x2f>

2 个答案:

答案 0 :(得分:2)

在Zulan的回答之外,我将尝试重申并添加更多信息。

最后分支记录(LBR)允许在可执行文件中查找热执行路径,以直接检查它们的优化机会。在性能方面,这是通过扩展调用堆栈显示机制并将最后的基本块添加到调用堆栈中来实现的,该堆栈通常用于显示函数调用的最常见层次结构。

这可以通过在perf记录中使用调用图(-g)和LBR(-b)选项以及在perf中使用-branch-history 选项来完成报告,它将最后的分支信息添加到调用图。本质上,它为8-32分支提供了某些发生原因的额外上下文。

最近perf版中的定时LBR 功能报告了每个基本块的平均周期数。

什么是迭代?

据我了解,分支历史代码具有循环检测功能。这使我们可以通过计算removed loops的数量来获得迭代次数。 仅在perf report输出中(通过直方图格式显示)通过Linux内核中的前一个commit引入了重复循环的消除。

struct iterations是有用的C结构,用于显示perf report中的迭代次数。

This是保存迭代次数的位置,以显示在perf report输出中。从save_iterations函数内部调用remove_loops函数。

在解决callchain时将删除循环。

您还可以阅读此commit,它描述了perf report如何显示在较新的Linux内核版本中引入的迭代和更改的数量。

答案 1 :(得分:1)

我从快速浏览perf源代码并提交的信息中整理信息时,会一针见血。

perf report --branch-history尝试基于跟踪中的分支记录来构建程序的控制流。这样做时,它还会检测到循环。但是,来自perf record的信息可能不完整-因此循环检测也将是错误的。

如果您的系统类似于我的系统(Haswell台式机,Linux 4.17.6),则perf可能会记录所采集的每个样本的LBR。如果此LBR包含16个最近的分支,则必须将事件周期减少到16个退休分支。即使使用convincing the kernel not to throttle recording,我也无法获得任何有意义的结果。

不幸的是,我不知道一种使用perf记录完整分支跟踪的方法。