3

の通常の実装Math.abs(x)(Oracle によって実装されている) は、次の式で与えられます。

public static double abs(double a) {
  return (a <= 0.0D) ? 0.0D - a : a;
}

数値の符号の 1 ビット コーディングを 0 (または 1) に設定する方が高速ではありませんか? 数値の符号をコーディングするビットは 1 つだけで、常に同じビットであると思いますが、これは間違っている可能性があります。

それとも、私たちのコンピューターは一般的に、原子命令で単一ビットの操作を行うのに適していませんか?

より高速な実装が可能であれば、それを提供できますか?

編集:

Java コードはプラットフォームに依存しないため、単一のマシンの不可分命令に依存することはできないと指摘されました。ただし、コードを最適化するために、JVM ホットスポット オプティマイザはマシンの詳細を考慮し、検討中の最適化そのものを適用する可能性があります。

ただし、簡単なテストを通じて、少なくとも私のマシンでは、Math.abs関数が単一の原子命令に最適化されていないように見えることがわかりました。私のコードは次のとおりです。

    long before = System.currentTimeMillis();
    int o = 0;
    for (double i = 0; i<1000000000; i++)
        if ((i-500)*(i-500)>((i-100)*2)*((i-100)*2)) // 4680 ms
            o++;
    System.out.println(o);
    System.out.println("using multiplication: "+(System.currentTimeMillis()-before));
    before = System.currentTimeMillis();
    o = 0;
    for (double i = 0; i<1000000000; i++)
        if (Math.abs(i-500)>(Math.abs(i-100)*2)) // 4778 ms
            o++;
    System.out.println(o);
    System.out.println("using Math.abs: "+(System.currentTimeMillis()-before));

次の出力が得られます。

234
using multiplication: 4985
234
using Math.abs: 5587

乗算が不可分命令によって実行されると仮定すると、少なくとも私のマシンでは、JVM ホットスポット オプティマイザーはMath.abs関数を単一の命令操作に最適化していないようです。

4

2 に答える 2

5

私が最初に考えたのは、それはNaN(Not-a-number) 値のためです。つまり、入力がNaN変更されずに返されるはずです。しかし、harold のテストでは、JVM の内部最適化が NaN の符号を保持しないことが示されているため (を使用しない限りStrictMath)、これは要件ではないようです。

Math.absのドキュメントには次のように書かれています。

つまり、結果は式の値と同じになります。 Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)

そのため、ビット操作のオプションはこのクラスの開発者に知られていましたが、彼らはそれをやめることにしました。

おそらく、この Java コードを最適化しても意味がないからです。ホットスポット オプティマイザは、ほとんどの環境で、ホットスポットで検出されると、その呼び出しを適切な FPU 命令に置き換えます。これは、多くのjava.lang.MathメソッドInteger.rotateLeftおよび同様のメソッドで発生します。それらは純粋な Java 実装を持っているかもしれませんが、CPU にそのための命令がある場合、それは JVM によって使用されます。

于 2013-10-29T11:38:14.067 に答える
1

私はJavaの専門家ではありませんが、問題はこの定義が言語で表現可能であることだと思います。float のビット操作はマシン形式に固有であるため、移植性がなく、Java では許可されていません。jit コンパイラのいずれかが最適化を行うかどうかはわかりません。

于 2013-10-29T10:55:33.047 に答える