例如:
一个) int [x][y][z]
VS
b) int[x*y*z]
最初我认为我会选择a)以简化
我知道Java不像C那样在内存中线性存储数组.但这对我的计划有什么影响?
我用Java编写了两个矩阵类,只是为了比较矩阵乘法的性能.一个类(Mat1)存储矩阵double[][] A
行所在的成员.其他类(MAT2)存储和其中是的转置.i
A[i]
A
T
T
A
假设我们有一个方矩阵M,我们想要它的乘积M.mult(M)
.打电话给产品P
.
当M是Mat1实例时,使用的算法是直截了当的:
P[i][j] += M.A[i][k] * M.A[k][j]
for k in range(0, M.A.length)
Run Code Online (Sandbox Code Playgroud)
在M是我使用的Mat2的情况下:
P[i][j] += M.A[i][k] * M.T[j][k]
Run Code Online (Sandbox Code Playgroud)
这是相同的算法,因为T[j][k]==A[k][j]
.在1000x1000矩阵上,第二个算法在我的机器上花费大约1.2秒,而第一个算法花费至少25秒.我期待第二个更快,但不是这么多.问题是,为什么这么快?
我唯一的猜测是第二个更好地利用了CPU缓存,因为数据以大于1个字的块的形式被拉入缓存,第二个算法通过仅遍历行来获益,而第一个算法忽略了拉入的数据缓存通过立即到达下面的行(在内存中大约1000个字,因为数组以行主要顺序存储),没有缓存的数据.
我问了一个人,他认为这是因为更友好的内存访问模式(即第二个版本会导致更少的TLB软故障).我根本没有想到这一点,但我可以看到它如何导致更少的TLB故障.
那么,这是什么?还是有其他原因导致性能差异?
我有一个二维数组,我需要顺时针旋转90度,但我不断得到arrayindexoutofbounds ...
public int[][] rorateArray(int[][] arr){
//first change the dimensions vertical length for horizontal length
//and viceversa
int[][] newArray = new int[arr[0].length][arr.length];
//invert values 90 degrees clockwise by starting from button of
//array to top and from left to right
int ii = 0;
int jj = 0;
for(int i=0; i<arr[0].length; i++){
for(int j=arr.length-1; j>=0; j--){
newArray[ii][jj] = arr[i][j];
jj++;
}
ii++;
}
return newArray;
}
Run Code Online (Sandbox Code Playgroud)