相关疑难解决方法(0)

Linux perf报告缓存未命中意外指令

我正在尝试将一些性能工程技术应用于Dijkstra算法的实现.为了找到(天真的和未经优化的)程序中的瓶颈,我正在使用该perf命令来记录缓存未命中的数量.相关的代码片段如下,它找到距离最小的未访问节点:

for (int i = 0; i < count; i++) {
    if (!visited[i]) {
        if (tmp == -1 || dist[i] < dist[tmp]) {
            tmp = i;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于LLC-load-misses度量标准,perf report显示程序集的以下注释:

       ?             for (int i = 0; i < count; i++) {                                                                                                                           ?
  1.19 ? ff:   add    $0x1,%eax                                                                                                                                                  ?
  0.03 ?102:   cmp    0x20(%rsp),%eax                                                                                                                                            ?
       ?     ? jge    135                                                                                                                                                        ?
       ?                 if (!visited[i]) {                                                                                                                                      ?
  0.07 ?       movslq %eax,%rdx                                                                                                                                                  ?
       ?       mov    0x18(%rsp),%rdi                                                                                                                                            ?
  0.70 …
Run Code Online (Sandbox Code Playgroud)

linux performance caching perf

5
推荐指数
1
解决办法
1033
查看次数

为什么在执行指针追逐时这条跳转指令如此昂贵?

我有一个执行指针追踪的程序,我正在尝试尽可能地优化指针追踪循环。我注意到perf record检测到函数中大约 20% 的执行时间myFunction()用于执行跳转指令(用于在读取特定值后退出循环)。

需要注意的一些事项:

  • 指针追踪路径可以轻松放入 L1 数据缓存
  • 使用__builtin_expect以避免分支预测错误的成本没有显着影响

perf record 有以下输出:

Samples: 153K of event 'cycles', 10000 Hz, Event count (approx.): 35559166926                                                                                                                                                               
myFunction  /tmp/foobar [Percent: local hits]                                                                                                                                                                            
Percent?      endbr64                                                                                                                                                                                                                       
      ...
 80.09 ?20:   mov     (%rdx,%rbx,1),%ebx                                                                                                                                                                                                    
  0.07 ?      add     $0x1,%rax                                                                                                                                                                                                             
       ?      cmp     $0xffffffff,%ebx                                                                                                                                                                                                      
 19.84 ?    ? jne     20                                                                                                                                                                                                                    
      ...
Run Code Online (Sandbox Code Playgroud)

我希望在这个循环中花费的大部分周期都用于从内存中读取值,这是由 perf 确认的。我还希望剩余的周期在执行循环中剩余的指令时会有些均匀地花费。相反, perf 报告的是剩余周期的很大一部分用于执行跳转。

我怀疑通过了解用于执行这些指令的微操作,我可以更好地了解这些成本,但我对从哪里开始有点迷茫。

x86 assembly pointers cpu-architecture perf

2
推荐指数
1
解决办法
100
查看次数

“perf annotate”内存加载/存储时间报告不一致

我很难解释英特尔性能事件报告。

\n

考虑以下主要读/写内存的简单程序:

\n
#include <stdint.h>\n#include <stdio.h>\n\nvolatile uint32_t a;\nvolatile uint32_t b;\n\nint main() {\n  printf("&a=%p\\n&b=%p\\n", &a, &b);\n  for(size_t i = 0; i < 1000000000LL; i++) {\n    a ^= (uint32_t) i;\n    b += (uint32_t) i;\n    b ^= a;\n  }\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我用gcc -O2以下命令编译它并运行perf

\n
#include <stdint.h>\n#include <stdio.h>\n\nvolatile uint32_t a;\nvolatile uint32_t b;\n\nint main() {\n  printf("&a=%p\\n&b=%p\\n", &a, &b);\n  for(size_t i = 0; i < 1000000000LL; i++) {\n    a ^= (uint32_t) i;\n    b += (uint32_t) i;\n    b ^= a;\n  }\n …
Run Code Online (Sandbox Code Playgroud)

performance assembly x86-64 micro-optimization perf

2
推荐指数
1
解决办法
394
查看次数