2011-09-17 9 views
1

Geforce GTX 580(Fermi)でCUDA 4.0を使用しています。私は7.721155e-43という小さな数字を持っています。 7.721155e-43 * 7.721155e-43を計算したいと言います。CUDA、float precision

私の経験から、私はそれがまっすぐにできないことを示しました。私に提案をお願いしますか?倍精度を使用する必要がありますか?どうやって?

+4

私はあなたには、いくつかのことで、すべての計算をスケールアップすることができない限り、あなたは、このために倍精度に行く必要があると思います適切な要因? –

答えて

5

通常のIEEE単精度最小値の大きさは約1.18e-38ですが、最小正規化は約1.40e-45になります。 consequeceとして、大きさ7.82e-43のオペランドは、約9個の非ゼロビットしか含まず、乗算(その結果は単精度でゼロにアンダフローします)に到達する前でもそれ自体が既に問題になっている可能性があります。したがって、これらの小さな数値を生成するアップストリーム計算を調べることもできます。

これらの小さな数値が数学的表現の中間語である場合、その式を小さな中間体を伴わない数学的に同等のものに書き換えることは、問題に取り組む一つの方法です。または、2の累乗であるファクタによっていくつかのオペランドをスケーリングすることができます(スケーリングによる余分な丸めが発生しないように)。たとえば、2^24 = 16777216でスケールします。

最後に、計算の一部を倍精度に切り替えることができます。これを行うには、単にdouble型の一時変数を導入し、それらに計算を実行し、floatに戻って最終的な結果を変換するには:統計で

float r, f = 7.721155e-43f; 
double d, t; 

d = (double)f; // explicit cast is not necessary, since converting to wider type 
t = d * d; 
[... more intermediate computation, leaving result in 't' ...] 
r = (float)t; // since conversion is to narrower type, cast will avoid warnings 
0

を私たちはしばしば非常にになってしまうの尤度と仕事をしなければなりません少数であり、標準的な手法はすべてのログを使用することです。そして、対数スケールでの乗算は単なる加算である。すべての中間番号はログとして保存されます。実際には少し慣れているかもしれませんが、比較的控えめな計算をしても、代わりに失敗することがよくあります。 R(!私の便宜上)ところで、デフォルトではダブル、版画7つの有効数字を使用して:

> 7.721155e-43 * 7.721155e-43 
[1] 5.961623e-85 
> exp(log(7.721155e-43) + log(7.721155e-43)) 
[1] 5.961623e-85