Single型は、単精度浮動小数点型(32ビット) という説明の基本型ですが、皆さん実際どれくらいの頻度で使っているのでしょうか?
僕はほとんどをDouble型で済ませちゃうので使う機会が少ないのですが。
Single型をよく使うと言う人は、どのような用途で使うのかを書いていただければ幸いですかね。雑談として。
Single型の使用頻度。
Single型の使用頻度。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
型の話題で盛り上がってますな!
String型に関しては、クラスモジュール化をして、仕様をオープンにできるようにする予定なので、こちらに関しては少々お待ちください。
Single型ですが、私の場合はほとんど使わないですね。使うとしたら、DirectXなどの外部モジュールのデータで指定があるときくらいでしょうか。
実際問題、処理速度に関してはFPUに投げているので、SingleもDoubleもあまり変わりません。内部的に倍精度で計算しなければならないところなどもありますので、もしかしたら、Double型のほうがちょっと早いって可能性もあるのかも(ここらへん、どなたかベンチマーク頼みますm(__)m)!?
String型に関しては、クラスモジュール化をして、仕様をオープンにできるようにする予定なので、こちらに関しては少々お待ちください。
Single型ですが、私の場合はほとんど使わないですね。使うとしたら、DirectXなどの外部モジュールのデータで指定があるときくらいでしょうか。
実際問題、処理速度に関してはFPUに投げているので、SingleもDoubleもあまり変わりません。内部的に倍精度で計算しなければならないところなどもありますので、もしかしたら、Double型のほうがちょっと早いって可能性もあるのかも(ここらへん、どなたかベンチマーク頼みますm(__)m)!?
僕はほとんどの処理を Single 型で済ませています。何故かというと、昔からの慣習で、というか癖です。
現在のメモリは dual channel 技術で多ワード転送が可能ですが、ちょっと昔は 64-bit の転送のコストは結構高かったこともありました。
精度を多少無駄にしても転送速度を上げたいこともあったのです(浮動小数点計算のまわりでは特に)。
キャッシュが乏しかった頃は転送にかかるコストも馬鹿になりませんでしたからね。
今ではそういうことも無いとわかっていつつも、つい、ね。悪しき慣習ってやつですな。
でも必ずしも悪というわけでは無いんです。(一応自己弁護)
Intel は 「必要でないならば倍精度型 (Double) ではなく単精度型 (Single) を積極的に利用すべし」という旨のことをどこかで言っていた記憶があります。(どこだったかな…)
他ならぬ Intel が提示する指針ですので、これに従う価値はあるとおもいます。(説得力薄)
>> 山本さん
> 内部的に倍精度で計算しなければならないところなどもありますので、もしかしたら、Double型のほうがちょっと早いって可能性もあるのかも
まじっすか!?それは初耳です。僕はてっきり、内部では全部拡張倍精度 (80-bit) で処理されているものだと思い込んでいました。
この辺、ちょっくら調査しておいた方がよさそうかも。
現在のメモリは dual channel 技術で多ワード転送が可能ですが、ちょっと昔は 64-bit の転送のコストは結構高かったこともありました。
精度を多少無駄にしても転送速度を上げたいこともあったのです(浮動小数点計算のまわりでは特に)。
キャッシュが乏しかった頃は転送にかかるコストも馬鹿になりませんでしたからね。
今ではそういうことも無いとわかっていつつも、つい、ね。悪しき慣習ってやつですな。
でも必ずしも悪というわけでは無いんです。(一応自己弁護)
Intel は 「必要でないならば倍精度型 (Double) ではなく単精度型 (Single) を積極的に利用すべし」という旨のことをどこかで言っていた記憶があります。(どこだったかな…)
他ならぬ Intel が提示する指針ですので、これに従う価値はあるとおもいます。(説得力薄)
>> 山本さん
> 内部的に倍精度で計算しなければならないところなどもありますので、もしかしたら、Double型のほうがちょっと早いって可能性もあるのかも
まじっすか!?それは初耳です。僕はてっきり、内部では全部拡張倍精度 (80-bit) で処理されているものだと思い込んでいました。
この辺、ちょっくら調査しておいた方がよさそうかも。
私がCを学んだときには既にdouble型で十分と言われてきたので,私はABでもDoubleばかり使っています。
他力本願ですが,SingleかDoubleかで迷うよりもコンパイラの最適化が進むことによる高速化の方を期待すればいいやと言う考えです。
想像で話をしても仕方が無いので検索して
http://www.google.co.jp/search?q=C+double+float
最初の方に見つかったこのページに計測するコードがあったのでABに持ってきてみました。
他力本願ですが,SingleかDoubleかで迷うよりもコンパイラの最適化が進むことによる高速化の方を期待すればいいやと言う考えです。
想像で話をしても仕方が無いので検索して
http://www.google.co.jp/search?q=C+double+float
最初の方に見つかったこのページに計測するコードがあったのでABに持ってきてみました。
すみませんオオポカをやらかしました。それでも見たい人はどうぞ。 [ここをクリックすると内容が表示されます]
http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.4.4.html
私のところではこのような結果でした。
ふと思ってr += 0.1をr += Sin(0.1)にしてみました。
実行させるとなかなか終わりそうに無かったのでループの回数を100000 - 1にしましたが,次のような結果でした。
そう言えばCも数学関数は皆doubleを引数に取るから型変換に時間がかかるという話を聞いたことがあります。
(今ではfloat版関数も用意されましたが,PCの性能向上で結局常にdoubleを使って問題ありませんと言うのが現在の状況です)
ABの数学関数もDouble版しかありませんから、同じ状況なのでしょう。
ようするに速度を求めるときには,単純な数値計算だけならSingleを使い,数学関数を多用するならDoubleを使えということではないでしょうか。
ちなみにSinとその中で呼ばれている_Support_tanのSingle版(Double/CDblをSingle/CSngに置き換えたもの)を作ってみましたが、次のような結果です。
回数を増やすと差も少しずつ広がりましたし誤差ではないようです。
コード: 全て選択
Declare Function timeGetTime Lib "winmm" () As DWord
Declare Function timeBeginPeriod Lib "winmm" (uPeriod As DWord) As Long
Declare Function timeEndPeriod Lib "winmm" (uPeriod As DWord) As Long
timeBeginPeriod(1)
Dim time[ELM(3)] As DWord
time[0] = timeGetTime()
SingleLoop()
time[1] = timeGetTime()
DoubleLoop()
time[2] = timeGetTime()
timeEndPeriod(1)
Print "Single:"; time[1] - time[0]
Print "Double:"; time[2] - time[1]
Sub SingleLoop()
Dim i As Long
Dim r = 0.0 As Single
For i = 0 To 10000000 - 1
r += 0.1
Next
Print "r = "; r
End Sub
Sub DoubleLoop()
Dim i As Double
Dim r = 0.0 As Single
For i = 0 To 10000000 - 1
r += 0.1
Next
Print "r = "; r
End Sub
あれ?Doubleが遅いですね、困りました。Single: 329
Double: 831
ふと思ってr += 0.1をr += Sin(0.1)にしてみました。
実行させるとなかなか終わりそうに無かったのでループの回数を100000 - 1にしましたが,次のような結果でした。
よし,これならDoubleに軍配が上がりました。Single: 217
Double: 182
そう言えばCも数学関数は皆doubleを引数に取るから型変換に時間がかかるという話を聞いたことがあります。
(今ではfloat版関数も用意されましたが,PCの性能向上で結局常にdoubleを使って問題ありませんと言うのが現在の状況です)
ABの数学関数もDouble版しかありませんから、同じ状況なのでしょう。
ようするに速度を求めるときには,単純な数値計算だけならSingleを使い,数学関数を多用するならDoubleを使えということではないでしょうか。
ちなみにSinとその中で呼ばれている_Support_tanのSingle版(Double/CDblをSingle/CSngに置き換えたもの)を作ってみましたが、次のような結果です。
だいぶ拮抗しましたがほんの少しDoubleが早いです。Single: 217
Double: 203
回数を増やすと差も少しずつ広がりましたし誤差ではないようです。
最後に編集したユーザー イグトランス [ 2006年5月08日(月) 07:27 ], 累計 1 回
イグトランスさん、コピペ後の修正箇所が間違っていますよ。
DoubleLoop() ではカウンタが Double 型になって、演算オペランド r は Single 型のままです。そりゃあ Single が勝ちますよ。
というか Sin() の勝負では Double 型が勝っちゃってますから、本来は Double 型の方が圧倒的に速い証拠ですね。
もう一つ。Sin() は引数が暗黙的に Double 型なので、公正を期する意味で次のように変えた方が良いと思います。
もしくは
# ごめんなさい、いま Linux から投稿しているのでこのサンプルをすぐには試せません。
それから、先程の「どこだったかな…」探していたら見つけました。
ftp://download.intel.co.jp/jp/developer ... inal_i.pdf
↑ これの浮動小数点に関するページ (2-54) です。
コンパイラの最適化を大前提としている点が、ちとイタイ。
DoubleLoop() ではカウンタが Double 型になって、演算オペランド r は Single 型のままです。そりゃあ Single が勝ちますよ。
というか Sin() の勝負では Double 型が勝っちゃってますから、本来は Double 型の方が圧倒的に速い証拠ですね。
もう一つ。Sin() は引数が暗黙的に Double 型なので、公正を期する意味で次のように変えた方が良いと思います。
コード: 全て選択
r += Sin(r)
コード: 全て選択
r += Sin(0.1 As Single) ' 適切な型にキャスト
それから、先程の「どこだったかな…」探していたら見つけました。
ftp://download.intel.co.jp/jp/developer ... inal_i.pdf
↑ これの浮動小数点に関するページ (2-54) です。
コンパイラの最適化を大前提としている点が、ちとイタイ。
自分もtakさんと同様に、精度を気にする必要の無い場合は、Single型で処理を行っています。
昔からの習性で、メモリー使用量が気になるからです。
他の人にプログラムを公開する必要が無い場合は、整数(固定小数点)で処理します。
例えば、
小数点2位までの精度で十分な場合は、0.01 を 1として計算
この時 1 は 100 と表現します。
昔のCPUは、この方法で数百倍高速化出来たけど・・・
今は引き継ぎしやすい表現を心がけています。
Double型の性能について
十分にチューニングを行った(SSEや並列処理を行う)ソフトウェアでは、
Single型が早いと思います。
現状のActiveBasicに限れば、データを設定する時の変換処理で
Single型の方が若干不利になっている為、Doubleを使用した方が
性能が出ていると思われます。
takさんが質問していた件について
①全部拡張倍精度 (80-bit) で処理?
32ビット版では、FPUで処理を行うので、各々の計算自体は80bit精度
しかし、計算結果はSingle(32bit)またはDouble(64bit)に丸めて保存。
(64bit版は不明)
②「必要でないならば倍精度型 (Double) ではなく単精度型 (Single) を積極的に利用すべし」
たぶんSSEの事だと思います。
Doubleは1命令で2演算、Singleだと1命令で4演算可能になります。
精度を必要としない場合は、Singleで計算すると最大2倍早くなる可能性があるので、推奨していると思われます。
昔からの習性で、メモリー使用量が気になるからです。
他の人にプログラムを公開する必要が無い場合は、整数(固定小数点)で処理します。
例えば、
小数点2位までの精度で十分な場合は、0.01 を 1として計算
この時 1 は 100 と表現します。
昔のCPUは、この方法で数百倍高速化出来たけど・・・
今は引き継ぎしやすい表現を心がけています。
Double型の性能について
十分にチューニングを行った(SSEや並列処理を行う)ソフトウェアでは、
Single型が早いと思います。
現状のActiveBasicに限れば、データを設定する時の変換処理で
Single型の方が若干不利になっている為、Doubleを使用した方が
性能が出ていると思われます。
takさんが質問していた件について
①全部拡張倍精度 (80-bit) で処理?
32ビット版では、FPUで処理を行うので、各々の計算自体は80bit精度
しかし、計算結果はSingle(32bit)またはDouble(64bit)に丸めて保存。
(64bit版は不明)
②「必要でないならば倍精度型 (Double) ではなく単精度型 (Single) を積極的に利用すべし」
たぶんSSEの事だと思います。
Doubleは1命令で2演算、Singleだと1命令で4演算可能になります。
精度を必要としない場合は、Singleで計算すると最大2倍早くなる可能性があるので、推奨していると思われます。
コードを直して計りなおしました。
r = 1087937
r = 999999.999838975
Single: 332
Double: 475
Long : 119
r += 0.1を10,000,000回行った結果です。
おまけにLong版を付けてみました。
r = 3.14176007475135
Single: 408
Double: 348
こちらは次の2行を2,000,000回行った結果です。
r += 0.1
r += Sin(r)
r = 1087937
r = 999999.999838975
Single: 332
Double: 475
Long : 119
r += 0.1を10,000,000回行った結果です。
おまけにLong版を付けてみました。
[ここをクリックすると内容が表示されます]
r = 3.1417601108551コード: 全て選択
Sub LongLoop()
Dim i As Long
Dim r = 1 As Long
For i = 0 To 10000000 - 1
r += 1
Next
Print "r = "; r / 10.0
End Sub
r = 3.14176007475135
Single: 408
Double: 348
こちらは次の2行を2,000,000回行った結果です。
r += 0.1
r += Sin(r)