我正在处理具有以下特征的2D数组:
const int cols = 500;
const int rows = 100;
int arr[rows][cols];
我按以下方式访问数组arr来做一些工作:
for(int k = 0; k < T; ++k) { // for each trainee
myscore[k] = 0;
for(int i = 0; i < cols; ++i) { // for each sample
for(int j = 0; j < rows; ++j) { // for each expert
myscore[k] += delta(i, anotherArray[k][i], arr[j][i]);
}
}
}
所以我担心数组'arr'而不是另一个。我需要让它更加缓存,并提高速度。我想也许可以调换阵列,但我不知道该怎么做。我的实现结果只适用于方形矩阵。我如何使其适用于非方形矩阵?
另外,将2D阵列映射到1D阵列会提升性能吗?如果是这样,我该怎么做?最后,关于我如何优化这一点的任何其他建议...我已经没有想法,但我知道arr [j] [i]是我需要进行更改的地方因为我正在访问列列而不是行,所以根本不是缓存友好。
谢谢, 赫里斯托斯
答案 0 :(得分:2)
一般in-place matrix transposition 非常很难,但是如果你把它转移到另一个数组就好了,那就很简单了。
const int cols = 500;
const int rows = 100;
int arr[rows][cols];
// fill arr[][]
int arrT[cols][rows];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
arrT[c][r] = arr[r][c];
}
}
当然,根据您获得arr[][]
的方式,您可以直接填写arrT[][]
。
但是,可能有一种更简单的简单交换循环顺序的解决方案。
for(int k = 0; k < T; ++k) { // for each trainee
myscore[k] = 0;
for(int j = 0; j < rows; ++j) { // for each expert
for(int i = 0; i < cols; ++i) { // for each sample
myscore[k] += delta(i, anotherArray[k][i], arr[j][i]);
}
}
}
答案 1 :(得分:2)
是的,1d应该比2d快。 C和C ++数组总是1d(内部)。 当你打电话给
时array[row][col]
编译器实际计算
col + row * maxcols
并将其用作1d数组的实际索引。你不妨自己这样做。循环通过整个阵列会更快,随机访问将与2d阵列一样快。
答案 2 :(得分:1)
for(int i = 0; i < N; ++i) { // for each sample
for(int j = 0; j < E[i]; ++j) { // for each expert
... arr[j][i] ... // each ++j causes a large stride => poor caching
}
}
转置循环:
for(int j = 0; j < E[i]; ++j) { // for each expert
for(int i = 0; i < N; ++i) { // for each sample
... arr[j][i] ... // each ++i looks to the next word in memory => good
}
}
当然,如果没有看到程序中的其他内容,我不能说这是否会导致问题。如果delta
没有副作用,你应该没事。
答案 3 :(得分:0)
您希望内存访问是相邻的。在您的情况下,只需在访问arr时交换I和j。