3

一言で言えば私のプログラム:

int の配列に対していくつかの並べ替えアルゴリズムを連続して実行し、それぞれのタイミングを計るプログラムがあります。GUI を使用すると、ユーザーは配列サイズと、ソートする配列を満たすさまざまな乱数範囲を選択できます。[並べ替え] ボタンをクリックするたびに、ユーザーの配列値が取得され、新しい配列が作成されます。次に、.clone().

問題:

「並べ替え」ボタンをもう一度クリックすると、並べ替えが改善されます。

どこかで、私には理解できない最適化が行われています。

これが問題である理由: ユーザーが配列の設定を変更せずに並べ替えメソッドを再度実行した場合、新しい乱数で新しい配列が構築されることは事実ですが、乱数の範囲は同じままであるため、実行時間が長くなります。 125k のリストでは、ほぼ同じままである必要があります.... 300% 改善されません。

ここに私が直面していることのデモプログラムがあります。問題を示すために、Java のネイティブな並べ替えを 1 つだけ使用します。また、ソートされるランダムな int 配列を構築するためにハードコードされた値を使用しますが、「Enter」キーを押すたびにそうします。ここでも同じ「エラー」が発生しているため、このシミュレーションは私のプログラムを正確に反映していると思います。

ソートが 2 回目に高速になるのはなぜですか?

...配列は実行ごとに新しい値で再構築されますが、どうすれば高速化できるのでしょうか?

package sortTooFast;

import java.util.Arrays;
import java.util.Scanner;

public class SortTooFast {
    public static final int ARRAY_SIZE = 500000;
    public static final int MIN_RANGE = 0;
    public static final int MAX_RANGE = 100;
    public static final int INCLUSIVE = 1;
    
    int[] sortingArray;

    public static void main(String[] args) {
        SortTooFast test = new SortTooFast();
        test.run();
    }
    
    // Run program.
    public void run(){
        while(true){    
            
            // Assign int[] filled with random numbers.
            sortingArray = getArray();                  

            // Inform user.
            System.out.println("\nPress return key to run sort!");
            
            // Wait for user.
            new Scanner(System.in).nextLine();
            
            System.out.println("First 15 elements to be sorted:");
            
            // Print a small section of the array; prove not sorted
            for (int i = 0; i < 15; i++){
                System.out.printf("%4d", sortingArray[i]);
            }
            
            // Perform sort.
            runNativeSort(sortingArray);
        }
    }

    // Run native java sort.
    private void runNativeSort(int[] array) {
        // Start timer
        long startTime = System.currentTimeMillis();
        
        // Perform sort.
        Arrays.sort(array);
        
        // End timer
        long finishTime = System.currentTimeMillis();
        
        // Running time.
        long runTime = finishTime - startTime;
        
        // Report run time.
        System.out.println("\nRun time: " +runTime);        
    }

    // Obtain an array filled with random int values.
    private int[] getArray() {
        // Make int array.
        int[] mArray = new int[ARRAY_SIZE];
        
        // Length of array.
        int length = mArray.length;
        
        // Fill array with random numbers.
        for(int counter = 0; counter < length; counter++){
            int random = MIN_RANGE + (int)(Math.random() * ((MAX_RANGE - MIN_RANGE) + INCLUSIVE));
            mArray[counter] = random;
        }
        return mArray;
    }
}
4

1 に答える 1

9

ソートが 2 回目に高速になるのはなぜですか?

その時までに、JIT はバイトコードをより高速なネイティブ コードに最適化したからです。

この種のものをベンチマークする際に対抗する必要がある 2 つの影響があります。

  1. そもそもコードを JIT するのにかかった時間
  2. JIT による最適化がますます難しくなるにつれて、ネイティブ コードが時間の経過とともに改善される方法。

通常、タイミングを開始する前にコードを完全に最適化するのに十分な時間コードを実行することで、この影響を減らして安定した状態を実現できます。

さらに、ベンチマークSystem.nanoTimeの代わりに使用する必要があります。これは、経過を測定するために特別に設計されているのに対し、時計が同期していないことに気付いた場合にオペレーティングシステムによって調整される可能性がある、かなり正確な「ウォールクロック」時間を提供することを目的としていますシステムクロックの変更に関係なく、特定の瞬間からの時間。System.currentTimeMillisSystem.currentTimeMillisnanoTime

于 2013-07-21T15:49:31.843 に答える