0

ネストされたforループの展開に問題があります。私は概念を理解しています。私はそれを実践しようとしていforますが、展開に合わせてループ内のステートメントを編集することにつまずいています。

誰かが私に効率的なアンロールを見せて、それを順を追って説明してくれたら、それは大きな助けになるでしょう.

展開したいループセクションは次のとおりです。

for (i=1 ; i < WIDTH-1 ; ++i) 
{
      for (j = 1 ; j < HEIGHT-1 ; ++j) 
      {
         n = getNeighbors(prv, i, j);    /* This is where I'm confused */
         mask = (prev[i][j] << 1);       
         next[i][j] = !(((n >> prev[i][j]) ^ 3) ^ mask);
      }
}

更新: これは正しいでしょうか?

for (i=1 ; i < WIDTH-1 ; i+=4) 
{
      for (j = 1 ; j < HEIGHT-1 ; j+=4) 
      {
         n = getNeighbors(prv, i, j);  
         mask = (prev[i][j] << 1);       
         next[i][j] = !(((n >> prev[i][j]) ^ 3) ^ mask);
         n = getNeighbors(prv, i, j+1);  
         mask = (prev[i][j+1] << 1);       
         next[i][j+1] = !(((n >> prev[i][j+1]) ^ 3) ^ mask);
         n = getNeighbors(prv, i, j+2);  
         mask = (prev[i][j+2] << 1);       
         next[i][j+2] = !(((n >> prev[i][j+2]) ^ 3) ^ mask);
         n = getNeighbors(prv, i, j+3);  
         mask = (prev[i][j+3] << 1);       
         next[i][j+3] = !(((n >> prev[i][j+3]) ^ 3) ^ mask);
      }
      for (j = 1 ; j < HEIGHT-1 ; j+=4) 
      {
         n = getNeighbors(prv, i+1, j);  
         mask = (prev[i+1][j] << 1);       
         next[i+1][j] = !(((n >> prev[i+1][j]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+1, j+1);  
         mask = (prev[i+!][j+1] << 1);       
         next[i+1][j+1] = !(((n >> prev[i+1][j+1]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+1, j+2);  
         mask = (prev[i+1][j+2] << 1);       
         next[i+1][j+2] = !(((n >> prev[i+1][j+2]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+1, j+3);  
         mask = (prev[i+1][j+3] << 1);       
         next[i+1][j+3] = !(((n >> prev[i+1][j+3]) ^ 3) ^ mask);
      }
      for (j = 1 ; j < HEIGHT-1 ; j+=4) 
      {
         n = getNeighbors(prv, i+2, j);  
         mask = (prev[i+2][j] << 1);       
         next[i+2][j] = !(((n >> prev[i+2][j]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+2, j+1);  
         mask = (prev[i+2][j+1] << 1);       
         next[i+2][j+1] = !(((n >> prev[i+2][j+1]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+2, j+2);  
         mask = (prev[i+2][j+2] << 1);       
         next[i+2][j+2] = !(((n >> prev[i+2][j+2]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+2, j+3);  
         mask = (prev[i+2][j+3] << 1);       
         next[i+2][j+3] = !(((n >> prev[i+2][j+3]) ^ 3) ^ mask);
      }
      for (j = 1 ; j < HEIGHT-1 ; j+=4) 
      {
         n = getNeighbors(prv, i+3, j);  
         mask = (prev[i+3][j] << 1);       
         next[i+3][j] = !(((n >> prev[i+3][j]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+3, j+1);  
         mask = (prev[i][j+1] << 1);       
         next[i+3][j+1] = !(((n >> prev[i+3][j+1]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+3, j+2);  
         mask = (prev[i][j+2] << 1);       
         next[i+3][j+2] = !(((n >> prev[i+3][j+2]) ^ 3) ^ mask);
         n = getNeighbors(prv, i+3, j+3);  
         mask = (prev[i+3][j+3] << 1);       
         next[i+3][j+3] = !(((n >> prev[i+3][j+3]) ^ 3) ^ mask);
      }
}
4

2 に答える 2

1

ループを次のようにします。

for(int i = 0; i < x; ++i)
    for(int j = 0; j < y; ++j)
        dosomething(i, j);

次のように展開できます。

for(int i = 0; i < x; i += 4) {
    for(int j = 0; j < y; j += 4) {
        dosomething(i, j);
        dosomething(i, j + 1);
        dosomething(i, j + 2);
        dosomething(i, j + 3);
    }
    for(int j = 0; j < y; j += 4) {
        dosomething(i + 1, j);
        dosomething(i + 1, j + 1);
        dosomething(i + 1, j + 2);
        dosomething(i + 1, j + 3);
    }
    for(int j = 0; j < y; j += 4) {
        dosomething(i + 2, j);
        dosomething(i + 2, j + 1);
        dosomething(i + 2, j + 2);
        dosomething(i + 2, j + 3);
    }
    for(int j = 0; j < y; j += 4) {
        dosomething(i + 3, j);
        dosomething(i + 3, j + 1);
        dosomething(i + 3, j + 2);
        dosomething(i + 3, j + 3);
    }
}

これがどれほどの利益をもたらすかはわかりません。このような展開後にコードをプロファイリングする必要があります。

于 2015-05-31T18:14:06.433 に答える
0

ほんの一例:

int r[3][3];

// loop version
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        r[i][j] = i + j;
    }
}

// unrolled version
r[0][0] = 0;
r[0][1] = 1;
r[0][2] = 2;
r[1][0] = 1;
r[1][1] = 2;
r[1][2] = 3;
r[2][0] = 2;
r[2][1] = 3;
r[2][2] = 4;

このような完全な展開は、コンパイル時にサイズがわかっているベクトルまたは行列に対してのみ簡単に可能であることに注意してください。また、最近のコンパイラは、このようなループを自分で展開できることが多いことに注意してください。

于 2015-05-31T18:17:46.200 に答える