2017-11-20 8 views
0

私は行列の乗算のための典型的なアルゴリズムを持っています。私は適用し、ループ展開を理解しようとしていますが、kが行列の倍数でないときにk回アンロールしようとするときにアルゴリズムを実装する際に問題が発生しています。 (私は結果として非常に大きな数字を得ます)。つまり、アンロール後に残りの要素を処理する方法が得られないということです。ここで私が持っているものです。残りの要素でループアンローリングが機能しない

void Mult_Matx(unsigned long* a, unsigned long* b, unsigned long*c, long n) 
{ 
    long i = 0, j = 0, k = 0; 
    unsigned long sum, sum1, sum2, sum3, sum4, sum5, sum6, sum7; 

    for (i = 0; i < n; i++) 
    { 
     long in = i * n; 
     for (j = 0; j < n; j++) 
     { 
      sum = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = 0; 

      for (k = 0; k < n; k += 8) 
      { 
       sum = sum + a[in + k] * b[k * n + j]; 
       sum1 = sum1 + a[in + (k + 1)] * b[(k + 1) * n + j]; 
       sum2 = sum2 + a[in + (k + 2)] * b[(k + 2) * n + j]; 
       sum3 = sum3 + a[in + (k + 3)] * b[(k + 3) * n + j]; 
       sum4 = sum4 + a[in + (k + 4)] * b[(k + 4) * n + j]; 
       sum5 = sum5 + a[in + (k + 5)] * b[(k + 5) * n + j]; 
       sum6 = sum6 + a[in + (k + 6)] * b[(k + 6) * n + j]; 
       sum7 = sum7 + a[in + (k + 7)] * b[(k + 7) * n + j]; 
      } 

      if (n % 8 != 0) 
      { 
       for (k = 8 * (n/8); k < n; k++) 
       { 
        sum = sum + a[in + k] * b[k * n + j]; 
       } 
      } 
      c[in + j] = sum + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7; 
     } 
    } 
} 

の別名nサイズを言ってみましょう、私はそれが余りループに入ることがないときを意味し、このコードは動作しますが、それを4回展開すると12です。しかし、私は何が起こっているのか分かりません。私が間違っている場所に誰かが私に指示することができれば、本当に感謝しています。私はこれを初めて知り、苦労している。

+2

手作業でループをアンローリングするのは80sだから...(私は言っている:do not。あなたが主張するなら、[Duffのデバイス](https://en.wikipedia.org/wiki/Duff%27s_device)を見てください。 )、アンロールされたコードのどこかをジャンプすることによって "残余"を処理する) –

+0

@FelixPalmen lol。私は、イントロのオペレーティングシステムクラスを取っています。だから... –

+0

おそらくあなたは[あなたのプログラムをデバッグする方法を学ぶ](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)にしばらく時間がかかるでしょうか? –

答えて

2

この形状にループをアンロールする一般的な方法は:

for(int i=0; i<N; i++) 
    ... 

int i; 
for(i=0; i<N-L; i+=L) 
    ... 
for(; i<N; i++) 
    ... 

であるか、ループの範囲にインデックス変数を保持する場合:

for(int i=0; i<N-L; i+=L) 
    ... 
for(int i=L*(N/L); i<N; i++) 
    ... 

ここでは、整数除算を切り捨てたという事実を利用しています。 Lは、最初のループで実行するステップ数です。

例:

const int N=22; 
const int L=6; 
int i; 
for(i=0; i<N-L; i+=L) 
{ 
    printf("%d\n", i); 
    printf("%d\n", i+1); 
    printf("%d\n", i+2); 
    printf("%d\n", i+3); 
    printf("%d\n", i+4); 
    printf("%d\n", i+5); 
} 
for(; i<N; i++) 
    printf("%d\n", i); 

しかし、私はDuff's deviceでご覧になることをお勧めします。しかし、私はいつも使うのが良いとは思わない。その理由は、モジュロはかなり高価な操作であるということです。

条件if (n % 8 != 0)は必要ありません。 forヘッダーは正しく書かれていればそれを処理する必要があります。

関連する問題