C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

32と64ビットプログラムの速度差

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■83163 / inTopicNo.1)  32と64ビットプログラムの速度差
  
□投稿者/ 拓殖 (1回)-(2017/03/09(Thu) 11:35:01)

分類:[.NET 全般] 

VB.NETを使って、
Byte、Short、Integer、Long、Single、Doubleに関して
bbb = aaa * aaa
という計算を1,000,000,000回Forループで繰り返した計算時間を32と64ビットで比較を行いました。
以下が結果です。

左が32ビット、右が64ビット
Byte		2.2秒		2.3秒
Short		2.2秒		2.3秒
Integer		2.2秒		2.3秒
Long		9.1秒		2.3秒
Single		1.8秒		2.4秒
Double		1.8秒		2.3秒


32ビットの場合、IntegerやSingleなどの4バイトに特化されており、
それ以下のByteやShortはIntegerが内包したような計算になっている
という情報をどこかで見かけました。
そのため、Byte、Short、Integerで速度差が見られず
Longだけが遅くなりました。

64ビットの場合、LongやDoubleなどの8バイトに特化されているため、
Byte、Short、Integer、Longで速度差が見られない結果となりました。

これは理解できます。

一方で、
32ビットでSingleとDoubleに速度差が見られなかった理由と、
Byte、Short、Integer、Longなどの整数よりも
Single、Doubleなどの浮動小数点の方がなぜか高速になった理由を教えていただけないでしょうか?

それと、Long型を除いて
32よりも64ビット型の方が遅くなる結果となっていますが、
これはなぜなのでしょうか?
一般的に32と64ビット型でプログラムの実行速度に違いが見られないか
若干64ビットの方が速くなると言われますが
64ビット型で32と同じ速度にする方法があれば教えてください。




引用返信 編集キー/
■83164 / inTopicNo.2)  Re[1]: 32と64ビットプログラムの速度差
□投稿者/ furu (87回)-(2017/03/09(Thu) 12:35:51)
今のCPUに詳しくはないのであくまで推測です。

No83163 (拓殖 さん) に返信
> 32ビットでSingleとDoubleに速度差が見られなかった理由
Singleは、メモリに保存する精度がSingleであり
計算用コプロセッサ内では、Doubleの場合と同じ精度で
計算をしている。

> Byte、Short、Integer、Longなどの整数よりも
> Single、Doubleなどの浮動小数点の方がなぜか高速になった理由
計算用コプロセッサにさせているので、CPUの時間を使っていない。

> それと、Long型を除いて
> 32よりも64ビット型の方が遅くなる結果となっていますが、
> これはなぜなのでしょうか?
誤差範囲内ですかね。

引用返信 編集キー/
■83168 / inTopicNo.3)  Re[1]: 32と64ビットプログラムの速度差
□投稿者/ PANG2 (160回)-(2017/03/09(Thu) 13:07:02)
No83163 (拓殖 さん) に返信
> VB.NETを使って、
> Byte、Short、Integer、Long、Single、Doubleに関して
> bbb = aaa * aaa
> という計算を1,000,000,000回Forループで繰り返した計算時間を32と64ビットで比較を行いました。
> 以下が結果です。

どのような方法で計測したのでしょうか?
Forループのコストを差し引いているでしょうか?
引用返信 編集キー/
■83170 / inTopicNo.4)  Re[2]: 32と64ビットプログラムの速度差
□投稿者/ 拓殖 (2回)-(2017/03/09(Thu) 13:20:12)
Forループのコストは差し引いていませんが、
相対時間だけは議論できると思います。
 
引用返信 編集キー/
■83172 / inTopicNo.5)  Re[3]: 32と64ビットプログラムの速度差
□投稿者/ 774RR (482回)-(2017/03/09(Thu) 14:47:40)
ildasm で C# のコンパイル結果を読むと IL レベルでは型によって差が無いので
あとは IL を CLI がどうネィティブ命令に翻訳するかで違ってくるわけだが

