ループ内のメモリ呼び出しの数を減らすことについて質問があります。次のコードを検討してください(長すぎるため、ここでは表現できないため、これは私のコードではありません)。
for(k=0;k<n;k++)
{
y[k] = x[0]*2 + z[1];
}
ご覧のとおり、各反復で、メモリ内の同じブロック(x [0]、z [1])が呼び出されています。同じメモリブロックが複数回呼び出されたときに、メモリアクセスを減らす方法があるかどうか疑問に思いました。前もって感謝します。
ループ内のメモリ呼び出しの数を減らすことについて質問があります。次のコードを検討してください(長すぎるため、ここでは表現できないため、これは私のコードではありません)。
for(k=0;k<n;k++)
{
y[k] = x[0]*2 + z[1];
}
ご覧のとおり、各反復で、メモリ内の同じブロック(x [0]、z [1])が呼び出されています。同じメモリブロックが複数回呼び出されたときに、メモリアクセスを減らす方法があるかどうか疑問に思いました。前もって感謝します。
単純に、ループの前に値を取得します。
i = x[0];
j = z[1];
for(k=0;k<n;k++)
{
y[k] = i*2 + j;
}
もちろん、何も変更しなくても、コンパイラはこれを最適化しますが (可能であれば)、より読みやすく直感的なコードを作成するのに役立ちます。すべての反復で値を取得する必要はなく、記述するコードはそれを示している必要があります。
マイクロ最適化を忘れて、より直感的で読みやすいコードを書きましょう!
コメントで正しく指摘されているように、右側の式はループから完全に独立しているため、次のようになります。
i = x[0]*2 + z[1];
for(k=0;k<n;k++)
{
y[k] = i;
}
これがあなたにできることです。
float value = x[0]*2 + z[1];
for(k=0;k<n;k++)
{
y[k] = value;
}
お役に立てれば。
v = x[0]*2 + z[1];
for(k=0;k<n;++k) y[k] = v
x[0]とz[1]がy[0..n-1]にマップされていないと仮定します。
z
より短い型int
(例) がある場合char
は、次のトリックを試すことができます。
char value = x[0]*2 + z[1];
unsigned int value32 = value | (value << 8) | (value << 16) | (value << 24);
unsigned int k;
// Going by blocks of 4
for(k = 0; k < n - n%4; k+=4) {
(unsigned int)z[k] = value32;
}
// Finishing loop
for(; k < n; k++) {
z[k] = value;
}
コンパイラはこれを最適化し、
ただし、最適化を行わずに壊れたコンパイラを使用する場合は、両方をregister
整数に入れて操作することができます。このような:
x0 = x[0]*2;
z1 = z[1];
y0 = x0 + z1;
register int k;
for(k=0;k<n;k++)
{
y[k] = y0;
}
これは、x[0] と z[1] がレジスターにあることを保証するものではありませんが、少なくともレジスターにある必要があることをコンパイラーに示唆します。