OpenMP C并行化算法

时间:2011-02-24 17:52:31

标签: openmp memory-access

“使用OpenMP”一书中的

是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

3 个答案:

答案 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/