做三个测试,都是计算 C = A * B,结果都一样,但是用的时间不一样。
在笔记本中,testIJK 用 5s 32ms,testJKI 用 15s 542ms,testKIJ 用 403 ms。可以看到,testKIJ 的 cache 命中率最高。
public class TestMemoryHierarchy {
int length = 1000;
double[][] a;
double[][] b;
double[][] c;
@BeforeClass
public void init() {
this.a = new double[this.length][this.length];
for (int i = 0; i < this.length; i++) {
for (int j = 0; j < this.length; j++) {
this.a[i][j] = i * j;
}
}
this.b = new double[this.length][this.length];
for (int i = 0; i < this.length; i++) {
for (int j = 0; j < this.length; j++) {
this.b[i][j] = i + j;
}
}
this.c = new double[this.length][this.length];
}
@Test
public void testIJK() {
for (int i = 0; i < this.length; i++) {
for (int j = 0; j < this.length; j++) {
double sum = 0.0;
for (int k = 0; k < this.length; k++) {
sum += a[i][k] * b[k][j];
}
c[i][j] = sum;
}
}
}
@Test
public void testJKI() {
for (int j = 0; j < this.length; j++) {
for (int k = 0; k < this.length; k++) {
double r = b[k][j];
for (int i = 0; i < this.length; i++) {
c[i][j] += a[i][k] * r;
}
}
}
}
@Test
public void testKIJ() {
for (int k = 0; k < this.length; k++) {
for (int i = 0; i < this.length; i++) {
double r = a[i][k];
for (int j = 0; j < this.length; j++) {
c[i][j] += b[k][j] * r;
}
}
}
}
}