[c#] Javaでの乗算や除算よりもビットシフトが高速ですか? 。ネット?



Answers

その塩の価値がある環境は、ほとんどあなたのためにこれを最適化します。 そして、そうでなければ、あなたは揚げるより大きな魚を持っています。 真剣に、 もう一度これについて考えてみてください。 パフォーマンス上の問題が発生したときには、そのことがわかります。 プロファイラを実行すると、その原因を知ることができ、それを修正する方法はかなり明確になります。

私のアプリケーションが遅すぎると、 x * 2をランダムにx << 1置き換えて、すべてが修正されました! パフォーマンスの問題は、同じ作業を1%高速化する方法を見つけることではなく、作業の規模を小さくする方法を見つけることで一般的に解決されます。

Question

2の累乗を使用している場合、左右のシフトビットは、乗算と除算操作よりも明らかに高速です。ただし、一部の読者や一部のアルゴリズムのコードの明瞭性を低下させる可能性があります。 パフォーマンスのためにビットシフトが本当に必要か、コンパイラやVMがケースに気付いて最適化する(特に2のべき乗がリテラルである場合)と期待できますか? 私は主にJavaと.NETの動作に興味を持っていますが、他の言語実装についての洞察も歓迎します。




私がテストしたコンピュータでは、整数の除算は他の演算より4〜10倍遅くなります

コンパイラが2の倍数で除算を行い、違いが見られない場合は、2の倍数で除算するとかなり遅くなります。

例えば、私は255で多くの多くの部門を持つ(グラフィックス)プログラムを持っています。実際に私の計算は:

r = (((top.R - bottom.R) * alpha + (bottom.R * 255)) * 0x8081) >> 23;

私は以前の計算よりもはるかに高速であることを保証することができます:

r = ((top.R - bottom.R) * alpha + (bottom.R * 255)) / 255;

そうではありません、コンパイラは最適化のすべてのトリックを行うことはできません。




私はちょうどこのコードを書いて、実際には2で乗算するよりも速度が遅いことに気づいたので、私は驚いています!

(編集:マイケルマイヤーズの提案後にコードがオーバーフローするのを修正しましたが、結果は同じです!何が間違っていますか?)

import java.util.Date;

public class Test {
    public static void main(String[] args) {
        Date before = new Date();
        for (int j = 1; j < 50000000; j++) {
            int a = 1 ;
            for (int i = 0; i< 10; i++){
                a *=2;
            }
        }
        Date after = new Date();
        System.out.println("Multiplying " + (after.getTime()-before.getTime()) + " milliseconds");
        before = new Date();
        for (int j = 1; j < 50000000; j++) {
            int a = 1 ;
            for (int i = 0; i< 10; i++){
                a = a << 1;
            }
        }
        after = new Date();
        System.out.println("Shifting " + (after.getTime()-before.getTime()) + " milliseconds");
    }
}

結果は次のとおりです。

639ミリ秒を掛ける
718ミリ秒シフト




ハードウェアに依存します。 私たちがマイクロコントローラやi386を話しているならば、シフトが速くなるかもしれませんが、いくつかの答えが述べるように、あなたのコンパイラは通常最適化を行います。

現代(Pentium Pro以降)のハードウェアでは、パイプライン処理はこれを完全に無関係にしています。暴落したパスから逸脱すると、得られるよりもはるかに多くの最適化が失われます。

マイクロ最適化はあなたの時間を無駄にするだけでなく、正しく取得することも非常に困難です。




ほとんどの場合、シフト演算に対する2のべき乗乗算の最適化に依存することができます。 これはコンパイラ構築の学生が学ぶ最初の最適化の1つです。 :)

しかし、私はこれについて何ら保証はないと思います。 オプティマイザに何をすべきかを伝えようとするのではなく、あなたのソースコードはあなたの意図を反映するべきです。 量を大きくする場合は、乗算を使用します。 ビットフィールドをある場所から別の場所に移動する場合(RGBカラー操作と考える)、シフト操作を使用します。 いずれにせよ、あなたのソースコードはあなたが実際にやっていることを反映します。




ほとんどのコンパイラは、必要に応じて乗算と除算をビットシフトに変換します。 これは、実行するのが最も簡単な最適化の1つです。 だから、あなたは、与えられた仕事のためにもっと読みやすく、適切なものをするべきです。






Related