2016-12-15 140 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编译到其内在对应。