是C中不良内存访问的一个例子,我认为这是我尝试并行高斯算法的主要问题。
示例如下所示:
k= 0 ;
for( int j=0; j<n ; j++)
for(int i = 0; i<n; i++)
a[i][j] = a[i][j] - a[i][k]*a[k][j] ;
所以,我确实理解为什么这会导致错误的内存访问。在C中,2d数组按行存储,在每个i步骤中,新行将从内存复制到缓存。
我正试图找到一个解决方案,但我没有得到一个很好的加速。我尝试的效果很小。
有人能给我一个暗示我可以做什么吗?
最简单的方法是交换for循环,但我想以列方式进行。
第二次尝试:
for( int j=0; j<n-1 ; j+=2)
for(int i = 0; i<n; i++)
{
a[i][j] = a[i][j] - a[i][k]*a[k][j] ;
a[i][j+1] = a[i][j+1] - a[i][k]*a[k][j+1] ;
}
根本没有任何区别。
第三次尝试:
for( int j=0; j<n ; j++)
{
d= a[k][j] ;
for(int i = 0; i<n; i++)
{
e = a[i][k] ;
a[i][j] = a[i][j] - e*d ;
}
}
很多
Greets Stepp
答案 0 :(得分:0)
使用平面数组,例如:
#define A(i,j) A[i+j*ldA]
for( int j=0; j<n ; j++)
{
d= A(k,j) ;
...
}
答案 1 :(得分:0)
正如您所指出的,您的循环顺序将导致每次迭代的缓存未命中。所以只需交换循环语句的顺序:
for (int i = 0; i < n; i++) // now "i" is first
for (int j = 0; j < n; j++)
a[i][j] = a[i][j] - a[i][k]*a[k][j];
这将修复a
中的行并仅改变列,这意味着您的内存访问将是连续的。
答案 2 :(得分:0)
此内存访问问题仅与CACHE使用有关,而与Openmp无关。
为了更好地利用缓存,您应该访问连续的内存位置。还要记住,如果两个或多个线程正在访问相同的内存区域,那么您可能会出现“错误剪切”问题,从而迫使缓存不必要地重新加载。
例如,见:
http://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads/