7

Java コンパイラ (JDK1.6.0_21 に付属するデフォルトの javac) はコードを最適化して、同じメソッドが同じ引数で何度も呼び出されるのを防ぎますか? このコードを書いた場合:

public class FooBar {
    public static void main(String[] args) {
        foo(bar);
        foo(bar);
        foo(bar);
    }
}

メソッドfoo(bar)は 1 回だけ実行されますか? もしそうなら、この最適化を防ぐ方法はありますか? (1 つは反復アルゴリズム、もう 1 つは比較アルゴリズムの 2 つのアルゴリズムの実行時間を比較しようとしています。代表的なサンプルを取得するために、それらを何度も呼び出したいと考えています)

どんな洞察も大歓迎です。私はこの問題を狂気に陥れました (しばらくの間、私のコンピューターは非常に高速だったので、code too large43671 行でエラーが発生するまでメソッド呼び出しを追加し続けました)。

4

4 に答える 4

6

あなたが観察している最適化は、おそらく繰り返しの呼び出しとは何の関係もありません...それは無効な最適化になるからです。おそらく、オプティマイザーは、メソッド呼び出しが計算に目に見える影響を与えていないことを認識しています。

解決策は、計算結果に影響を与えるようにメソッドを変更することです...

于 2010-08-02T03:17:30.867 に答える
4

そうではありません。foo純粋でない場合、大きな問題を引き起こします(プログラムのグローバルな状態を変更します)。例えば:

public class FooBar {
    private int i = 0;
    private static int foo() {
        return ++i;
    }

    public static void main(String[] args) {
        foo();
        foo();
        foo();
        System.out.println(i);
    }
}
于 2010-08-02T03:17:05.407 に答える
4

決定的な回答を可能にするのに十分な情報を提供していませんが、jvm ランタイム オプティマイザーは非常に強力で、あらゆる種類のインライン化、ランタイム データフローとエスケープ分析、およびあらゆる種類のキャッシュ トリックを実行します。

最終的な結果は、実行しようとしている種類のマイクロ ベンチマークを実際には役に立たなくすることです。潜在的に役立つ場合でも、正しく理解するのは非常に困難です。

あなたが直面している問題についての完全な議論については、必ずhttp://www.ibm.com/developerworks/java/library/j-benchmark1.htmlを読んでください。少なくとも、次のことを確認する必要があります。

  1. foo は、何千回も実行されるループで呼び出されます
  2. foo() は結果を返し、
  3. その結果が使用されます

以下は、foo() が自明ではないため、インライン化される可能性が低いと仮定した場合の最小限の出発点です。注: ループのアンローリングやその他のキャッシュ レベルの最適化を期待する必要があります。また、同じ JVM で測定を再実行しようとすると、ホットスポット コンパイル ブレークポイント (これは -server IIRC で約 5000 回の呼び出しであると思われます) にも注意してください。

public class FooBar {
    public static void main(String[] args) {
        int sum = 0;
        int ITERATIONS = 10000;
        for (int i = 0; i < ITERATIONS; i++) {
            sum += foo(i);
        }

        System.out.println("%d iterations returned %d sum", ITERATIONS, sum);
    }
}

真剣に、最新の JVM でベンチマークを作成するために有意義な進歩を遂げる前に、いくつかの資料を読む必要があります。最新の Java コードが C++ に匹敵するか、場合によっては C++ を凌駕するのと同じ最適化が、ベンチマークを非常に困難にしています。

于 2010-08-02T04:00:49.793 に答える
0

Java コンパイラは、このような最適化の実行を許可されていません。メソッドの呼び出しは、IO アクションや到達可能なすべてのフィールドへの変更、またはそうする他のメソッドの呼び出しなどの副作用を引き起こす可能性が非常に高いためです。

各関数呼び出しが同じ引数で呼び出された場合に同じ結果を返すことが保証されている (状態の変更は禁止されている) 関数型言語では、コンパイラーは結果を記憶することによって複数の呼び出しを実際に最適化する可能性があります。

アルゴリズムが速すぎると感じた場合は、大規模または複雑な問題セットをいくつか与えてみてください。常に非常に高速なアルゴリズムはごくわずかです。

于 2011-08-10T09:18:42.787 に答える