2012-04-08 50 views
-1

考虑下面的代码:缓存未命中?我怎么能看到?

for (int i=0; i<n; i++) 
{ 
    counter += myArray[i]; 
} 

,循环展开版本:

for (int i=0; i<n; i+=4) 
{ 
    counter1 += myArray[i+0]; 
    counter2 += myArray[i+1]; 
    counter3 += myArray[i+2]; 
    counter4 += myArray[i+3]; 
} 

total = counter1+ counter2 + counter3+ counter4; 
  1. 为什么我们在第一个版本高速缓存未命中?
  2. 第二个版本的确比第一个版本有更好的表现吗?为什么?

问候

+3

是什么让你认为存在的第一个版本高速缓存未命中? – templatetypedef 2012-04-08 19:40:08

+0

我不知道还会有差别很大...... – 2012-04-08 19:40:10

+0

气味像功课太多... – m0skit0 2012-04-08 19:40:13

回答

4

为什么我们在第一个版本的高速缓存未命中?

正如奥利在评论中指出的那样。这个问题没有根据。如果数据已经在缓存中,那么将不存在缓存未命中。

除此之外,您的两个示例在内存访问方面没有区别。所以这不会成为它们之间性能差异的一个因素。

第二个版本是否确实比第一个版本有更好的性能?为什么?

通常,要做的事情是实际测量。但在这个特定的例子中,我会说它可能会更快。不是因为更好的缓存访问,而是因为循环展开。

您正在进行的优化称为“节点分割”,您将分割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 [email protected] 
[email protected]: 

; 133 :  { 
; 134 :   counter += myArray[i]; 

    add edx, DWORD PTR [rax] 
    add rax, 4 
    dec rcx 
    jne SHORT [email protected] 
[email protected]: 

; 135 :  } 

Visual Studio 2010中似乎没有能够为这个(简单)例如进行“节点分离”的...

相关问题