Cuda 数学与 C++ 数学

Cuda math vs C++ math

我在 CPU 上使用 C++ 和在 GPU 上使用 CUDA 实现了相同的算法。在这个算法中,我必须在数值上求解一个积分,因为没有解析答案。我必须集成的函数是一个奇怪的曲线多项式,最后有一个 exp 函数。

在 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 来加速医学物理算法,这些差异不是很好,因为我必须证明其中一个输出比另一个输出“更真实”,这显然可能是灾难性的患者。

差异来自函数本身吗?否则,我认为它可能来自 a_i 因素的 memcopy 或我获取它们的方式。

编辑:“完成”代码

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

的值

您正在使用 CUDA API 中不太准确的 exp() 实现。

基本上您可以在设备上使用三个版本的 exp() :

  • exp(),越准确越好
  • expf(),即单精度"equivalent"
  • __expf(),这是前一个的内在版本,而且不太准确

您可以在 CUDA 文档的 Mathematical Functions Appendix 中阅读有关数学函数的不同实现的更多信息,包括双精度、单精度和内部版本:

D.2. Intrinsic Functions

The functions from this section can only be used in device code.

Among these functions are the less accurate, but faster versions of some of the functions of Standard Functions .They have the same name prefixed with __ (such as __sinf(x)). They are faster as they map to fewer native instructions.

在同一页中,您会看到您删除的编译器选项只是阻止每个函数被其固有版本替换。当您明确使用 exp() 的固有版本时,删除此标志对您没有任何改变:

The compiler has an option (-use_fast_math) that forces each function in Table 8 to compile to its intrinsic counterpart.