0

値を保存するのにどれくらいの時間がかかりますか? 2 回、5 回、または 20 回使用する計算値 x があるとします。使用するたびに再計算するのではなく、計算値を保存する方が最適になるのはどの時点ですか? 例:

int a=0,b=-5;
for(int i=0;i<k;++i)
  a+=abs(b);

また

int a=0,b=-5;
int x=abs(b);
for(int i=0;i<k;++i)
  a+=x;

2 番目のシナリオでは、どの k 値でより良い結果が得られますか? また、このRAMはどの程度依存していますか?

4

5 に答える 5

3

の値はabs(b)for ループ内で変更されないため、コンパイラは両方のスニペットを最適化して同じ結果、つまり の値をabs(b)1 回だけ評価する可能性が高くなります。

于 2013-08-30T15:36:28.150 に答える
1

実際のシナリオでは、対策以外の答えを提供することはほとんど不可能です。コード内のデータをキャッシュすると、レジスタに格納される場合があります (指定したコードでは、おそらくそうなります)、ループの内容に応じて、L1 キャッシュまたは L2 キャッシュにフラッシュされる場合があります。しています (どのくらいのデータを使用していますか?)。値がレジスタにキャッシュされている場合、コストは 0 です。値をプッシュするほど、値を取得するためのコストが高くなります。

一般に、読みやすく保守しやすいコードを作成してから、アプリケーションのパフォーマンスを測定し、パフォーマンスが良くない場合はプロファイルを作成します。ホットスポットを見つけ、それらがホットスポットである理由を見つけ、そこから作業を進めます。上記のようなキャッシングと計算abs(x)が実際のアプリケーションでホットスポットになるとは思えません。だから、汗をかかないでください。

于 2013-08-30T15:44:38.400 に答える
0

多くの場合、k=2 からより良いパフォーマンスが得られます。あなたが与えた例はです。ない1。ほとんどのコンパイラは、低レベルの最適化が有効になっている場合でも、この種の巻き上げを実行しようとします。値は、最悪の場合、ローカル スタックに保存されるため、かなりキャッシュ ウォームのままになる可能性が高く、メモリに関する懸念は解消されます。

しかし、潜在的にそれはレジスターに保持されます。

オリジナルは追加の分岐を実行し、計算を繰り返して値を返す必要があります。Abs は、コンパイラが constexpr およびホイストとして認識できる関数の一例です。

これは、独自のクラスを開発する際に、可能な限りメンバーと参照を construe としてマークする必要がある理由の 1 つです。

于 2013-08-30T16:19:11.743 に答える
0

コンパイラは abs(x) の結果をとにかくレジスタに格納する可能性が最も高いため、経験則として、その値をループの外に格納するのに、どちらかと言えばそれほどコストはかかりません。実際、コンパイラがこのコードを最適化するとき (最適化がオンになっていると仮定)、コンパイラが最初に行うことの 1 つは、その abs(x) をループから引き出すことです。

「x」の宣言を「register」ヒントで修飾することにより、コンパイラーが適切なコードを生成するのをさらに支援できます。これは、可能であれば x をレジスター値に格納するようにコンパイラーに要求します。

コンパイラがコードに対して実際に何をするかを確認したい場合、やるべきことの 1 つは、コンパイルするがアセンブルしないように指示し (gcc では、オプションは -S)、結果のアセンブリ コードを調べることです。多くの場合、コンパイラは、手動で最適化するよりも優れたコードを生成します。ただし、これらの簡単な最適化を自分で実行しない理由もありません。

補遺:

GCC で最適化をオンにして上記のコードをコンパイルすると、次のようなコードになります。

a = abs(b) * k;

試してみてください。

于 2013-08-30T16:15:27.057 に答える