1

本の「Using 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 では 2 次元配列は行ごとに格納され、ここでは i ステップごとに新しい行がメモリからキャッシュにコピーされます。

これに対する解決策を見つけようとしていますが、スピードアップがうまくいきません。私の試みの影響は軽微です。

誰かが私に何ができるかのヒントを教えてもらえますか?

最も簡単な方法は for ループを交換することですが、私は列ごとに行いたいと考えています。

2 回目の試行:

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] ;
  }

まったく違いはありませんでした。

3 回目の試行:

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 ;
  }
}

ありがとう

ステップに挨拶

4

3 に答える 3

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だけが変更されます。つまり、メモリアクセスが連続します。

于 2011-02-24T18:12:40.150 に答える
0

このメモリ アクセスの問題は、Openmp ではなく CACHE の使用に関連しています。一般的にキャッシュを有効に利用するには、連続したメモリ ロケーションにアクセスする必要があります。また、2 つ以上のスレッドが同じメモリ領域にアクセスしている場合、キャッシュが不必要に再ロードされる「偽のシアリング」の問題が発生する可能性があることにも注意してください。例を参照してください:
http://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads/

于 2011-02-24T21:55:59.327 に答える
0

代わりにフラット配列を使用します。例:

#define A(i,j) A[i+j*ldA]

for( int j=0; j<n ; j++)
{  
  d= A(k,j) ;
  ...
}
于 2011-02-24T18:05:33.080 に答える