2016-12-15 144 views
1

我在CPU上使用C++和使用CUDA的GPU上實現了相同的算法。在這個算法中,我必須用數字來求解積分,因爲它沒有分析答案。我必須整合的函數是一個奇怪的曲線多項式,最後還有一個exp函數。Cuda數學與C++數學

在C++

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

在CUDA

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*__expf(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

輸出:

CPU:dose_output = 0.00165546

GPU:dose_output = 0.00142779

我認爲,math.h的函數exp和CUDA的函數__expf不是計算同樣的事情。我試圖刪除--use_fast_math編譯器標誌,認爲它是原因,但似乎這兩個實現差異大約20%。

我正在使用CUDA來加速醫學物理算法,這些差異並不是很好,因爲我必須證明其中一個輸出比另一個更「真實」,對患者來說顯然可能是災難性的。

區別來自函數本身嗎?否則,我認爲它可能來自於因素的備忘錄或我獲取它們的方式。

編輯: 「完整的」 代碼

float a0 = 5.9991e-04; 
float a1 = -1.4694e-02; 
float a2 = 1.1588; 
float a3 = 4.5675e-01; 
float a4 = -3.8617e-03; 
float a5 = 3.2066e-03; 
float a6 = 4.7050e-01; 

float integral = 0.0; 

float r_int = 5.0; 
float step = 0.1/200; 

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

cout << "Integral=" << integral << endl; 

我建議在GPU和CPU上運行此部分兩者。 來自Carleton's seed database的值

+0

評論是不適用於擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/130831/discussion-on-question-by-feynstein-cuda-math-vs-c-math)。 –

回答

3

您正在使用CUDA API中較不準確的exp()實現。

基本上你可以在裝置上使用EXP的三個版本():

  • EXP()時,更準確的一個
  • expf(),它是一個單精度 「等效」
  • __expf(),它是與前一個的固有版本和較不準確的

可以進一步瞭解的數學函數,包括雙精度,單precisio不同實現n和內部版本,在CUDA文檔的Mathematical Functions Appendix中:

D.2。固有功能

本節中的功能只能用於設備代碼。

其中,這些功能是標準函數的一些功能 的準確性較低但速度更快的版本。它們的前綴爲__(例如__sinf它們更快,因爲它們映射到 更少的本地指令。

在同一頁面中,您將讀取您剛移除的編譯器選項,以防止每個函數被其內在版本所取代。當你明確地使用EXP()的固有版本,移除該標誌對你沒有任何變化:

編譯器有一個選項(-use_fast_math),強制每個函數 表8編譯到其內在對應。