Math.pow(int、int)が私の素朴な実装よりも遅いのはなぜですか?

ウッドローバーロウ

昨日、なぜMath.pow(int,int)こんなに遅いのかという質問を見ましたが、言葉が貧弱で研究努力も見られなかったので、すぐに締め切られました。

私は自分で少しテストを行ったところMath.pow、整数引数を処理するときにメソッドが実際に自分のナイーブな実装(特に効率的な実装でさえない)と比較して非常に遅く実行されることがわかりました以下は、これをテストするために実行したコードです。

class PowerTest {

    public static double myPow(int base, int exponent) {
        if(base == 0) return 0;
        if(exponent == 0) return 1;
        int absExponent = (exponent < 0)? exponent * -1 : exponent;
        double result = base;
        for(int i = 1; i < absExponent; i++) {
            result *= base;
        }
        if(exponent < 1) result = 1 / result;
        return result;
    }

    public static void main(String args[]) {
        long startTime, endTime;

        startTime = System.nanoTime();
        for(int i = 0; i < 5000000; i++) {
            Math.pow(2,2);
        }
        endTime = System.nanoTime();
        System.out.printf("Math.pow took %d milliseconds.\n", (endTime - startTime) / 1000000);

        startTime = System.nanoTime();
        for(int i = 0; i < 5000000; i++) {
            myPow(2,2);
        }
        endTime = System.nanoTime();
        System.out.printf("myPow took %d milliseconds.\n", (endTime - startTime) / 1000000);
    }

}

私のコンピューター(Intel x86_64 cpu上のLinux)では、ほとんどの場合、出力には10ミリ秒かかり、2ミリ秒Math.powかかると報告されていましたmyPowこれは時々ミリ秒単位で変動しましたが、平均Math.powして約5倍遅くなりました。

私はいくつかの研究を行なったし、によるとgrepcodeMath.pow唯一の型シグネチャを持つメソッドを提供しています(double, double)、そしてそれはにそれを延期StrictMath.powネイティブメソッド呼び出しである方法。

Mathライブラリpowがdoubleを処理する関数のみを提供しているという事実は、この質問に対する可能な答えを示しているようです。明らかに、double型の底または指数の可能性を処理する必要があるべき乗アルゴリズムは、整数のみを処理する私のアルゴリズムよりも実行に時間がかかります。ただし、最終的には、アーキテクチャに依存するネイティブコード(ほとんどの場合、JVMバイトコード(私の場合はCまたはアセンブリ)よりも高速に実行されます)に要約されます。このレベルでは、データ型をチェックし、可能であればより単純なアルゴリズムを実行するために最適化が行われるようです。

この情報を考えると、整数引数が与えられたときに、ネイティブMath.powメソッドが最適化されていないナイーブなmyPowメソッドよりも一貫してはるかに遅く実行されるのはなぜですか?

トビー

他の人が言っているようにdouble、浮動小数点演算はほぼ確実に遅くなるため、の使用を無視することはできませんただし、これが唯一の理由ではありません。実装を変更してそれらを使用する場合でも、より高速です。

これは、の二つである:最初にそれである2^2(指数ではなく、XOR)を実行するために非常に速い計算がある、あなたのアルゴリズムはそのために使用する結構ですので-から2つの値を使用してみてくださいRandom#nextInt(またはnextDouble)、あなたはそれが表示されますMath#powですが、実際にははるかに高速です。

もう1つの理由は、ネイティブメソッドの呼び出しにはオーバーヘッドがあり、2^2計算が非常に速くMath#pow、何度も呼び出すためここでは実際に意味がありますJNI呼び出しが遅くなる理由を参照してください詳細については。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

math.powがネイティブにintを処理できないのはなぜですか?(床/天井も)

分類Dev

Python 2.xでmath.factorialが3.xよりもはるかに遅いのはなぜですか?

分類Dev

Python 2.xでmath.factorialが3.xよりもはるかに遅いのはなぜですか?

分類Dev

math.Pow10(e int)がint64ではなくfloat64を返すのはなぜですか?

分類Dev

Math.cbrt(1728)がMath.pow(1728、1 / 3)よりも正確な結果を生成するのはなぜですか?

分類Dev

Math.imul()が、入力が少ない通常の乗算(*)よりも速く、多くの場合は遅いのはなぜですか?

分類Dev

なぜMath.pow私に正しい値を返さないのですか?

分類Dev

「1Math.pow2」がscalaで機能しないのはなぜですか?

分類Dev

