我试图弄清楚为什么修改后的C程序比未修改的计数器部分运行得更快(我添加了很少的代码行来执行一些额外的工作).在这种情况下,我怀疑" 缓存效应 "是主要的解释(指令缓存).因此,我到达perf(https://perf.wiki.kernel.org/index.php/Main_Page)分析工具,但遗憾的是我无法理解其有关缓存未命中的输出的含义.
提供了几个关于缓存的事件:
cache-references [Hardware event]
cache-misses [Hardware event]
L1-dcache-loads [Hardware cache event]
L1-dcache-load-misses [Hardware cache event]
L1-dcache-stores [Hardware cache event]
L1-dcache-store-misses [Hardware cache event]
L1-dcache-prefetches [Hardware cache event]
L1-dcache-prefetch-misses [Hardware cache event]
L1-icache-loads [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
L1-icache-prefetches [Hardware cache event]
L1-icache-prefetch-misses [Hardware cache event]
LLC-loads [Hardware cache event]
LLC-load-misses [Hardware cache event]
LLC-stores [Hardware cache event]
LLC-store-misses [Hardware cache event]
LLC-prefetches [Hardware cache event]
LLC-prefetch-misses [Hardware cache event]
dTLB-loads [Hardware cache event] …Run Code Online (Sandbox Code Playgroud) 我正在开发一个项目,我们必须实现一个在理论上被证明是缓存友好的算法.简单来说,如果N是输入,并且B是每次我们有高速缓存未命中时在高速缓存和RAM之间传输的元素数,则该算法将需要O(N/B)访问RAM.
我想表明这确实是实践中的行为.为了更好地理解如何测量各种缓存相关的硬件计数器,我决定使用不同的工具.一个是Perf,另一个是PAPI库.不幸的是,我使用这些工具越多,我就越不了解他们的确切做法.
我正在使用Intel(R)Core(TM)i5-3470 CPU @ 3.20GHz,8 GB RAM,L1缓存256 KB,L2缓存1 MB,L3缓存6 MB.缓存行大小为64字节.我猜这必须是块的大小B.
我们来看下面的例子:
#include <iostream>
using namespace std;
struct node{
int l, r;
};
int main(int argc, char* argv[]){
int n = 1000000;
node* A = new node[n];
int i;
for(i=0;i<n;i++){
A[i].l = 1;
A[i].r = 4;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
每个节点需要8个字节,这意味着一个缓存行可以容纳8个节点,所以我应该期待大约1000000/8 = 125000L3缓存未命中.
没有优化(否-O3),这是perf的输出:
perf stat -B -e cache-references,cache-misses ./cachetests
Performance counter stats for …Run Code Online (Sandbox Code Playgroud)