-4

重複の可能性:
これらのコードのうち、Java の方が速いのはどれですか?

ループを次のように書くと

for (int i=n; i>=0; i--)

そして他のものとして

for (int i=0; i<=n; i++)

Javaでは、どちらがより高速で、その理由は?.. n=10000と言う

4

6 に答える 6

9

不思議に思うことはありません。GoogleCaliperを使用して調べてください。ゼロと上限、およびインクリメントとデクリメントに対するテストの相対的な重みについてはかなりの議論があったので、これらすべてのケースのデカルト積を次に示します。

import java.util.Random;

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class Performance extends SimpleBenchmark {
  static final Random rnd = new Random();

  public int timeDecrementToZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = Integer.MAX_VALUE; j >= 0; j--) sum += j;
    }
    return sum;
  }
  public int timeDecrementFromZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = 0; j > Integer.MIN_VALUE; j--) sum += j;
    }
    return sum;
  }
  public int timeIncrementFromZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = 0; j < Integer.MAX_VALUE; j++) sum += j;
    }
    return sum;
  }
  public int timeIncrementToZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = Integer.MIN_VALUE; j < 0; j++) sum += j;
    }
    return sum;
  }

  public static void main(String... args) {
    Runner.main(Performance.class, args);
  }
}

結果:

 0% Scenario{vm=java, trial=0, benchmark=DecrementToZero} 984060500.00 ns; σ=30872487.22 ns @ 10 trials
25% Scenario{vm=java, trial=0, benchmark=DecrementFromZero} 982646000.00 ns; σ=35524893.00 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=IncrementFromZero} 1023745500.00 ns; σ=24828496.82 ns @ 10 trials
75% Scenario{vm=java, trial=0, benchmark=IncrementToZero} 1081112500.00 ns; σ=20160821.13 ns @ 10 trials

        benchmark   ms linear runtime
  DecrementToZero  984 ===========================
DecrementFromZero  983 ===========================
IncrementFromZero 1024 ============================
  IncrementToZero 1081 ==============================

どうやら、制限がゼロであるかどうかは、inc対decを使用するよりも効果が少ないようです。

少しだけ変更してみましょう...

これらの違いがどれほど希薄であるかを指摘するために、これは実質的に同じコードですが、現在はlongsを使用しています(スケールを維持するために、最初の例の1つのメソッドを含めます)。

  public int timeDecrementFromZeroInt(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = 0; j > Integer.MIN_VALUE; j--) sum += j;
    }
    return sum;
  }
  public long timeDecrementFromZero(int reps) {
    long sum = rnd.nextLong();
    for (long i = 0; i < reps; i++) {
      for (long j = 0; j > Integer.MIN_VALUE; j--) sum += j;
    }
    return sum;
  }
  public long timeIncrementFromZero(int reps) {
    long sum = rnd.nextLong();
    for (long i = 0; i < reps; i++) {
      for (long j = 0; j < Integer.MAX_VALUE; j++) sum += j;
    }
    return sum;
  }
  public long timeDecrementToZero(int reps) {
    long sum = rnd.nextLong();
    for (long i = 0; i < reps; i++) {
      for (long j = Integer.MAX_VALUE; j >= 0; j--) sum += j;
    }
    return sum;
  }
  public long timeIncrementToZero(int reps) {
    long sum = rnd.nextLong();
    for (long i = 0; i < reps; i++) {
      for (long j = Integer.MIN_VALUE; j < 0; j++) sum += j;
    }
    return sum;
  }

結果:

 0% Scenario{vm=java, trial=0, benchmark=DecrementFromZeroInt} 978513000.00 ns; σ=14861284.82 ns @ 10 trials
20% Scenario{vm=java, trial=0, benchmark=DecrementFromZero} 2160652000.00 ns; σ=13825686.87 ns @ 3 trials
40% Scenario{vm=java, trial=0, benchmark=IncrementFromZero} 2153370000.00 ns; σ=6318160.49 ns @ 3 trials
60% Scenario{vm=java, trial=0, benchmark=DecrementToZero} 4379893000.00 ns; σ=8739917.79 ns @ 3 trials
80% Scenario{vm=java, trial=0, benchmark=IncrementToZero} 4383569000.00 ns; σ=5798095.89 ns @ 3 trials

           benchmark   ms linear runtime
DecrementFromZeroInt  979 ======
   DecrementFromZero 2161 ==============
   IncrementFromZero 2153 ==============
     DecrementToZero 4380 =============================
     IncrementToZero 4384 ==============================

主な結論:このような低レベルでのパフォーマンスについては、決して想定しないでください。完全なコードを記述し、全体としてテストします。これは、考慮していない他の何かが常に存在するため、テーブルが完全に変わるためです。

于 2012-12-07T19:32:57.953 に答える
4

CPU には、数値 (i) を 0 と比較する方法と、別の任意の数値 (n) と比較する方法の方が高速である可能性があります。これにより、理論的には減分バージョンが高速になります。

ただし、これは純粋に学術的なものです。どちらも基本的に「同じ」であるため、後でコードを保守する人にとってより論理的で理解しやすい方を実装する必要があります。

于 2012-12-07T19:29:23.880 に答える
2

答えは、それが何であるかに依存するということnです。カウント ダウンの場合、コードはn1 回だけアクセスする必要があります。カウントアップする場合、これは当てはまらない場合があります。したがって、たとえば、nvolatileフィールドである場合、またはループ本体の何かが の値を変更する可能性がある場合、nループのたびに値を調べる必要があります。これにより、ループが大幅に遅くなります。

このコードでは、カウントアップはカウントダウンよりも数百倍遅くなります。

public class Counts {
    private static final int ITERS = 100000;
    volatile int n = 1000;

    public long countUp() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = 0; i < n; ++i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }

    public long countDown() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = n - 1; i >= 0; --i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }
}
于 2012-12-07T19:56:51.410 に答える
2

ループを書くのが最も理にかなっている方法でループを書いてください。(a) プログラム全体で数ナノ秒の余分な時間が違いを生むほどタイム クリティカルなことを行っている、(b) コードが非常に最適化されているため、ボトルネックがインクリメント操作またはデクリメント操作である、ループ。

テスト後にプロファイリングで特定のループが問題であることがわかった場合は、そのループの最適化について心配し、インクリメントやデクリメントなどではなく、ループ本体に注目してください。

于 2012-12-07T19:28:34.397 に答える
0

測定可能な違いがある場合は、CPU レベルでは 0 との比較が高速であるため、0 との比較によるバリアントよりも高速です。ただし、ほとんどの場合、読みやすいコードを使用することをお勧めします

于 2012-12-07T19:38:36.233 に答える
0

他の誰かが何が起こっているのかを理解するのに必要な時間と比較すると、ほとんどの場合、時間の差は取るに足らないものです。従うのが最も簡単なものを使用してください。テストしたい場合は、次のように実行できます。

long startTime = System.nanoTime();  
long duration, endTime;  

for (int i=0;i<1000 ;i++ ) {  
        //function
   }  

endTime = System.nanoTime();  
duration = endTime - startTime;  

System.out.printf("The duration was %d.%03d microseconds%n", duration / 1000, duration % 1000); 

インクリメントとデクリメントの両方に。

より大きな問題は、ポストプリインクリメント/デクリメントです。ここの2ページの下部から始まるかなり良い説明があります:http://www.iar.com/Global/Resources/Developers_Toolbox/C_Cplusplus_Programming/Writing%20optimizer-friendly%20code.pdf

于 2012-12-07T19:40:34.733 に答える