2011-09-17 42 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。因此,即使在進行乘法運算(其結果將以單精度下溢到零)之前,7.82e-43的操作數也只會包含大約9個非零位,這本身可能已成問題。所以你可能也想看看產生這些微小數字的任何上游計算。

如果這些小數字是數學表達式中的中間項,將該表達式重寫爲不涉及微小中間體的數學等價數值將是解決該問題的一種方法。或者你可以通過兩個冪的因子來縮放一些操作數(以免由於縮放而導致額外的舍入)。例如,縮放2^24 = 16777216.

最後,您可以將部分計算切換爲雙精度。要做到這一點,簡單介紹類型的臨時變量雙,執行對他們的計算,然後將其轉換的最終結果返回給浮動:

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

在統計中我們經常與最終被非常可能性工作小數字和標準技術是使用日誌的一切。然後在對數標度上乘法只是加法。所有中間數字都存儲爲日誌。事實上,它可能需要一些習慣 - 但是,即使在進行相對適中的計算時,替代方案通常也會失敗。在這7個顯著數字默認BTW採用雙打和打印R(爲了我的方便!):

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