【发布时间】:2015-12-22 16:43:07
【问题描述】:
我一直在测试 cpu 缓存优化,我做的一个简单测试是在嵌套循环内对一个 2048x2048 整数矩阵求和,首先我尝试使用顺序索引(总是跳转到下一个内存整数),然后使用长宽度内存访问(跳到下一个整数的第 2048 个),我将这些代码段分别运行 1000 次,然后我得到了每段代码的平均执行时间,测试是在 Intel Core 2 Duo E4600 2.4 GHz 上执行的,没有其他进程可以损害后台执行时间,结果是:
顺序索引:平均:8ms。
长宽度内存访问:平均:43。
这里是源代码:
import java.util.Arrays;
import java.util.Random;
public class Main {
public static void main(String[] args) {
int [][] matrix = new int[2048][2048];
long tInitial = 0;
long tFinal = 0;
long [] avgExecTime = new long[1000];
for (int i = 0; i < avgExecTime.length; i++) {
fillWithRandomNumbers(matrix);
tInitial = System.currentTimeMillis();
sumSequentially(matrix);
tFinal = System.currentTimeMillis();
avgExecTime[i] = tFinal - tInitial;
}
System.out.println(Arrays.stream(avgExecTime).sum() / avgExecTime.length);
for (int i = 0; i < avgExecTime.length; i++) {
fillWithRandomNumbers(matrix);
tInitial = System.currentTimeMillis();
sumRandomly(matrix);
tFinal = System.currentTimeMillis();
avgExecTime[i] = tFinal - tInitial;
}
System.out.println(Arrays.stream(avgExecTime).sum() / avgExecTime.length);
}
public static void fillWithRandomNumbers(int [][] matrix) {
Random r = new Random();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = r.nextInt();
}
}
}
public static long sumSequentially(int [][] matrix) {
long total = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
total += matrix[i][j];
}
}
return total;
}
public static long sumRandomly(int [][] matrix) {
long total = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
total += matrix[j][i];
}
}
return total;
}
}
我的问题是:
- 考虑到 sumRandomly 和 sumSequentially 最终结果相同,为什么 java 编译器没有优化 sumRandomly 方法?
- Java 编译器是否会考虑在求和发生时可能存在一个线程更改我的矩阵参数值并可能改变结果?
我已经试过不使用方法,在main方法上做所有事情,结果几乎一样。
【问题讨论】:
-
如果数组是锯齿状的,这两种方法是不等价的。