x86 や x64 に話を限定するなら single 専用の演算命令というのは存在しない。
浮動小数点数演算自体は double で行われて結果を single 範囲に収める仕様。
なので single のほうが double より遅いか、同じになるのは予想の範囲。

double と int とで速度が違うとしたら loop の unroll 状況等の違いがあるかもしれない。
Visual Studio 2005 の C++ で同等のコードをコンパイルしたら
double は fmul 命令を unroll 10回してループ回数が 1/10 になっていたのに対して
unsigned long では imul 命令を1回生成して忠実にループ回数回っていたので、
double のほうが高速だった。
その意味で「ループのコスト」は考察に入れないと判断を誤ると思われる。


引用返信 編集キー/
■83180 / inTopicNo.6)  Re[4]: 32と64ビットプログラムの速度差
□投稿者/ なちゃ (177回)-(2017/03/10(Fri) 00:16:42)
64ビットだと命令サイズが大きくなるなどで単純に効率が悪くなるというシンプルな理由もよくある話のような。
引用返信 編集キー/
■83200 / inTopicNo.7)  Re[5]: 32と64ビットプログラムの速度差
□投稿者/ 拓殖 (4回)-(2017/03/12(Sun) 11:40:13)
No83180 (774RR さん) に返信

Dim sss5 As Integer = 5
Dim sss6 As Integer = 5


Dim sss13 As Double = 5
Dim sss14 As Double = 5


sss6 = sss5 * sss5
だけForループを繰り返すと2.2秒

sss14 = sss13 * sss13
だけForループを繰り返すと1.8秒

になるのに


sss6 = sss5 * sss5
sss14 = sss13 * sss13

と2つをForループで回すと足し算した4.0秒ではなく
1.6秒となり、それぞれを回した時よりもなぜか速くなる結果が得られました。

何度か試したみたのですがやはり速くなってしまいます。

一体これはなぜなのでしょうか?

fmul unroll のワードで検索をかけてみたのですが
分かりやすい解説ページが見つかりませんでした。

Forループ分の計算コストを見積もるためには
どのようにすれば良いのでしょうか?



引用返信 編集キー/
■83201 / inTopicNo.8)  Re[6]: 32と64ビットプログラムの速度差
□投稿者/ 拓殖 (5回)-(2017/03/12(Sun) 11:44:26)
https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%97%E5%B1%95%E9%96%8B

ここに解説ページがありました。

こういうことが自動的に行われる場合と行われない場合があるのですね。

いったいどうすればForループ分の計算コストを見積もることができるのでしょうか?

引用返信 編集キー/
■83202 / inTopicNo.9)  Re[6]: 32と64ビットプログラムの速度差
□投稿者/ なちゃ (178回)-(2017/03/12(Sun) 12:11:59)
No83200 (拓殖 さん) に返信
> ■No83180 (774RR さん) に返信
>
> Dim sss5 As Integer = 5
> Dim sss6 As Integer = 5
>
>
> Dim sss13 As Double = 5
> Dim sss14 As Double = 5
>
>
> sss6 = sss5 * sss5
> だけForループを繰り返すと2.2秒
>
> sss14 = sss13 * sss13
> だけForループを繰り返すと1.8秒
>
> になるのに
>
>
> sss6 = sss5 * sss5
> sss14 = sss13 * sss13
>
> と2つをForループで回すと足し算した4.0秒ではなく
> 1.6秒となり、それぞれを回した時よりもなぜか速くなる結果が得られました。
>
> 何度か試したみたのですがやはり速くなってしまいます。
>
> 一体これはなぜなのでしょうか?
>
> fmul unroll のワードで検索をかけてみたのですが
> 分かりやすい解説ページが見つかりませんでした。