GCCがC <math.h>よりもC ++ <cmath>に対してisnan()をより効率的に実装するのはなぜですか?

分類Dev

Javaの結果は(int)Math.pow(2、x)と1 << xで異なります

分類Dev

Math.pow(0、0)=== 1なのはなぜですか?

分類Dev

Math.pow()がJavaScriptの**と等しくない場合があるのはなぜですか?

分類Dev

Math.pow(long、(1/3))が常に1を返すのはなぜですか?

分類Dev

(int)Math.random()* 10がJavaで10を生成しないのはなぜですか?

分類Dev

Math.pow(x、y)がDoubleとして数えるのはなぜですか?

分類Dev

Math.powのJavaScript実装

分類Dev

Java.Lang.Mathが抽象的でないのはなぜですか?

分類Dev

Math.floor(float)がないのはなぜですか?

分類Dev

なぜpow(int、int)はとても遅いのですか?

分類Dev

なぜpow(int、int)はとても遅いのですか?

分類Dev

Math.Pow()は.NET Frameworkでどのように実装されていますか?

分類Dev

Math.powを使用してこのコードが「HELLO WORLD」を出力するのはなぜですか?

分類Dev

math.powが正しい答えを返すのに、numpy.powerが小さな指数に対して0を返すのはなぜですか?

分類Dev

math.MaxInt64がint32として推定されるのはなぜですか?

分類Dev

Go定数で「math.Sin」が許可されないのはなぜですか?

分類Dev

Math.atan2が正しく機能しないのはなぜですか?

分類Dev

JavascriptのMath.pow()がCの同じ値と比較して、丸められた値を返すように見えるのはなぜですか?

分類Dev

inputValのMath.pow()

分類Dev

Math.floorがdoubleを返すのはなぜですか?

Related 関連記事

  1. 1

    math.powがネイティブにintを処理できないのはなぜですか?(床/天井も)

  2. 2

    Python 2.xでmath.factorialが3.xよりもはるかに遅いのはなぜですか?

  3. 3

    Python 2.xでmath.factorialが3.xよりもはるかに遅いのはなぜですか?

  4. 4

    math.Pow10(e int)がint64ではなくfloat64を返すのはなぜですか?

  5. 5

    Math.cbrt(1728)がMath.pow(1728、1 / 3)よりも正確な結果を生成するのはなぜですか?

  6. 6

    Math.imul()が、入力が少ない通常の乗算(*)よりも速く、多くの場合は遅いのはなぜですか?

  7. 7

    なぜMath.pow私に正しい値を返さないのですか?

  8. 8

    「1Math.pow2」がscalaで機能しないのはなぜですか?

  9. 9

    GCCがC <math.h>よりもC ++ <cmath>に対してisnan()をより効率的に実装するのはなぜですか?

  10. 10

    Javaの結果は(int)Math.pow(2、x)と1 << xで異なります

  11. 11

    Math.pow(0、0)=== 1なのはなぜですか?

  12. 12

    Math.pow()がJavaScriptの**と等しくない場合があるのはなぜですか?

  13. 13

    Math.pow(long、(1/3))が常に1を返すのはなぜですか?

  14. 14

    (int)Math.random()* 10がJavaで10を生成しないのはなぜですか?

  15. 15

    Math.pow(x、y)がDoubleとして数えるのはなぜですか?

  16. 16

    Math.powのJavaScript実装

  17. 17

    Java.Lang.Mathが抽象的でないのはなぜですか?

  18. 18

    Math.floor(float)がないのはなぜですか?

  19. 19

    なぜpow(int、int)はとても遅いのですか?

  20. 20

    なぜpow(int、int)はとても遅いのですか?

  21. 21

    Math.Pow()は.NET Frameworkでどのように実装されていますか?

  22. 22

    Math.powを使用してこのコードが「HELLO WORLD」を出力するのはなぜですか?

  23. 23

    math.powが正しい答えを返すのに、numpy.powerが小さな指数に対して0を返すのはなぜですか?

  24. 24

    math.MaxInt64がint32として推定されるのはなぜですか?

  25. 25

    Go定数で「math.Sin」が許可されないのはなぜですか?

  26. 26

    Math.atan2が正しく機能しないのはなぜですか?

  27. 27

    JavascriptのMath.pow()がCの同じ値と比較して、丸められた値を返すように見えるのはなぜですか?

  28. 28

    inputValのMath.pow()

  29. 29

    Math.floorがdoubleを返すのはなぜですか?

ホットタグ

アーカイブ