12

Java コードの評価中に大きな問題が発生しました。問題を単純化するために、同じ奇妙な動作を生成する次のコードを書きました。重要なのは、メソッド run() と指定された double 値レートです。実行時テスト (メイン メソッド内) では、レートを 0.5 に設定したときと 1.0 に設定したときがあります。値が 1.0 の場合、if ステートメントは各ループ反復で実行され、値が 0.5 の場合、if ステートメントは半分だけ実行されます。このため、最初のケースではランタイムが長くなると予想していましたが、その逆です。誰か私にこの現象を説明できますか??

メインの結果:

Test mit rate = 0.5
Length: 50000000, IF executions: 25000856
Execution time was 4329 ms.
Length: 50000000, IF executions: 24999141
Execution time was 4307 ms.
Length: 50000000, IF executions: 25001582
Execution time was 4223 ms.
Length: 50000000, IF executions: 25000694
Execution time was 4328 ms.
Length: 50000000, IF executions: 25004766
Execution time was 4346 ms.
=================================
Test mit rate = 1.0
Length: 50000000, IF executions: 50000000
Execution time was 3482 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3572 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3529 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3479 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3473 ms.

コード

public ArrayList<Byte> list = new ArrayList<Byte>();
public final int LENGTH = 50000000;

public PerformanceTest(){
    byte[]arr = new byte[LENGTH];
    Random random = new Random();
    random.nextBytes(arr);
    for(byte b : arr)
        list.add(b);
}

public void run(double rate){

    byte b = 0;
    int count = 0;

    for (int i = 0; i < LENGTH; i++) {

        if(getRate(rate)){
            list.set(i, b);
            count++;
        }
    }
    System.out.println("Length: " + LENGTH + ", IF executions: " + count);
}

public boolean getRate(double rate){
    return Math.random() < rate;
}

public static void main(String[] args) throws InterruptedException {
    PerformanceTest test = new PerformanceTest();

    long start, end;
    System.out.println("Test mit rate = 0.5");
    for (int i = 0; i < 5; i++) {
        start=System.currentTimeMillis();
        test.run(0.5);
        end = System.currentTimeMillis();
        System.out.println("Execution time was "+(end-start)+" ms.");

        Thread.sleep(500);
    }       
    System.out.println("=================================");
    System.out.println("Test mit rate = 1.0");      
    for (int i = 0; i < 5; i++) {
        start=System.currentTimeMillis();
        test.run(1.0);
        end = System.currentTimeMillis();
        System.out.println("Execution time was "+(end-start)+" ms.");
        Thread.sleep(500);
    }   
}
4

3 に答える 3

10

最初のケースでは、分岐の予測ミスによりパフォーマンスが低下します。2 番目のケースはある程度の作業を行いますが、やや単純なので、プロセッサは次のステップを簡単に予測できます。詳細については、このウィキペディアのページを参照してください。

0.7 でテストしてみてください。私が正しければ、パフォーマンスは 0.5 から 1.0 の間のどこかになります。

于 2012-09-18T15:11:59.510 に答える
9

私のコメントに示されているように、分岐予測ミスの影響が見られることを確認するために、いくつかのテストを実行しました。テーブルには、レート (実行メソッドへの入力)、実行回数、ifおよび実行時間が表示されます。

0.0   0             1162
0.1   5,000,892     1204.25
0.2   10,002,410    1236.8
0.3   14,998,226    1264
0.4   19,996,983    1278
0.5   24,998,455    1305.5
0.6   29,998,879    1263.25
0.7   34,999,821    1232.25
0.8   39,999,414    1203.5
0.9   44,998,674    1202
1.0   50,000,000    1176.75

0.5 に近づくほど、分岐の予測ミスが多くなります (実行ごとに約 1 回)。0 または 1 に近づくほど、より正確な分岐予測が得られます (レートが 0 または 1 の場合、予測ミスはありません)。

そして、絵は千の言葉に値するからです:

ここに画像の説明を入力

于 2012-09-18T15:40:39.597 に答える
0

「並べ替えられた配列の処理が、並べ替えられていない配列よりも速いのはなぜですか?」によく似ています。そして、舞台裏にも同じ理由があります。

于 2012-09-18T15:34:30.597 に答える