Cache

Cache 对循环的影响

CPU 在读取 Cache 的时候一次读取一个 Cache Line。Cache Line 常见的大小为 64 字节。在循环中步长在一个 Cache Line 中的循环对速度影响一般不大,但是对于不同行的 Cache Line 具有很大的变化。例如:

static public void main(String [] args){
int [] arr = new int[64*1024*1024];

long start1 = System.currentTimeMillis();
for(int i =0; i <arr.length; i++) arr[i] *=3;
System.out.println(System.currentTimeMillis() - start1);

long start2 = System.currentTimeMillis();
for(int i =0; i <arr.length; i+=16) arr[i] *=3;
System.out.println(System.currentTimeMillis() - start2);

long start3 = System.currentTimeMillis();
for(int i =0; i <arr.length; i+=32) arr[i] *=3;
System.out.println(System.currentTimeMillis() - start3);
}

结果是:

30
33
26

原因就是前两个循环读取的 Cache Line 数量是一样的。第三种情况理想情况下应该是少一半,这里不知道什么情况。

另外有些问题的是 C++

int  arrLen = 64 * 1024 * 1024;
int* arr    = new int[arrLen];
for(int i = 0; i < arrLen; ++i) arr[i] = 0;
auto printTime = [&](int step) {
   auto start = std::chrono::steady_clock::now();
   for(int i = 0; i < arrLen; i += step) arr[i] += 2;
   auto                          end    = std::chrono::steady_clock::now();
   std::chrono::duration<double> result = end - start;
   cout << result.count() << endl;
};
printTime(1);
printTime(2);
printTime(6);
printTime(10);
printTime(16);
printTime(32);

结果是:

0.177454
0.0971365
0.0398913
0.0338586
0.028566
0.0274254

这里和 Java 明显不同。这已经是关闭了编译器优化了。即使是清空流水线和清除 cache 也不会影响倍数关系。在我电脑上一级和二级缓存的 Cache Line 都是 64 字节

Last moify: 2023-02-04 01:03:05
Build time:2025-07-18 09:41:42
Powered By asphinx