为什么我们在第一个版本中有缓存未命中?
正如奥利在评论中指出的那样。这个问题是没有根据的。如果数据已经在缓存中,则不会有缓存未命中。
除此之外,您的两个示例之间的内存访问没有区别。因此,这不太可能成为它们之间任何性能差异的一个因素。
第二版的性能确实比第一版好?为什么 ?
通常,要做的是实际测量。但在这个特定的例子中,我想说它可能会更快。不是因为更好的缓存访问,而是因为循环展开。
您正在进行的优化称为“节点拆分”,您可以在其中分离counter
变量以打破依赖链。
但是,在这种情况下,您正在执行一个简单的归约操作。许多现代编译器能够识别这种模式并为您进行这种节点拆分。
那么它更快吗?最有可能的。但是您应该检查编译器是否为您执行此操作。
郑重声明:我刚刚在 Visual Studio 2010 上对此进行了测试。
我很惊讶它无法进行此优化。
; 129 :
; 130 : int counter = 0;
; 131 :
; 132 : for (int i=0; i<n; i++)
mov ecx, DWORD PTR n$[rsp]
xor edx, edx
test ecx, ecx
jle SHORT $LN1@main
$LL3@main:
; 133 : {
; 134 : counter += myArray[i];
add edx, DWORD PTR [rax]
add rax, 4
dec rcx
jne SHORT $LL3@main
$LN1@main:
; 135 : }
对于这个(微不足道的)示例,Visual Studio 2010 似乎无法执行“节点拆分”...