0

2 つの行列を乗算するための適切なループ展開を見つけようとしています。

たとえば、NxN 行列を合計したい場合:

void SumMatrix(int *M, int n, int *result) 
{ 
  int  i,j; 

  *result = 0; 
  for (i=0; i<n; i++) 
    for (j=0; j<n; j++) 
      *result += M[j][i]; 
}

できるよ :

void SumMatrix(int *M, int n, int *result) 
{ 
    int  i; 
    int  size = n*n; 
    int  last = size%8; 
    int  acc1 = 0; 
    int  acc2 = 0; 
    int  *pEnd = M+size-last; 

    for (; M<pEnd; M+=8) 
    { 
      acc1 += (*M + *(M+1)) + (*(M+2) + *(M+3));
      acc2 += (*(M+4) + *(M+5)) + (*(M+6) + *(M+7));
    } 

    /* adding the last entries */ 
    while (last--)  
        acc1 += *(M++); 

    *result = acc1+acc2;        
}

しかし、私は 2 つの行列を乗算する (良い) 方法を見つけようとしましたが、現時点では何も見つかりませんでした。

備考: これは宿題ではありません。今日試験があって、ちょうどこの問題について考えました。

助けていただければ幸いです

よろしく

ロン

4

2 に答える 2

2

ほとんどのコンパイラはあなたに代わって展開を行います(フラグをオンにするか、最適化レベルに設定する必要があるかもしれません-gccでそれを行うと思います-funroll-loops)。

また、あなたの質問では、すべての数値を合計しているので、それが2D行列であるという事実は重要ではありません。単一のプロセス/スレッドに制限されている場合は、キャッシュパフォーマンスが最適であるため、番号を順番に加算するのが最も速くなります。SSEまたはベクトル命令からいくつかの利点が得られる可能性があります。繰り返しになりますが、今日のコンパイラーは、このような単純な問題でこれらを実行できます。

于 2012-04-19T07:40:09.457 に答える
0

BLAS ライブラリの最適化されたバージョン (主に行列乗算に基づく) を提供する ATLAS プロジェクトがいかに複雑であるかを見てください。スレッド レベルの並列処理だけでなく、メモリ階層 (アンロールだけでなく、キャッシュ タイルとレジスタ タイル、ソフトウェア パイプラインなど) も考慮する必要があります。これは通常、手動で作成されるか、ATLAS などの「自動チューナー」によって最適化されます。スレッド レベルの並列処理を解明したい場合は、「タイル アルゴリズム」を使用して、結果のタイル計算をスレッド間で分散することをお勧めします。

于 2012-04-27T17:08:30.720 に答える