5
  1. llvmまたはgccコンパイラを使用した場合の結果のマシン コードに関して、次の 2 つのコード ブロックに違いはありますか?
  2. この最適化が実際に価値があるのはいつですか?

最適化されていません:

for (int i=0; i<array.count; i++) {
    //do some work
}

最適化:

int count = array.count;
for (int i=0; i<count; i++) {
    //do some work
}

編集array:これは不変でありarray.count、ループの実行中に変更されないことを指摘する必要があります。

4

2 に答える 2

3
  1. 実際に自分で確認する必要があります。私の推測では、出力されたコードに違いあると思いますが、コンパイラとコンパイラ オプションに依存する可能性があり、array.
  2. array.count「何らかの作業」と比較して、評価はほとんど常に重要ではないという前提で、ほとんどありません。ただし、それを測定する方法は、プロファイラー (または同等のもの) を使用して、そのコード行でプログラムの実行時間のどの割合が費やされるかを観察することです。プロファイラーが正確であれば、それを変更することで得られる最大の期待値です。

常に同じ結果が返さarray.countれることがわかっているが、コンパイラはそれを認識していない、非常に遅いものがあるとします。それなら、手動で持ち上げる価値があるかもしれません。strlen例として使用されます。実際にどれくらいの頻度strlen実際に遅いかについては議論の余地がありますが、必要以上に遅くなる可能性のある例を簡単に作成できます。

char some_function(char a) {
    return (a * 2 + 1) & 0x3F;
}

for (int i = 0; i < strlen(ptr); ++i) {
    ptr[i] = some_function(ptr[i]); // faster than strlen for long enough strings.
}

あなたも私も、 が 0 を返さないことを知っているsome_functionので、文字列の長さが変わることはありません。コンパイラは の定義をsome_function認識しない可能性があり、たとえ定義を認識したとしても、ゼロ以外の戻り値が重要であることを理解していない可能性があります。

于 2012-10-10T10:30:13.680 に答える
1

スティーブジェソップの答えは良いものです。追加したいのは:

個人的には、常に最適化されたバージョンを使用しています。ループからすべての定数コンポーネントを削除することは、私の一連のグッドプラクティスにすぎません。それほど手間がかからず、コードがすっきりします。これは「時期尚早の最適化」ではなく、問題やトレードオフを引き起こすことはありません。デバッグが容易になります(ステッピング)。また、コードが高速になる可能性があります。ですから、それは私にとって簡単なことです。

于 2012-10-10T13:29:21.803 に答える