2012-10-16 1 views
5

浮動小数点数と整数の間で変換を行う際に発生する可能性のあるエラーについては知っていますが、性能についてはどうですか(精度の問題は無視してください)。浮動小数点数の変換とパフォーマンス

(例えばfloat(例えばfloatdouble)浮動小数点型の異なる点/整数型の組み合わせをフローティングに、すなわち、Iは、演算の種類が異なるオペランドに対してn進演算を行う場合、一般的に、苦しむ、パフォーマンスを行い、 int)?すべてのオペランドを同じ型に保つなどの経験則がありますか?

P .:私は式テンプレートライブラリを作成しており、異なる算術型の値を含むベクトルに対してバイナリ演算を許可するかどうかを知りたいと思っています。

+1

はい、異種間の変換には費用がかかります。私は私の中期から帰ってくるまでに他の人がいなければ、詳細な答えを出すかもしれません。 – Mysticial

+0

浮動小数点演算は基本2算術の点では自明ではないので、コンパイラはヘルパー関数を発行することが多く(libgccが必要な理由を参照)、パフォーマンスに重大な影響を与えることがあります。 –

+0

問題は、あなたのプログラムは、異なるタイプのオペランドに対してn-ary演算をしないことです。それは、例えば、 C99の6.3.1。通常は同じタイプの引数を使用してn-ary演算が実行されます(例外はいくつかありますが、浮動小数点型は含まれません)。 –

答えて

5

私は、ハードウェアで変換が発生する可能性があるため、この質問に対する回答はターゲットアーキテクチャによって異なると思われます。例えば、int型とフロートの間にいくつかの相互変換が発生し、次のコードを、考えてみましょう。私はデフォルト設定で(私はUbuntuの、x86でよ)++グラムでこれをコンパイルしようとした、と分解し、GDBを使用

int main (int argc, char** argv) 
{ 
    int precoarced = 35; 
    // precoarced gets forced to float 
    float result = 0.5 + precoarced; 

    // and now we force it back to int 
    return (int)result; 

    // I wonder what the disassembly looks like in different environments? 
} 

0x00000000004004b4 <+0>: push %rbp 
    0x00000000004004b5 <+1>: mov %rsp,%rbp 
    0x00000000004004b8 <+4>: mov %edi,-0x14(%rbp) 
    0x00000000004004bb <+7>: mov %rsi,-0x20(%rbp) 
    0x00000000004004bf <+11>: movl $0x23,-0x8(%rbp) 
    0x00000000004004c6 <+18>: cvtsi2sdl -0x8(%rbp),%xmm0 
    0x00000000004004cb <+23>: movsd 0x10d(%rip),%xmm1  # 0x4005e0 
    0x00000000004004d3 <+31>: addsd %xmm1,%xmm0 
    0x00000000004004d7 <+35>: unpcklpd %xmm0,%xmm0 
    0x00000000004004db <+39>: cvtpd2ps %xmm0,%xmm0 
    0x00000000004004df <+43>: movss %xmm0,-0x4(%rbp) 
    0x00000000004004e4 <+48>: movss -0x4(%rbp),%xmm0 
    0x00000000004004e9 <+53>: cvttss2si %xmm0,%eax 
    0x00000000004004ed <+57>: pop %rbp 
    0x00000000004004ee <+58>: retq 

cvt接頭辞付きニーモニックの説明に注意してください。これらは変換の指示です。そのため、この場合、ハードウェアでの変換はいくつかの命令で行われています。したがって、これらの命令のコストはどれくらいのサイクルになるかによって、かなり高速になる可能性があります。しかし、やはり異なるアーキテクチャー(または別のコンパイラー)がストーリーを変える可能性があります。

編集:面白いことに、誤って0.5fの代わりに0.5を指定してしまったため、そこに追加の変換があります。それがcvtpd2psオペレーションがそこにある理由です。

編集:x86は長い間(80年代以降)FPをサポートしていたので、x86をターゲットとしたC++コンパイラは一般的にハードウェアを使用します(コンパイラが時代遅れでない限り)。これを指摘してくれたHot Licksに感謝します。

+0

コンパイラはコンパイル時に変換を実行するのに十分スマートであったかもしれませんが、それはそうではありませんでした... – user1095108

+0

@ user1095108確かに。これはあまりにも私を驚かせることはありません。私はデフォルトの設定であった。フロートを文字通りのようにすることは、典型的な「実用的な」ユースケースではありません。また、コンパイラの実装者は、非常に注意しなければならないので、おそらくfloat関連の最適化を恐れているでしょう。たとえば、加算の可換性(A + B = B + A)が浮動加算の最適化の有効な基礎になると考えるかもしれませんが、fpの不正確さのためにそうではありません。 FPアルゴリズムの精度を著しく損なう可能性があります。 – WeirdlyCheezy

+0

変換命令は、元の8087コプロセッサ以降、1つの形式または別の形式で存在しています。したがって、事実上、浮動小数点ハードウェアを持つすべてのシステムはハードウェアで変換されます。 –

2

ほとんどのマシンでは、浮動小数点ハードウェアの機能を利用して浮動小数点と整数の間の変換がかなり高速です。

しかし、ドキュメンテーションの目的でのみリテラルを「正しい」形式で表現するためには、もちろん努力する必要があります。また、明示的なキャストも使用しても問題ありません。

2

通常、いくつかのパフォーマンスの低下がありますが、他のものに比べて無視できます。これは、積分レジスタと浮動小数点レジスタ間のデータマイグレーション、およびその他の考えられるABIの問題によるものです。

このような質問に対する回答は、常に同じです。疑っている? ベンチマークです。パフォーマンスは理論的にはほとんど予測できません。

+2

私は親指のルールについて尋ねたことを忘れないでください。私はベンチルールを知っています。 – user1095108

関連する問題