我有两个数组:A有N_A个随机整数,B有N_B随机整数,在0和(N_A – 1)之间.我在下面的循环中使用B中的数字作为A的索引: for(i = 0; i N_B; i++) { sum += A[B[i]];} 在Intel i7-3770上进行试验,N_A = 2.56亿,
for(i = 0; i < N_B; i++) { sum += A[B[i]]; }
在Intel i7-3770上进行试验,N_A = 2.56亿,N_B = 6400万,此循环仅需0.62秒,这对应于约9纳秒的存储器访问延迟.
由于这个延迟太小,我想知道硬件预取器是否正在发挥作用.有人可以提供解释吗?
CPU在指令流中向前充电,并将同时处理多个未完成的负载.流看起来像这样:load b[0] load a[b[0]] add loop code load b[1] load a[b[1]] add loop code load b[1] load a[b[1]] add loop code ...
迭代仅由循环代码序列化,循环代码快速运行.所有负载可以同时运行. Concurrency is just limited by how many loads the CPU can handle.
我怀疑你想要对随机,不可预测,序列化的内存负载进行基准测试.这在现代CPU上实际上非常难.尝试引入一个牢不可破的依赖链:
int lastLoad = 0; for(i = 0; i < N_B; i++) { var load = A[B[i] + (lastLoad & 1)]; //be sure to make A one element bigger sum += load; lastLoad = load; }
这需要执行最后一次加载,直到可以计算下一次加载的地址.