ハイ パフォーマンス コンピューティングというコースの割り当てのために、次のコード フラグメントを最適化する必要がありました。
int foobar(int a, int b, int N)
{
int i, j, k, x, y;
x = 0;
y = 0;
k = 256;
for (i = 0; i <= N; i++) {
for (j = i + 1; j <= N; j++) {
x = x + 4*(2*i+j)*(i+2*k);
if (i > j){
y = y + 8*(i-j);
}else{
y = y + 8*(j-i);
}
}
}
return x;
}
いくつかの推奨事項を使用して、次のようなコードを最適化することができました (少なくとも私はそう思います)。
- 一定の伝播
- 代数的単純化
- 伝播のコピー
- 共通部分式の削除
- デッドコードの排除
- ループ不変式の削除
- 安価なため、乗算ではなくビットごとのシフト。
これが私のコードです:
int foobar(int a, int b, int N) {
int i, j, x, y, t;
x = 0;
y = 0;
for (i = 0; i <= N; i++) {
t = i + 512;
for (j = i + 1; j <= N; j++) {
x = x + ((i<<3) + (j<<2))*t;
}
}
return x;
}
私のインストラクターによると、適切に最適化されたコード命令は、アセンブリ言語レベルの命令が少ないかコストがかからないはずです。したがって、元のコードよりも短い時間で命令を実行する必要があります。つまり、計算は次のように行われます::
実行時間 = 命令数 * 命令ごとのサイクル数
次のコマンドを使用してアセンブリ コードを生成するとgcc -o code_opt.s -S foobar.c
、
生成されたコードには、いくつかの最適化を行ったにもかかわらず、元のコードよりも多くの行があり、実行時間は短くなりますが、元のコードほどではありません. 私は何を間違っていますか?
アセンブリ コードは両方とも非常に広範囲に及ぶため、貼り付けないでください。そのため、メインで関数「foobar」を呼び出しており、Linux で time コマンドを使用して実行時間を測定しています。
int main () {
int a,b,N;
scanf ("%d %d %d",&a,&b,&N);
printf ("%d\n",foobar (a,b,N));
return 0;
}