94

Surface Pro 2 タブレットで Windows 8.1 x64 と Java 7 update 45 x64 (32 ビット Java はインストールされていません) を実行しています。

以下のコードは、i の型が long の場合は 1688 ミリ秒、i が int の場合は 109 ミリ秒かかります。64 ビット JVM を使用した 64 ビット プラットフォームで long (64 ビット型) が int よりも桁違いに遅いのはなぜですか?

私の唯一の憶測は、CPU が 32 ビット整数よりも 64 ビット整数を追加するのに時間がかかるということですが、それはありそうにないようです。Haswell はリップル キャリー加算器を使用していないと思われます。

これを Eclipse Kepler SR1 で実行しています。

public class Main {

    private static long i = Integer.MAX_VALUE;

    public static void main(String[] args) {    
        System.out.println("Starting the loop");
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheck()){
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Finished the loop in " + (endTime - startTime) + "ms");
    }

    private static boolean decrementAndCheck() {
        return --i < 0;
    }

}

編集: これは、VS 2013 (以下)、同じシステムによってコンパイルされた同等の C++ コードの結果です。long: 72265ms int: 74656ms これらの結果は、デバッグ 32 ビット モードでのものでした。

64 ビット リリース モードの場合:長い: 875mslong long: 906ms int: 1047ms

これは、私が観察した結果が、CPU の制限ではなく、JVM 最適化の奇妙さであることを示唆しています。

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "limits.h"

long long i = INT_MAX;

using namespace std;


boolean decrementAndCheck() {
return --i < 0;
}


int _tmain(int argc, _TCHAR* argv[])
{


cout << "Starting the loop" << endl;

unsigned long startTime = GetTickCount64();
while (!decrementAndCheck()){
}
unsigned long endTime = GetTickCount64();

cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl;



}

編集:Java 8 RTMでこれをもう一度試しましたが、大きな変化はありません。

4

8 に答える 8

1

これは、JVM が long の使用時にセーフポイントをチェックし (カウントされないループ)、int に対してはチェックしない (カウントされたループ) ためである可能性があります。

参考文献: https://stackoverflow.com/a/62557768/14624235

https://stackoverflow.com/a/58726530/14624235

http://psy-lob-saw.blogspot.com/2016/02/wait-for-it-counteduncounted-loops.html

于 2020-11-12T08:40:12.003 に答える
0

私はテストする 64 ビット マシンを持っていませんが、かなり大きな違いは、わずかに長いバイトコード以上のものがあることを示唆しています。

私の 32 ビット 1.7.0_45 では、long/int (4400 ミリ秒と 4800 ミリ秒) の時間が非常に近いことがわかります。

これは推測にすぎませんが、メモリのミスアライメント ペナルティの影響であると強く疑っています。疑いを確認/否定するには、public static int dummy = 0; を追加してみてください。i の宣言の前。これにより、メモリ レイアウトで i が 4 バイト押し下げられ、適切に配置されてパフォーマンスが向上する場合があります。問題の原因ではないことを確認しました。

編集:これの背後にある理由は、VM が、JNI に干渉する可能性があるため、最適な位置合わせのためにパディングを追加して、余暇にフィールドを並べ替えない可能性があるためです。(そうではありません)。

于 2013-11-07T19:23:39.397 に答える