1

私が書いているJavaコードに本当に奇妙なバグがあります。私が書いた並列コードを実行すると、完全に実行されますが、同じ実行で同じコードを複数回実行すると、実行時間は毎回遅くなります。

スレッド数を4から8に増やすと、反復ごとに速度が大幅に低下します。

各実行は完全に独立しています。古い実行をクリアするために、その間にランタイム変数をnullに設定しました。だから私はそれを遅くすることができるのか分かりません。Visual VMを使用していますが、.run()がすべての時間を「SelfTime」または「Thread.init()」に費やしていると表示されますが、これは役に立ちません。

コードのスニペット:

for (int r = 0; r < replicateRuns; ++r) {
    startTime = System.nanoTime();
    result = newRuntime.execute();
    result = null;
    System.out.println((System.nanoTime() - startTime) / 1000000);
    total += System.nanoTime() - startTime;
}

    parentThread = this;
    thread = new Thread[numberOfThreads];
    barrier = new CyclicBarrier(numberOfThreads);

    for (int i = 0; i < numberOfThreads; i++) {
        thread[i] = new Thread(new Runtime(parentThread, variation, delta, eta, i,
                numberOfThreads), i + "");
        thread[i].start();
    }

    for (int i = 0; i < numberOfThreads; i++) {
        try {
            thread[i].join();
            thread[i] = null;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

したがって、Javaアプリを何度も起動すると、まともな結果が得られる理由の手がかりはありますが、同じ起動内で何度も実行すると、すべてがnullになっていることがわかりますが、すべてが遅くなります。 GCが来て、それをクリーンアップします。

私はスレッドローカル変数を使用していますが、私が読んだことから、スレッド自体がnullに設定されると、それらはすべてクリーンアップされます。

助けてくれてありがとう!

編集1:

すべての助けをありがとう。プロットが厚くなり、(MacBookとは対照的に)Windowsデスクトップではまったく問題がなく、実行回数を増やしても、各スレッドは正常に実行され、途中で速度が低下することはありません。これを1日見つめた後、朝一番にEclipseMATで再試行します。

ソースに関しては、MOEADの並列バージョンでMOEAフレームワークを拡張しているため、多くの依存関係とクラスがあります。MOEAフレームワーク私のクラスのソースはここにあります。基本的に、numberOfEvaulationsが設定された数値に達するまで、反復が繰り返し呼び出されます。

4

2 に答える 2

1

みんながここで言っている問題は、スレッドを正しい方法で「停止」していないということだと思います。

私の経験では、状態をスレッドのブール変数に格納するのが最善の方法ですisRunning。次に、ループ内でisRunningフラグの状態をテストします。つまり、

//inside the run method
while(isRunning){
//your code goes here
}

このようにして、ループの各反復でフラグの現在の状態をチェックしているため、たとえばカスタムstop()メソッドでフラグを「false」に設定する場合があります。ループの次の繰り返しにより、スレッドはそのrunメソッドを終了し、スレッドの寿命が終わります。技術的には、これでガベージ コレクションの準備が整いました。コードのどこかにぶら下がっているこの脅威への参照がないことを考えると、メモリは近い将来のある時点で割り当て解除されます。

このアプローチを示すソースは他にもあります。たとえば、LinkedIn のこのディスカッションをご覧ください。

newRuntime補足として、または変数、そのクラス、継承などを正確に確認することは実際に役立ちresultます。それ以外の場合は、コードで実際に何が起こっているかを推測することしかできません。

于 2012-12-17T12:26:30.460 に答える
0

常に新しいスレッドを生成し、それらを破棄することはありません。スレッドの数がプロセッサ コアの数よりも多い場合、スレッドを切り替える必要があり、パフォーマンスが約 1000 分の 1 に低下する可能性があります。Netbeans IDE を使用している場合は、プロファイラーでスレッドとそのステータスを確認できます。

于 2012-12-17T12:38:10.780 に答える