プロが教えるわが家の防犯対策術!

+=と÷=の処理速度の謎を教えて下さい。

処理速度をQueryPerformanceCounterで調べていて気になったのですが、
変数A = 1; として以下の処理を100万回行いました。

疑問1
 A+=1; は A=1+1; より2~3割高速なのに
 A/=3; は A=1/3; より3倍弱処理が遅い事。

疑問2
 以前割算と掛算は、足し算と引き算の3倍遅いと聞いたものの
 A=1+1; A=1-1; A=1/3; A=3*3; がほぼ全て同速な事。

この2点なのですが、後者はただのガセだったのかもですが
前者の結果はどうにもふに落ちず・・。
もしかして後者は/=が遅い事をそう例えたのでしょうか?

何かお解りになられます方、
教えて頂けますと幸いです。

A 回答 (3件)

A=1+1; A=1-1; A=1/3; A=3*3;


こういうのはコンパイル前にあらかじめ計算されてしまいます
A=2; A=0; A=0; a=1;
としてコンパイルされるでしょう
ただの代入なので実行時間も同じになりますね
A=B+1; A=B-1; A=B/3; A=B*3;
のようにしたら差が出るかもしれません
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
そうなんですね。
実際下のようにやってみたら、2割ほど処理時間が増加しました。
教えていただきありがとうございます。

お礼日時:2010/07/21 07:07

> 疑問1


>  A+=1; は A=1+1; より2~3割高速なのに
>  A/=3; は A=1/3; より3倍弱処理が遅い事。

Aの型やどんな記憶域期間を持つかにもよりますが、int型の自動変数だと仮定した場合、通常はレジスタに割り付けられるので...

A+=1はインクリメント命令、A=1+1はA=2を意味する転送命令に展開されます。
このとき、転送命令ではオペランド分命令長が長くなりますので、それだけフェッチの時間が余分にかかります(プロセッサのアーキテクチャによっては、もう少し別の要素も絡んできます)。

A/=3は除算命令、A=1/3はA=0を意味する転送命令またはA^=Aのようなビット演算命令に展開されます。
除算命令は整数演算の中では最も時間がかかりますので、単純な転送やビット演算よりはずっと遅くなります。
なお、A/=2のように除数が2のべきである場合は、シフト命令になるので除算命令より高速になります。Aは符号なしの場合、負の値の処理が不要になるのでさらに高速になります。

> 疑問2
>  以前割算と掛算は、足し算と引き算の3倍遅いと聞いたものの
>  A=1+1; A=1-1; A=1/3; A=3*3; がほぼ全て同速な事。

A=1+1とA=3*3は、それぞれA=2とA=9を意味する転送命令に展開されます。
一方、A=1-1とA=1/3は、A=0を意味する転送命令またはA^=Aのようなビット演算命令に展開されます。
結果として、A=1-1やA=1/3の方が若干高速になる可能性はありますが、乗除算ほどの差は出ません。

この類の疑問を解消するには、コンパイル結果を実際に調べてみる必要があります。
コンパイラにアセンブリ言語のソースを出力させてもよいですが、命令長を知るには逆アセンブルする方が便利かもしれません。
    • good
    • 0
この回答へのお礼

詳しいご回答ありがとうございます。
コンパイル結果、展開される結果・・色々有るのですね。
逆アセンブル結果を読めれば、どんな内容に変換されたかがわかるのですね。

ご回答ありがとうございました。

お礼日時:2010/08/01 18:33

訂正


A=3*3; は A=9; としてコンパイルされるの間違いです
訂正ついでに
加算、減算はCPUにそのままの命令があるので速くなります
乗算、除算はCPU命令がない場合、加算、減算の繰り返しになるのでループの分遅くなるはずです
2の階乗の乗除算の場合は特別に最適化されてシフト演算に変換され高速になるかもしれません
(A /= 8 が A >>= 3; としてコンパイルされる)
    • good
    • 0
この回答へのお礼

追加のご回答ありがとうございます。
掛算はそうなるのですか。
加算と減算、乗算と除算、シフト演算 そういう内側の事情が有るのですね。
勉強になりました。とても今後の為になりそうです。
ありがとうございます。

お礼日時:2010/07/21 07:15

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています