6

for ループで何が優れているか

これ:

for(int i = 0; i<someMethod(); i++)
{//some code
 }

また:

int a = someMethod();
for(int i = 0; i<a; i++)
{//some code
 }

someMethod()が何か大きなものを返すとしましょう。

最初のメソッドは各ループでsomeMethod()を実行するため速度が低下し、2 番目のメソッドは高速ですが、アプリケーションに同様のループが多数あるため、変数 vill を宣言するとより多くのメモリが消費されるとします。

それで何がいいのか、それとも私が愚かに考えているだけなのか.

4

9 に答える 9

11

2 番目の方が優れています。副作用someMethod()がないと仮定します。 実際には、によって計算された値がキャッシュされるため、再計算する必要はありません (比較的拡張性の高い操作であると仮定します)。
someMethod()

そうである場合 (副作用があります) - 2 つのコード スナップは同等ではありません-正しいことを行う必要があります。

「変数 a のサイズ」について - とにかく問題ではありません。戻り値は、計算前someMethod()に何らかの中間一時変数に格納する必要があります(そうでなかったとしても、1 つの整数のサイズは無視できます)。 )。

PS
場合によっては、コンパイラ/JIT オプティマイザは、もちろん副作用がないと仮定して、最初のコードを 2 番目のコードに最適化することがあります。

于 2013-02-04T14:39:40.780 に答える
4

疑わしい場合は、テストしてください。プロファイラーを使用します。測定。

于 2013-02-04T14:39:47.617 に答える
4

反復順序が関係ないと仮定し、また、コードを本当にナノ最適化したいと仮定すると、これを行うことができます:

for (int i=someMethod(); i-->0;) {
  //some code
}

しかし、追加のローカル変数 ( your a) はそれほど負担ではありません。実際には、これは 2 番目のバージョンと大差ありません。

于 2013-02-04T14:40:06.167 に答える
3

ループ後にこの変数が必要ない場合は、内部に隠す簡単な方法があります。

for (int count = someMethod (), i = 0; i < count; i++)
{
    // some code
}
于 2013-02-04T14:46:09.050 に答える
2

これは、someMethod()の出力を生成するのにかかる時間によって異なります。someMethod()は最初に出力を生成し、次にこれを格納する必要があるため、メモリ使用量も同じになります。2番目の方法は、CPUがループごとに同じ出力を計算するのを防ぎ、より多くのメモリを消費しないようにします。したがって、2番目の方が優れています。

于 2013-02-04T14:44:02.123 に答える
2

変数 a は int であり、64 ビット マシンでは 192 ビットを必要とするため、変数 a のメモリ消費は問題とは見なしません。したがって、実行効率が優れているため、2番目の選択肢をお勧めします。

于 2013-02-04T14:45:11.537 に答える
1

ループの最適化に関する最も重要な部分は、JVMがループを展開できるようにすることです。最初のバリアントでこれを行うには、への呼び出しをインライン化できる必要がありますsomeMethod()。インライン化にはある程度の予算があり、ある時点で無効になる可能性があります。someMethod()が十分に長い場合、JVMはインライン化を望まないと判断する可能性があります。

2番目のバリアントは、(JITコンパイラーにとって)より有用であり、より適切に機能する可能性があります。

ループを置くための私の方法は次のとおりです。 for (int i=0, max=someMethod(); i<max; i++){...}

maxコードを汚染せず、someMethod()の複数の呼び出しによる副作用がなく、コンパクト(シングルライナー)であることを確認します

于 2013-02-06T08:15:11.800 に答える
0

これを最適化する必要がある場合、これがクリーンで明白な方法です。

int a = someMethod();
for (int i = 0; i < a; i++) {
    //some code
}

@dystroy によって提案された代替バージョン

for (int i=someMethod(); i-->0;) {
    //some code
}

... 3 つの問題があります。

  • 彼は反対方向に繰り返しています。

  • その繰り返しは慣用的ではないため、読みにくくなります。特に、Java スタイル ガイドを無視して、本来あるべき場所に空白を入れない場合はなおさらです。

  • コードがより慣用的なバージョンよりも実際に高速であるという証拠はありません...特にJITコンパイラーが両方を最適化した場合はなおさらです。(そして、読みにくいバージョンの方が高速であったとしても、その違いは無視できる可能性が高いです。)

一方、someMethod()(あなたが仮定したように)高価な場合は、呼び出しを「ホイスト」して、一度だけ実行されるようにすることは価値がある可能性があります。

于 2013-02-04T14:55:49.963 に答える