我正在尝试将一些性能工程技术应用于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) 我有一个执行指针追踪的程序,我正在尝试尽可能地优化指针追踪循环。我注意到perf record检测到函数中大约 20% 的执行时间myFunction()用于执行跳转指令(用于在读取特定值后退出循环)。
需要注意的一些事项:
__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 报告的是剩余周期的很大一部分用于执行跳转。
我怀疑通过了解用于执行这些指令的微操作,我可以更好地了解这些成本,但我对从哪里开始有点迷茫。
我很难解释英特尔性能事件报告。
\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}\nRun Code Online (Sandbox Code Playgroud)\n我用gcc -O2以下命令编译它并运行perf:
#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)