いやアンロールによる最適化の問題以前に、二つまとめればそりゃ早くなります。
ループって言うのは、条件判定とジャンプの組み合わせな訳で、毎ループそれぞれに時間がかかります。
一つのループ内で二つ計算すれば、ループの負担は単純に考えても半分になるわけです。
引用返信 編集キー/
■83203 / inTopicNo.10)  Re[7]: 32と64ビットプログラムの速度差
□投稿者/ なちゃ (179回)-(2017/03/12(Sun) 12:15:07)

> いやアンロールによる最適化の問題以前に、二つまとめればそりゃ早くなります。
> ループって言うのは、条件判定とジャンプの組み合わせな訳で、毎ループそれぞれに時間がかかります。
> 一つのループ内で二つ計算すれば、ループの負担は単純に考えても半分になるわけです。

で、これを単一処理であっても1ループにつき複数処理に意図的に変えるのがアンロールによる最適化です(別に元が単一処理には処理に限りませんか)。
引用返信 編集キー/
■83205 / inTopicNo.11)  Re[8]: 32と64ビットプログラムの速度差
□投稿者/ 拓殖 (6回)-(2017/03/12(Sun) 12:38:02)
> 一つのループ内で二つ計算すれば、ループの負担は単純に考えても半分になるわけです。

まったくコレが理解できないのですが

例えば、
s = 5 * 5
の計算が10^-12秒かかるとします。
これを10^12回繰り返すと1秒かかります。
それでは
s1 = 5 * 5
s2 = 5 * 5
s3 = 5 * 5
の計算を10^12回繰り返すと3秒になりませんか?

これがなぜか0.3333秒になったらおかしくないですか?


引用返信 編集キー/
■83206 / inTopicNo.12)  Re[9]: 32と64ビットプログラムの速度差
□投稿者/ なちゃ (180回)-(2017/03/12(Sun) 13:47:49)
おっと、読み違えてました、足して1.6秒ですね。
なら別の理由ですね。
そもそも計算方法が変わるような最適化がされることもあるかもしれませんし、演算ユニットが並列動作するようになったとか、他の演算命令をうまく使えたとかいろいろ可能性はありそうです。

引用返信 編集キー/
■83207 / inTopicNo.13)  Re[10]: 32と64ビットプログラムの速度差
□投稿者/ 拓殖 (7回)-(2017/03/12(Sun) 14:59:53)
そうでしたか、
forループの計算コストのもとめかたを教えてください
 
引用返信 編集キー/
■83210 / inTopicNo.14)  Re[11]: 32と64ビットプログラムの速度差
□投稿者/ 774RR (487回)-(2017/03/13(Mon) 09:41:40)
.NET において C# や VB のコンパイル結果は CIL (Common Intermediate Language) になる。
CIL は CLR (Common Language Runtime) によって更に翻訳されて native 機械語になる。
なので
・ CLR の性能によって実行速度が異なる
・ CLR のバージョンアップ等によって実行速度が異なる
・一度 native 機械語に翻訳済みな箇所でも(そこが実行時間の面で特に重要と判断したとき)
  CLR は、実行中であっても更に別な翻訳を与えなおすことができる(必ず「する」とは限らない)
などなどの理由により、

・ .NET 系言語の実行時間は事前に予期できない(同一コードを同一マシンで実行しても同じと限らない)
ってのがオイラなりの結論。

> 64ビット型で32と同じ速度にする方法があれば教えてください。
・ある特定の CLR 実装では***と書くと同じになる
・また別の CLR 実装では@@@と書くと同じになる
・ Windows Update 等で CLR がいつバージョンアップするかはわからない
という理由により「無い」ないしは「考えるだけ無駄」と言う結論になりそう。

特定 CPU を熟知したプログラマが技巧の限りを尽くしてその CPU の最高性能を出す、
ような目的には .NET 系言語は向かない。

普通のプログラマが普通にコード書いて普通に実行する場合、
そういう普通のプログラマよりは CLR のほうが CPU を良く知っているのでお任せすればよい。
それで CPU 性能の 100% を引き出せなくても開発効率のほうを優先するってのが .NET 的発想。

引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