Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

アルゴリズム

今日は。
if (a == x) {
    ......
} else {
    ......
}



if (a != x) {
    ......
} else {
    ......
}

だと
どっちが速いですか?

11

回答

78720

閲覧

11件の回答

評価

0

forループで==バージョンと!=バージョンをそれぞれ繰り返しまわして実行してみて、そちらが速いか計測してみたらどうでしょう??

評価

0

実験することは良いことなので、それ自体は否定しませんが…。

そういう瑣末なことは、少なくとも最初のうちは考えても仕方ないものです。
処理の意味、ソースとしての見通しの良さを考えましょう。

一例として、ブロックの小さい順に並べると、ソースとして見やすいものになります。

評価

0

じゃーん!
実験結果を発表します。
コードは↓
public class ASample {

    /**
     * @param args
     */
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        long start, stop;
        start = System.currentTimeMillis();
        for (int i =0; i < 10000; i++) {
            Super.func1();
        }
        System.out.println("\n");
        stop = System.currentTimeMillis();
        System.out.println("func1()---" + (stop-start));

        start = System.currentTimeMillis();
        for (int i =0; i < 10000; i++) {
            Super.func2();
        }
        System.out.println("\n");
        stop = System.currentTimeMillis();
        System.out.println("func2()---" + (stop-start));
        

    }
}

class Super {
    static int a = 1, x = 1;
    static void func1() {
        if (a == x) {
            System.out.print("A");
        } else {
            System.out.print("A");
        }
    }
    static void func2() {
        if (a != x) {
            System.out.print("A");
        } else {
            System.out.print("A");
        }
    }

}
結果は
なんと、、、、、、
一緒でした。
skさん、実験のヒントありがとうございます。
mioさん、初心者は最適化するべからずですね?
深いです。ありがとうございます。

評価

0

やまさん(さん)結果発表おつかれさまです。
うーん、でもこのプログラムには問題がありますね

高速な!=と==を比べるのに低速なかつパソコンの状態に大きく左右されるSystem.out.printとか(スクロールするしないとか)使ってはいけませんね。
System.out.printの速度を測っているようなものです。

それから、条件が一律なのもいただけません。
もう少し工夫すると!=と==の速度が測れると思いますよ。

あと10回計測の平均値を表示するとかですね。

研究熱心なやまさんに敬意を表して指摘させてもらいました。
がんばってください。

評価

0

じゃーん!
お待たせしました。
tamaさんの言ってる意味はすごく重要でした。
まず、
2006-09-07 21:10を低速ノートで実験しました。

>それから、条件が一律なのもいただけません。
x=1の場合と、x=0の場合で実験しました(3回)。
実験結果↓

x=1の場合、
func1---251 250 350
func2---150 170 171

x=0の場合
func1---260 250 261
func2---200 201 170

なるほど、、、、
そして、次のコードでも実験↓
public class ASample {

    public static void main(String[] args) {
        
        long start, stop;
        
        start = System.currentTimeMillis();
        for (int i =0; i < 100000; i++) {
            Super.func1();
        }
        stop = System.currentTimeMillis();
        System.out.println("func1()---" + (stop-start));

        start = System.currentTimeMillis();
        for (int i =0; i < 100000; i++) {
            Super.func2();
        }
        stop = System.currentTimeMillis();
        System.out.println("func2()---" + (stop-start));
    }
}

class Super {
    static int cnt1, cnt2;
    static int a = 1, x = 0;
    static void func1() {
        if (a == x) {
            cnt1++;
        } else {
            cnt1++;
        }
    }
    static void func2() {
        if (a != x) {
            cnt2++;
        } else {
            cnt2++;
        }
    }
}
実験結果
x=1の場合
func1---10 10 10 
func2--- 0 10  0

x=0の場合
func1---20  0 10
func2--- 0  0  0

なるほど、!= のほうが == より速い?のか。
tamaさん、アドバイス感謝します。

ちょっとした疑問が、、いい勉強になりました。
これが将来役に立つといいが、、、。

評価

0

誤差の範囲内のような気もするけどなあ・・。
計測した時間単位はmsecなんでしょ?

真と偽の時間差が厳密に(nsec単位とかで)どう違うかなんてのはコードレベルでコンパイラ次第でしょう。
(実行時ではプロセッサの状態とかにもよる)
コンパイラ,バージョンが変われば平気で逆転したりしてもおかしくない筈。

>一例として、ブロックの小さい順に並べると、
は、ホンの一例という意味だと思ってますけど、
別の一例とすれば、

・簡素化できるならなるべく簡素化する。

・例えばエラーで除外するものとか、早期に処理を終えてメソッドから抜けるものを優先して先にするとか、条件判断の順序に一貫性を持たせるとかいうのも一例。
かなり好みが関わると思うけど、早めに抜けてしまうものはサッサと抜けさせると、続くフローの主流において頭から除外できるとか。

・この実験?とかではあまり見えてこないけど、if〜else if〜が続くと後ろにあるものほど、各判定分遅くなる。
通常、一番真になる回数が多いものを最初に書くとか・・条件の組み合わせとかを踏まえて。

でも、やるならアプリが完成した後にパフォーマンステストなりして、遅い!と思えてからチューニングすべきもので、コードを起こしているうちに気にしても・・それが明らかなものでもなければ・・あまり意味ないかなと。

Javaではどうなるのか判らないけど、例えばCではifよりswitchの方が速い場合とかいうのもあります。
しかし、それはコンパイラによりで全てに通用するものではないし、Javaなりでも、同じコンパイラを使い続け、多くの経験を積んだ上で、経験と感とかにより決められる(ような気がする)とかでもなければ、コードを書いている段階であまりのめり込んでも得られるものは少ないのではないかと・・。

書いているロジックに無駄になっている部分がないかとか、1つ1つのコードに変な無駄をしてないかとかが、コードを書きながら自然に頭の中に浮かぶようであれば、そういったのはやれるならやらないよりはやれた方がいいかもですけどね。

評価

0

結果が私の予想と違っていたので^^;自分でも実験してみました。

まあさんの言われるようにコンパイラやVMの仕様によって大きく変わるのでしょうし、最近のCPUは分岐予測機構やパイプラインによってJZやJNZのマシン語の必要クロック数などはあまり意味をもたなくなっているので、私の予想では同じくらいになると思っていました・・

やまさんの下のプログラムのループ回数を3桁増やして実験したところ。
X=0の場合ほぼ同じ
X=1の場合==が若干速い
という結果になりました。

うーん微妙
疑問をもって実験する心意気は大切ですし、技術者としてはそうあるべきだと思います、これからもがんばりましょう。

mioさんやまあさんが言われるように無駄のないロジックをまず考えるべきで、要求パフォーマンスに問題が出てくれば最適化を行い、無ければ可読性を重視して書いていけばいいと思います。

評価

0

tamaさん
まあさん
ご指摘ありがとうございます。
今回は本当に勉強になりました。

・今回のmy実験結果はtamaさんの言われるとおり
>うーん微妙

自分なりに
まあさん(2006-09-08 09:45)
tamaさん(2006-09-08 10:30)
の回答を整理して、
myNote.docに保存します。
参考書では手に入れられない情報がGETできたことは、
感激もので、まさかちっさな疑問がここまで広がるとは思いませんでした。

mioさんも最初に指摘されてましたが、
最終的に重要なことがわかったような気がします。

どうもありがとうございます。

評価

0

今回の実験に関して補足してみれば、

まずマルチタスクなOSを使っていますよね?
そしてこの実験の場合、タイムスライスが発生している筈です。
そのスライス時間は昔から変わってないみたいですけど、大抵10msec。Winでどう設定されているかは知らないけど。
つまり、(10msecは正確にではなく延びもするし縮みもするけど)たまたま他のタスクに取られることになった時間分誤差が出ます。
なので、単純に比較するのは非常に難しいと思います。
例え無視できるだけの長い時間でサンプリングしたとしても今の実験では誤差は累積します。
その累積を取り除けばいいわけですが、この実験自体があまり意味無さそうに思うので、何かの時にその方法を考えてみるといいでしょう。

といったようなところが、実験コードと時間単位はmsec?というところからの話。


疑問を持つこと、それを考えつきとめようとするのは、最近かなり少ないみたいだし、その気があるというのは珍しくもあり?、いいことだと思います。
欲を言えば、時間を費やす価値があることかとかいうことも考える力も付いてくれば・・。
それには(経験を積んだ)先輩とかの存在もあったりしますし。

"いや、絶対に違う。その答えを探し出してやる"とか言うのもありですけどね。
必ずしも先輩・著名人?とかが正しいことだけを言っているとは限らないので。

評価

0

>欲を言えば、時間を費やす価値があることかとかいうことも考える力も付いてくれば・・。

同感です。

今回は、私にとって得るものは大きかったです。
次回?は、回答してくださる皆様が、わざわざ時間を費やしてもいいと思ってもらえる実験(そんなのあるのかどうか?)をするようにします。

By やまさん

評価

0

>回答してくださる皆様が、わざわざ時間を費やしてもいいと思ってもらえる

それを判断することはかなり難しいと思うし、考えなくていいんではないかと。

>そんなのあるのかどうか?

意欲がある限りは一生掛けても終わらないほどの材料があると思いますよ。
本や人から聞いて解っても、実験してみて本当に解るということもあるし。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。