C++ 将[i][j]更改为[j][i]时,通过矩阵的迭代速度较慢
我有一个名为C++ 将[i][j]更改为[j][i]时,通过矩阵的迭代速度较慢,c++,c,arrays,performance,caching,C++,C,Arrays,Performance,Caching,我有一个名为a的ints矩阵,当我按列而不是按行对其进行迭代时,它的运行速度大约慢50毫秒: for(int i=0;i<n;i++) for(int j=0;j<n;j++) cout<<A[j][i]; //slower than of A[i][j] for(int i=0;i,因为第一个循环访问内存,而另一个循环之间有间隙。因此第一个循环对缓存更友好。2D数组作为1D数组存储在内存中(行/列)major。这意味着一个包含5列
a
的int
s矩阵,当我按列而不是按行对其进行迭代时,它的运行速度大约慢50毫秒:
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cout<<A[j][i]; //slower than of A[i][j]
for(int i=0;i,因为第一个循环访问内存,而另一个循环之间有间隙。因此第一个循环对缓存更友好。2D数组作为1D数组存储在内存中(行/列)major。这意味着一个包含5列的数组可能会一列接一列地存储为5列,因此根据您的访问方式与此顺序,您的访问可能会被缓存,或者每一个访问都可能导致缓存失败,从而导致性能上的巨大差异。逐行遍历矩阵更快导致高速缓存的原因
当您访问A[i][j]
时,加载到缓存中的内存多于一个元素。请注意,矩阵的每一行都存储在连续内存块中,因此当内存“环绕”A[i][j]
仍在缓存中,访问同一行中的下一个元素更有可能导致从缓存而不是从主内存中读取该元素(请参阅)
另请参见相关问题:
这是关于缓存线读取机制的。
了解
若要验证,请尝试在运行此应用程序时禁用缓存。(我忘记了如何执行此操作,但可以执行此操作。)正如其他人所指出的,这是一个缓存问题。在每次访问数组元素时,使用一种方法可能会导致缓存未命中
缓存问题实际上是优化的一个非常重要的因素。这就是为什么有时使用数组结构而不是数组结构更好的原因。比较这两种方法:
struct StructOfArrays {
int values[100];
char names[100][100];
}
struct StructOfArrays values;
struct NormalValStruct {
int val;
char name[100];
}
struct NormalValStruct values[100];
如果您迭代StructOfArrays
中的值,这些值可能会加载到缓存中并进行高效读取。当您迭代NormalValStruct
并获取值成员时,每隔一段时间就会出现一次缓存未命中
这种技巧通常用于高性能应用程序中。这些应用程序通常是游戏。你能在初始化数组的地方发布代码吗?它是一个全局数组,只是int a[100][100]